[hamradio-commits] [wsjtx] 03/07: Imported Upstream version 1.5.0

Iain R. Learmonth irl at moszumanska.debian.org
Sun Oct 18 17:53:45 UTC 2015


This is an automated email from the git hooks/post-receive script.

irl pushed a commit to branch master
in repository wsjtx.

commit d63dd8d081a6fcd0715cd13f26df59fb831769d2
Author: Iain R. Learmonth <irl at debian.org>
Date:   Sun Oct 18 18:51:00 2015 +0100

    Imported Upstream version 1.5.0
---
 .gitignore                                         |    2 +
 AUTHORS                                            |    4 +
 AudioDevice.cpp                                    |   23 +
 AudioDevice.hpp                                    |   98 +
 BUGS                                               |   14 +
 Bands.cpp                                          |  196 +
 Bands.hpp                                          |   58 +
 CMake/Modules/FindFFTW3.cmake                      |   93 +
 CMake/Modules/FindGitSubversion.cmake              |   75 +
 CMake/Modules/Findhamlib.cmake                     |   59 +
 CMake/Modules/LibFindMacros.cmake                  |  112 +
 CMake/Modules/NSIS.template.in                     | 1056 ++++++
 CMake/Modules/QtAxMacros.cmake                     |   36 +
 CMake/VersionCompute.cmake                         |   11 +
 CMake/cmake_uninstall.cmake.in                     |   22 +
 CMake/download_html_manual.cmake                   |   16 +
 CMake/download_kvasd.cmake                         |   43 +
 CMake/getsvn.cmake                                 |   54 +
 CMakeCPackOptions.cmake.in                         |  280 ++
 CMakeLists.txt                                     | 1245 ++++++
 COPYING                                            |  151 +
 CandidateKeyFilter.cpp                             |   70 +
 CandidateKeyFilter.hpp                             |   36 +
 Configuration.cpp                                  | 2423 ++++++++++++
 Configuration.hpp                                  |  219 ++
 Configuration.ui                                   | 2248 +++++++++++
 DXLabSuiteCommanderTransceiver.cpp                 |  398 ++
 DXLabSuiteCommanderTransceiver.hpp                 |   57 +
 Darwin/Info.plist.in                               |   10 +
 .../KVASD-installer.xcodeproj/project.pbxproj      |  306 ++
 .../project.xcworkspace/contents.xcworkspacedata   |    7 +
 Darwin/KVASD-installer/KVASD-installer/Credits.rtf |   30 +
 .../AppIcon.appiconset/Contents.json               |   68 +
 .../AppIcon.appiconset/icon_128x128.png            |  Bin 0 -> 10762 bytes
 .../AppIcon.appiconset/icon_128x128 at 2x.png         |  Bin 0 -> 28347 bytes
 .../AppIcon.appiconset/icon_16x16.png              |  Bin 0 -> 1084 bytes
 .../AppIcon.appiconset/icon_16x16 at 2x.png           |  Bin 0 -> 2448 bytes
 .../AppIcon.appiconset/icon_256x256.png            |  Bin 0 -> 28347 bytes
 .../AppIcon.appiconset/icon_256x256 at 2x.png         |  Bin 0 -> 71830 bytes
 .../AppIcon.appiconset/icon_32x32.png              |  Bin 0 -> 2448 bytes
 .../AppIcon.appiconset/icon_32x32 at 2x.png           |  Bin 0 -> 5864 bytes
 .../AppIcon.appiconset/icon_512x512.png            |  Bin 0 -> 71830 bytes
 .../AppIcon.appiconset/icon_512x512 at 2x.png         |  Bin 0 -> 181288 bytes
 .../KVASD-installer/InfoPlist.strings              |    2 +
 .../KVASD-installer/KVASD-installer-Info.plist     |   51 +
 .../KVASD-installer/KVASD-installer-Prefix.pch     |    9 +
 .../KVASD-installer/KVASD-installer/MainMenu.xib   |  290 ++
 .../KVASD-installer/WSJTAppDelegate.applescript    |  357 ++
 Darwin/KVASD-installer/KVASD-installer/main.m      |   17 +
 Darwin/Mac-wsjtx-startup.sh                        |   16 +
 Darwin/ReadMe.txt                                  |  106 +
 Darwin/developer read me.txt                       |   91 +
 Darwin/postflight.sh.in                            |    3 +
 Darwin/postupgrade.sh.in                           |    2 +
 Darwin/sysctl.conf                                 |    5 +
 Darwin/wsjtx_DMG.DS_Store                          |  Bin 0 -> 15364 bytes
 Detector.cpp                                       |  134 +
 Detector.hpp                                       |   58 +
 EmulateSplitTransceiver.cpp                        |  116 +
 EmulateSplitTransceiver.hpp                        |   53 +
 ForeignKeyDelegate.cpp                             |   32 +
 ForeignKeyDelegate.hpp                             |   35 +
 FrequencyItemDelegate.cpp                          |   36 +
 FrequencyItemDelegate.hpp                          |   53 +
 FrequencyLineEdit.cpp                              |   40 +
 FrequencyLineEdit.hpp                              |   45 +
 FrequencyList.cpp                                  |  357 ++
 FrequencyList.hpp                                  |   59 +
 GetUserId.cpp                                      |   75 +
 GetUserId.hpp                                      |    8 +
 HRDTransceiver.cpp                                 | 1002 +++++
 HRDTransceiver.hpp                                 |  179 +
 HamlibTransceiver.cpp                              |  874 +++++
 HamlibTransceiver.hpp                              |   70 +
 INSTALL                                            |  369 ++
 LICENSE_WHEATLEY.TXT                               |   30 -
 LiveFrequencyValidator.cpp                         |   92 +
 LiveFrequencyValidator.hpp                         |   52 +
 MessageAggregator.cpp                              |  509 +++
 MessageClient.cpp                                  |  342 ++
 MessageClient.hpp                                  |   89 +
 MessageServer.cpp                                  |  376 ++
 MessageServer.hpp                                  |   81 +
 Modulator.cpp                                      |  296 ++
 Modulator.hpp                                      |   84 +
 NEWS                                               | 1285 +++++++
 NetworkMessage.cpp                                 |  100 +
 NetworkMessage.hpp                                 |  290 ++
 NetworkServerLookup.cpp                            |   86 +
 NetworkServerLookup.hpp                            |   38 +
 OmniRigTransceiver.cpp                             |  620 +++
 OmniRigTransceiver.hpp                             |   71 +
 PSKReporter.h                                      |  127 -
 Palettes/Banana.pal                                |    9 +
 Palettes/Blue1.pal                                 |    9 +
 Palettes/Blue2.pal                                 |    9 +
 Palettes/Blue3.pal                                 |    9 +
 Palettes/Brown.pal                                 |    9 +
 Palettes/Cyan1.pal                                 |    9 +
 Palettes/Cyan2.pal                                 |    9 +
 Palettes/Cyan3.pal                                 |    9 +
 Palettes/Default.pal                               |    9 +
 Palettes/Digipan.pal                               |    9 +
 Palettes/Fldigi.pal                                |    9 +
 Palettes/Gmfsk.pal                                 |    9 +
 Palettes/Gray1.pal                                 |    9 +
 Palettes/Gray2.pal                                 |    9 +
 Palettes/Green1.pal                                |    9 +
 Palettes/Green2.pal                                |    9 +
 Palettes/Jungle.pal                                |    9 +
 Palettes/Linrad.pal                                |    9 +
 Palettes/Negative.pal                              |    9 +
 Palettes/Orange.pal                                |    9 +
 Palettes/Pink.pal                                  |    9 +
 Palettes/Rainbow.pal                               |    9 +
 Palettes/Scope.pal                                 |    9 +
 Palettes/Sunburst.pal                              |    9 +
 Palettes/VK4BDJ.pal                                |    9 +
 Palettes/YL2KF.pal                                 |    9 +
 Palettes/Yellow1.pal                               |    9 +
 Palettes/Yellow2.pal                               |    9 +
 Palettes/ZL1FZ.pal                                 |    9 +
 PollingTransceiver.cpp                             |  181 +
 PollingTransceiver.hpp                             |   75 +
 QtSupport.iss                                      |   10 -
 README                                             |   46 +
 Radio.cpp                                          |  107 +
 Radio.hpp                                          |   54 +
 SettingsGroup.hpp                                  |   34 +
 StationList.cpp                                    |  550 +++
 StationList.hpp                                    |  102 +
 THANKS                                             |   58 +
 TraceFile.cpp                                      |  118 +
 TraceFile.hpp                                      |   23 +
 Transceiver.cpp                                    |   51 +
 Transceiver.hpp                                    |  169 +
 TransceiverBase.cpp                                |  295 ++
 TransceiverBase.hpp                                |  149 +
 TransceiverFactory.cpp                             |  219 ++
 TransceiverFactory.hpp                             |  186 +
 Versions.cmake                                     |    6 +
 WFPalette.cpp                                      |  330 ++
 WFPalette.hpp                                      |   55 +
 about.cpp                                          |   31 +-
 about.h                                            |   16 +-
 about.ui                                           |   74 +-
 afmhot.dat                                         |  257 --
 artwork/DragNDrop Background.svg                   |  143 +
 artwork/README                                     |   30 +
 artwork/installer_logo.svg                         | 1126 ++++++
 artwork/make_graphics.sh                           |   72 +
 artwork/wsjt_globe_1024x1024.svg                   |  577 +++
 artwork/wsjt_globe_128x128.svg                     |  839 ++++
 artwork/wsjtx_globe_1024x1024.svg                  |  602 +++
 astro.cpp                                          |  212 ++
 astro.h                                            |   51 +
 astro.ui                                           |  103 +
 blue.dat                                           |  256 --
 commons.h                                          |   13 +-
 contrib/Commander TCPIP Mesages.pdf                |  Bin 0 -> 234145 bytes
 .../Darwin/KVASD-installer.app/Contents/Info.plist |   67 +
 .../Contents/MacOS/KVASD-installer                 |  Bin 0 -> 19368 bytes
 .../Darwin/KVASD-installer.app/Contents/PkgInfo    |    1 +
 .../Contents/Resources/AppIcon.icns                |  Bin 0 -> 587063 bytes
 .../Contents/Resources/Credits.rtf                 |   30 +
 .../Contents/Resources/InfoPlist.strings           |  Bin 0 -> 92 bytes
 .../Contents/Resources/MainMenu.nib                |  Bin 0 -> 18027 bytes
 .../Contents/Resources/WSJTAppDelegate.scpt        |  Bin 0 -> 56286 bytes
 contrib/NSIS/AccessControl.zip                     |  Bin 0 -> 42009 bytes
 contrib/NSIS/Md5dll.zip                            |  Bin 0 -> 22087 bytes
 contrib/NSIS/NsRichEdit.zip                        |  Bin 0 -> 29672 bytes
 contrib/NSIS/Plugins-i386-ansi/AccessControl.dll   |  Bin 0 -> 13312 bytes
 contrib/NSIS/Plugins-i386-ansi/md5dll.dll          |  Bin 0 -> 6656 bytes
 contrib/NSIS/Plugins-i386-ansi/nsRichEdit.dll      |  Bin 0 -> 5632 bytes
 .../NSIS/Plugins-i386-unicode/AccessControl.dll    |  Bin 0 -> 15360 bytes
 contrib/NSIS/Plugins-i386-unicode/md5dll.dll       |  Bin 0 -> 6656 bytes
 contrib/NSIS/Plugins-i386-unicode/nsRichEdit.dll   |  Bin 0 -> 5632 bytes
 contrib/NSIS/README                                |    9 +
 cty.dat                                            | 1325 +++++++
 debian/CMakeLists.txt                              |   39 +
 debian/changelog.Debian.in                         |    6 +
 debian/copyright.in                                |   10 +
 decodedtext.cpp                                    |  166 +
 decodedtext.h                                      |   91 +
 devsetup.cpp                                       |  595 ---
 devsetup.h                                         |  120 -
 devsetup.ui                                        | 2599 -------------
 displaytext.cpp                                    |  170 +-
 displaytext.h                                      |   27 +-
 doc/CMakeLists.txt                                 |  163 +
 doc/README                                         |   51 +
 doc/common/communication.adoc                      |   17 +
 doc/common/license.adoc                            |   15 +
 doc/common/links.adoc                              |  111 +
 doc/theme/wsjt/wsjt.css                            |  546 +++
 doc/user_guide/acknowledgements.adoc               |   24 +
 doc/user_guide/compiling.adoc                      |   20 +
 doc/user_guide/config-details.adoc                 |    4 +
 doc/user_guide/controls-functions-center.adoc      |   32 +
 doc/user_guide/controls-functions-left.adoc        |   41 +
 doc/user_guide/controls-functions-main-window.adoc |   51 +
 doc/user_guide/controls-functions-menus.adoc       |   46 +
 doc/user_guide/controls-functions-messages.adoc    |   55 +
 doc/user_guide/controls-functions-status-bar.adoc  |   17 +
 doc/user_guide/controls-functions-wide-graph.adoc  |   49 +
 doc/user_guide/coop-prgrms.adoc                    |    5 +
 doc/user_guide/cooperating-programs.adoc           |   23 +
 doc/user_guide/faq.adoc                            |   83 +
 doc/user_guide/font-sizes.adoc                     |   15 +
 doc/user_guide/images/130610_2343-wav-80.png       |  Bin 0 -> 188086 bytes
 doc/user_guide/images/MacAppMenu.png               |  Bin 0 -> 56114 bytes
 doc/user_guide/images/RadioTab.png                 |  Bin 0 -> 26363 bytes
 doc/user_guide/images/band-settings.png            |  Bin 0 -> 19043 bytes
 doc/user_guide/images/colors.png                   |  Bin 0 -> 11609 bytes
 doc/user_guide/images/decode-menu.png              |  Bin 0 -> 2214 bytes
 doc/user_guide/images/decodes.png                  |  Bin 0 -> 21505 bytes
 doc/user_guide/images/file-menu.png                |  Bin 0 -> 6812 bytes
 doc/user_guide/images/freemsg.png                  |  Bin 0 -> 7146 bytes
 doc/user_guide/images/help-menu.png                |  Bin 0 -> 4938 bytes
 doc/user_guide/images/jtalert.png                  |  Bin 0 -> 51183 bytes
 doc/user_guide/images/keyboard-shortcuts.png       |  Bin 0 -> 64736 bytes
 doc/user_guide/images/log-qso.png                  |  Bin 0 -> 14418 bytes
 doc/user_guide/images/main-ui-1.5.png              |  Bin 0 -> 349543 bytes
 doc/user_guide/images/main-ui-controls.png         |  Bin 0 -> 2270 bytes
 doc/user_guide/images/misc-controls-center.png     |  Bin 0 -> 3609 bytes
 doc/user_guide/images/misc-main-ui.png             |  Bin 0 -> 6586 bytes
 doc/user_guide/images/mode-menu.png                |  Bin 0 -> 2651 bytes
 doc/user_guide/images/new-msg-box.png              |  Bin 0 -> 5679 bytes
 doc/user_guide/images/psk-reporter.png             |  Bin 0 -> 544952 bytes
 doc/user_guide/images/r3666-config-screen-80.png   |  Bin 0 -> 26312 bytes
 doc/user_guide/images/r3666-main-ui-80.png         |  Bin 0 -> 212244 bytes
 doc/user_guide/images/r4148-freq-ui.png            |  Bin 0 -> 25860 bytes
 doc/user_guide/images/r4148-txmac-ui.png           |  Bin 0 -> 7156 bytes
 doc/user_guide/images/reporting.png                |  Bin 0 -> 15971 bytes
 doc/user_guide/images/save-menu.png                |  Bin 0 -> 2668 bytes
 doc/user_guide/images/settings-audio.png           |  Bin 0 -> 13349 bytes
 doc/user_guide/images/settings-ui.png              |  Bin 0 -> 23744 bytes
 doc/user_guide/images/setup-menu.png               |  Bin 0 -> 16034 bytes
 doc/user_guide/images/special-mouse-commands.png   |  Bin 0 -> 54116 bytes
 doc/user_guide/images/status-bar-a.png             |  Bin 0 -> 1940 bytes
 doc/user_guide/images/traditional-msg-box.png      |  Bin 0 -> 6103 bytes
 doc/user_guide/images/tx-macros.png                |  Bin 0 -> 12200 bytes
 doc/user_guide/images/view-menu.png                |  Bin 0 -> 2414 bytes
 doc/user_guide/images/wide-graph-controls.png      |  Bin 0 -> 4361 bytes
 doc/user_guide/install-from-source.adoc            |   29 +
 doc/user_guide/install-linux.adoc                  |   79 +
 doc/user_guide/install-mac.adoc                    |   23 +
 doc/user_guide/install-windows.adoc                |   28 +
 doc/user_guide/introduction.adoc                   |   43 +
 doc/user_guide/jt65-jt9-differences.adoc           |   41 +
 doc/user_guide/jt65-protocol.adoc                  |   51 +
 doc/user_guide/jt9-protocol.adoc                   |   20 +
 doc/user_guide/logging.adoc                        |   40 +
 doc/user_guide/make-qso.adoc                       |  166 +
 doc/user_guide/platform-dependencies.adoc          |   48 +
 doc/user_guide/rig-config-adat.adoc                |  104 +
 doc/user_guide/rig-config-alinco.adoc              |  104 +
 doc/user_guide/rig-config-aor.adoc                 |  103 +
 doc/user_guide/rig-config-drake.adoc               |  104 +
 doc/user_guide/rig-config-elecraft.adoc            |  104 +
 doc/user_guide/rig-config-flexrad.adoc             |  104 +
 doc/user_guide/rig-config-icom.adoc                |  104 +
 doc/user_guide/rig-config-kenwood.adoc             |  104 +
 doc/user_guide/rig-config-main.adoc                |   33 +
 doc/user_guide/rig-config-softrock.adoc            |  104 +
 doc/user_guide/rig-config-template.adoc            |   60 +
 doc/user_guide/rig-config-tentec.adoc              |  104 +
 doc/user_guide/rig-config-yaesu.adoc               |  102 +
 doc/user_guide/settings-audio.adoc                 |   20 +
 doc/user_guide/settings-colors.adoc                |    8 +
 doc/user_guide/settings-frequencies.adoc           |   39 +
 doc/user_guide/settings-general.adoc               |   14 +
 doc/user_guide/settings-radio.adoc                 |   75 +
 doc/user_guide/settings-reporting.adoc             |   16 +
 doc/user_guide/settings-txmacros.adoc              |   16 +
 doc/user_guide/system-requirements.adoc            |   12 +
 doc/user_guide/transceiver-setup.adoc              |   56 +
 doc/user_guide/tutorial-example1.adoc              |   96 +
 doc/user_guide/tutorial-example2.adoc              |  117 +
 doc/user_guide/tutorial-main-window.adoc           |   16 +
 doc/user_guide/tutorial-wide-graph-settings.adoc   |   14 +
 doc/user_guide/tx-rx.adoc                          |   80 +
 doc/user_guide/utilities.adoc                      |   59 +
 doc/user_guide/wsjtx-main.adoc                     |  205 +
 doc/wsjtx.conf.in                                  |    8 +
 ffft.f                                             |   69 -
 fftw3.f                                            |   64 -
 getdev.cpp                                         |  259 --
 getfile.cpp                                        |   11 +-
 getfile.h                                          |    1 +
 icons/Darwin/DragNDrop Background.png              |  Bin 0 -> 32276 bytes
 icons/Darwin/wsjt.iconset/icon_128x128.png         |  Bin 0 -> 10762 bytes
 icons/Darwin/wsjt.iconset/icon_128x128 at 2x.png      |  Bin 0 -> 28347 bytes
 icons/Darwin/wsjt.iconset/icon_16x16.png           |  Bin 0 -> 1084 bytes
 icons/Darwin/wsjt.iconset/icon_16x16 at 2x.png        |  Bin 0 -> 2448 bytes
 icons/Darwin/wsjt.iconset/icon_256x256.png         |  Bin 0 -> 28347 bytes
 icons/Darwin/wsjt.iconset/icon_256x256 at 2x.png      |  Bin 0 -> 71830 bytes
 icons/Darwin/wsjt.iconset/icon_32x32.png           |  Bin 0 -> 2448 bytes
 icons/Darwin/wsjt.iconset/icon_32x32 at 2x.png        |  Bin 0 -> 5864 bytes
 icons/Darwin/wsjt.iconset/icon_512x512.png         |  Bin 0 -> 71830 bytes
 icons/Darwin/wsjt.iconset/icon_512x512 at 2x.png      |  Bin 0 -> 181288 bytes
 icons/Darwin/wsjtx.iconset/icon_128x128.png        |  Bin 0 -> 17659 bytes
 icons/Darwin/wsjtx.iconset/icon_128x128 at 2x.png     |  Bin 0 -> 43423 bytes
 icons/Darwin/wsjtx.iconset/icon_16x16.png          |  Bin 0 -> 1084 bytes
 icons/Darwin/wsjtx.iconset/icon_16x16 at 2x.png       |  Bin 0 -> 2448 bytes
 icons/Darwin/wsjtx.iconset/icon_256x256.png        |  Bin 0 -> 43423 bytes
 icons/Darwin/wsjtx.iconset/icon_256x256 at 2x.png     |  Bin 0 -> 104868 bytes
 icons/Darwin/wsjtx.iconset/icon_32x32.png          |  Bin 0 -> 2448 bytes
 icons/Darwin/wsjtx.iconset/icon_32x32 at 2x.png       |  Bin 0 -> 5864 bytes
 icons/Darwin/wsjtx.iconset/icon_512x512.png        |  Bin 0 -> 104868 bytes
 icons/Darwin/wsjtx.iconset/icon_512x512 at 2x.png     |  Bin 0 -> 251432 bytes
 icons/README                                       |    3 +
 icons/Unix/wsjtx_icon.png                          |  Bin 0 -> 17659 bytes
 icons/windows-icons/installer_logo.bmp             |  Bin 0 -> 25818 bytes
 icons/windows-icons/wsjtx.ico                      |  Bin 0 -> 550870 bytes
 in.dat                                             |   16 -
 killbyname.cpp                                     |  568 +--
 lib/Makefile.MinGW                                 |   76 +-
 lib/{Makefile.MinGW => Makefile.MinGW.qt4}         |  239 +-
 lib/{Makefile.MinGW => Makefile.jtsdk}             |   60 +-
 lib/Makefile.linux                                 |   67 +-
 lib/afc65b.f90                                     |  118 +-
 lib/afc9.f90                                       |  137 +-
 lib/all_fft.out                                    | 2069 ++++++++++
 lib/astro.f90                                      |  108 +
 lib/astro0.f90                                     |   82 +
 lib/astrosub.f90                                   |   14 +
 lib/baddata.f90                                    |   27 +
 lib/chkfft.f90                                     |  162 +
 lib/chkfft.txt                                     |  124 +
 lib/chkfft2.f90                                    |  187 +
 lib/chkfft3.f90                                    |  176 +
 lib/chkmsg.f90                                     |    6 +-
 lib/chkss2.f90                                     |   12 +-
 lib/coord.f90                                      |   41 +
 lib/cutil.c                                        |   93 -
 lib/dcoord.f90                                     |   40 +
 lib/{decoder.f90 => decjt9.f90}                    |  319 +-
 lib/decode65a.f90                                  |    4 +-
 lib/decode65b.f90                                  |    4 +-
 lib/decoder.f90                                    |  269 +-
 lib/demod64a.f90                                   |   21 +-
 lib/determ.f90                                     |   32 +
 lib/dot.f90                                        |   11 +
 lib/downsam9.f90                                   |  153 +-
 lib/encode4.f90                                    |   20 -
 lib/extract.F90                                    |  223 +-
 lib/fano232.f90                                    |    4 +-
 lib/fchisq.f90                                     |    2 +-
 lib/fftw3.f03                                      | 1246 ++++++
 lib/fftw3mod.f90                                   |    4 +
 lib/fil4.f90                                       |   49 +
 lib/filbig.f90                                     |   79 +-
 lib/fillcom.f90                                    |   28 +-
 lib/flat1.f90                                      |   29 +-
 lib/flat4.f90                                      |   50 +
 lib/fmtmsg.f90                                     |   21 +
 lib/four2a.f90                                     |  163 +-
 lib/g1                                             |    4 +
 lib/g1.bat                                         |    4 +
 lib/g2.bat                                         |    4 +
 lib/g3.bat                                         |    4 +
 lib/g4.bat                                         |    3 +
 lib/gen24.f90                                      |   86 -
 lib/gen65.f90                                      |    7 +-
 lib/genjt9.f90                                     |    7 +-
 lib/geocentric.f90                                 |   17 +
 lib/getpfx1.f90                                    |   11 +-
 lib/gran.c                                         |   56 +-
 lib/init_rs.c                                      |    2 +-
 lib/jt65a.f90                                      |   28 +-
 lib/jt65code.f90                                   |  104 +
 lib/jt9.f90                                        |  344 +-
 lib/jt9a.f90                                       |  143 +-
 lib/jt9c.f90                                       |   10 +-
 lib/jt9code.f90                                    |   70 +-
 lib/{decode9.f90 => jt9fano.f90}                   |   20 +-
 lib/jt9sim.f90                                     |   46 +-
 lib/libhamlib.dll.a                                |  Bin 177492 -> 0 bytes
 lib/moon2.f90                                      |  166 +
 lib/moondop.f90                                    |   72 +
 lib/nfft.dat                                       | 2067 ++++++++++
 lib/nfft.out                                       | 2067 ++++++++++
 lib/options.f90                                    |  337 ++
 lib/packmsg.f90                                    |   76 +-
 lib/polfit.f90                                     |   72 +
 lib/prog_args.f90                                  |    4 +
 lib/smo.f90                                        |   23 +
 lib/softsym.f90                                    |   14 +-
 lib/sort.f90                                       |   87 +-
 lib/ss.bat                                         |    2 +-
 lib/ssort.f90                                      |  264 --
 lib/stdmsg.f90                                     |    5 +-
 lib/sun.f90                                        |   88 +
 lib/symspec.f90                                    |   48 +-
 lib/symspec2.f90                                   |   10 +-
 lib/symspec65.f90                                  |   21 +-
 lib/sync9.f90                                      |    7 -
 lib/timefft.f90                                    |  139 +
 lib/timefft_opts.f90                               |   48 +
 lib/timer.f90                                      |  312 +-
 lib/timeval.h                                      |   74 -
 lib/tm2.f90                                        |   14 +
 lib/tmoonsub.c                                     |  518 +++
 lib/toxyz.f90                                      |   25 +
 lib/twkfreq.f90                                    |    8 +-
 lib/unpackcall.f90                                 |   24 +-
 lib/unpackmsg.f90                                  |    1 +
 lib/usleep.c                                       |    8 +
 lib/wavhdr.f90                                     |   38 +
 lib/wisdom.c                                       |   13 +
 lib/wisdom1.bat                                    |    2 +
 lib/wrapkarn.c                                     |  140 +-
 logbook/adif.cpp                                   |  206 +
 logbook/adif.h                                     |   50 +
 logbook/countriesworked.cpp                        |   42 +
 logbook/countriesworked.h                          |   29 +
 logbook/countrydat.cpp                             |  136 +
 logbook/countrydat.h                               |   35 +
 logbook/logbook.cpp                                |   99 +
 logbook/logbook.h                                  |   39 +
 logqso.cpp                                         |  323 +-
 logqso.h                                           |  113 +-
 logqso.ui                                          |    3 -
 main.cpp                                           |  253 +-
 mainwindow.cpp                                     | 3997 +++++++++++---------
 mainwindow.h                                       |  576 +--
 mainwindow.ui                                      | 3185 ++++++++--------
 manpages/CMakeLists.txt                            |   81 +
 manpages/man1/jt65code.1.txt                       |  104 +
 manpages/man1/rigctl-wsjtx.1.txt                   |   29 +
 manpages/man1/rigctld-wsjtx.1.txt                  |   29 +
 manpages/man1/wsjtx.1.txt                          |  120 +
 message_aggregator.qrc.in                          |    5 +
 meterwidget.cpp                                    |    2 +
 meterwidget.h                                      |    1 +
 mouse_commands.txt                                 |    1 -
 paInputDevice.c                                    |   56 -
 pa_get_device_info.c                               |  172 -
 pimpl_h.hpp                                        |   29 +
 pimpl_impl.hpp                                     |   28 +
 plotter.cpp                                        |  280 +-
 plotter.h                                          |   67 +-
 prefixes.txt                                       |   27 +
 psk_reporter.cpp                                   |   59 +-
 psk_reporter.h                                     |   25 +-
 qmake_only/svnversion.h                            |    4 +
 qss/default.qss                                    |    5 +
 qt_helpers.cpp                                     |   37 +
 qt_helpers.hpp                                     |   82 +
 revision_utils.cpp                                 |   83 +
 revision_utils.hpp                                 |   10 +
 rigclass.cpp                                       |  324 --
 rigclass.h                                         |   98 -
 samples/130418_1742.wav                            |  Bin 0 -> 1440044 bytes
 samples/130610_2343.wav                            |  Bin 0 -> 1440044 bytes
 shortcuts.txt                                      |   54 +-
 signalmeter.cpp                                    |    2 +
 signalmeter.h                                      |    4 +-
 sleep.h                                            |    1 +
 soundin.cpp                                        |  316 +-
 soundin.h                                          |   72 +-
 soundout.cpp                                       |  385 +-
 soundout.h                                         |   83 +-
 ss.bat                                             |    2 +-
 wf_palette_design_dialog.ui                        |   87 +
 widegraph.cpp                                      |  269 +-
 widegraph.h                                        |  185 +-
 widegraph.ui                                       |  800 ++--
 wsjt.ico                                           |  Bin 1078 -> 0 bytes
 wsjtx.desktop                                      |   11 +
 wsjtx.iss                                          |   29 +-
 wsjtx.pro                                          |  145 +-
 wsjtx.qrc.in                                       |    5 +
 wsjtx.rc                                           |    2 +-
 wsjtx_config.h.in                                  |   33 +
 wsjtx_update.iss                                   |   18 +
 477 files changed, 51213 insertions(+), 12847 deletions(-)

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..9db84e7
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+TAGS
+tags
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..7dae8af
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,4 @@
+Joe Taylor, K1JT <k1jt at arrl.net>
+
+See  also about.cpp  or "Help->About  WSJT-X" in  the application  for
+details of other contributions.
diff --git a/AudioDevice.cpp b/AudioDevice.cpp
new file mode 100644
index 0000000..a557aa6
--- /dev/null
+++ b/AudioDevice.cpp
@@ -0,0 +1,23 @@
+#include "AudioDevice.hpp"
+
+#include <QMetaType>
+
+namespace
+{
+  struct init
+  {
+    init ()
+    {
+      qRegisterMetaType<AudioDevice::Channel> ("AudioDevice::Channel");
+    }
+  } static_initializer;
+}
+
+bool AudioDevice::initialize (OpenMode mode, Channel channel)
+{
+  m_channel = channel;
+
+  // open and ensure we are unbuffered if possible
+  return QIODevice::open (mode | QIODevice::Unbuffered);
+}
+
diff --git a/AudioDevice.hpp b/AudioDevice.hpp
new file mode 100644
index 0000000..c435468
--- /dev/null
+++ b/AudioDevice.hpp
@@ -0,0 +1,98 @@
+#ifndef AUDIODEVICE_HPP__
+#define AUDIODEVICE_HPP__
+
+#include <QIODevice>
+
+class QDataStream;
+
+//
+// abstract base class for audio devices
+//
+class AudioDevice : public QIODevice
+{
+public:
+  enum Channel {Mono, Left, Right, Both}; // these are mapped to combobox index so don't change
+
+  static char const * toString (Channel c)
+  {
+    return Mono == c ? "Mono" : Left == c ? "Left" : Right == c ? "Right" : "Both";
+  }
+
+  static Channel fromString (QString const& str)
+  {
+    QString s (str.toCaseFolded ().trimmed ().toLatin1 ());
+    return "both" == s ? Both : "right" == s ? Right : "left" == s ? Left : Mono;
+  }
+
+  bool initialize (OpenMode mode, Channel channel);
+
+  bool isSequential () const override {return true;}
+
+  size_t bytesPerFrame () const {return sizeof (qint16) * (Mono == m_channel ? 1 : 2);}
+
+  Channel channel () const {return m_channel;}
+
+protected:
+  AudioDevice (QObject * parent = 0)
+    : QIODevice (parent)
+  {
+  }
+
+  void store (char const * source, size_t numFrames, qint16 * dest)
+  {
+    qint16 const * begin (reinterpret_cast<qint16 const *> (source));
+    for ( qint16 const * i = begin; i != begin + numFrames * (bytesPerFrame () / sizeof (qint16)); i += bytesPerFrame () / sizeof (qint16))
+      {
+	switch (m_channel)
+	  {
+	  case Mono:
+	    *dest++ = *i;
+	    break;
+
+	  case Right:
+	    *dest++ = *(i + 1);
+	    break;
+
+	  case Both:		// should be able to happen but if it
+				// does we'll take left
+	    Q_ASSERT (Both == m_channel);
+	  case Left:
+	    *dest++ = *i;
+	    break;
+	  }
+      }
+  }
+
+  qint16 * load (qint16 const sample, qint16 * dest)
+  {
+    switch (m_channel)
+      {
+      case Mono:
+	*dest++ = sample;
+	break;
+
+      case Left:
+	*dest++ = sample;
+	*dest++ = 0;
+	break;
+
+      case Right:
+	*dest++ = 0;
+	*dest++ = sample;
+	break;
+
+      case Both:
+	*dest++ = sample;
+	*dest++ = sample;
+	break;
+      }
+    return dest;
+  }
+
+private:
+  Channel m_channel;
+};
+
+Q_DECLARE_METATYPE (AudioDevice::Channel);
+
+#endif
diff --git a/BUGS b/BUGS
new file mode 100644
index 0000000..dc0b767
--- /dev/null
+++ b/BUGS
@@ -0,0 +1,14 @@
+
+ __       __   ______      _____  ________      __    __ 
+|  \  _  |  \ /      \    |     \|        \    |  \  |  \
+| $$ / \ | $$|  $$$$$$\    \$$$$$ \$$$$$$$$    | $$  | $$
+| $$/  $\| $$| $$___\$$      | $$   | $$ ______ \$$\/  $$
+| $$  $$$\ $$ \$$    \  __   | $$   | $$|      \ >$$  $$ 
+| $$ $$\$$\$$ _\$$$$$$\|  \  | $$   | $$ \$$$$$$/  $$$$\ 
+| $$$$  \$$$$|  \__| $$| $$__| $$   | $$       |  $$ \$$\
+| $$$    \$$$ \$$    $$ \$$    $$   | $$       | $$  | $$
+ \$$      \$$  \$$$$$$   \$$$$$$     \$$        \$$   \$$
+                                                         
+                                                         
+                                                         
+There are some defects remaining in WSJT-X.
diff --git a/Bands.cpp b/Bands.cpp
new file mode 100644
index 0000000..747eb7f
--- /dev/null
+++ b/Bands.cpp
@@ -0,0 +1,196 @@
+#include "Bands.hpp"
+
+#include <algorithm>
+
+#include <QString>
+#include <QVariant>
+
+namespace
+{
+  // Local structure to hold a single ADIF band definition.
+  struct ADIF_band
+  {
+    char const * const name_;
+    Radio::Frequency lower_bound_;
+    Radio::Frequency upper_bound_;
+  };
+
+  // Table of ADIF band definitions as defined in the ADIF
+  // specification.
+  ADIF_band constexpr ADIF_bands[] = {
+    {"2190m", 	136000u, 	137000u},
+    {"630m", 	472000u, 	479000u},
+    {"560m", 	501000u, 	504000u},
+    {"160m", 	1800000u, 	2000000u},
+    {"80m", 	3500000u, 	4000000u},
+    {"60m", 	5102000u, 	5406500u},
+    {"40m", 	7000000u, 	7300000u},
+    {"30m", 	10000000u, 	10150000u},
+    {"20m", 	14000000u, 	14350000u},
+    {"17m", 	18068000u, 	18168000u},
+    {"15m", 	21000000u, 	21450000u},
+    {"12m", 	24890000u, 	24990000u},
+    {"10m", 	28000000u, 	29700000u},
+    {"6m", 	50000000u, 	54000000u},
+    {"4m", 	70000000u, 	71000000u},
+    {"2m", 	144000000u, 	148000000u},
+    {"1.25m", 	222000000u, 	225000000u},
+    {"70cm", 	420000000u, 	450000000u},
+    {"33cm", 	902000000u, 	928000000u},
+    {"23cm", 	1240000000u, 	1300000000u},
+    {"13cm", 	2300000000u, 	2450000000u},
+    {"9cm", 	3300000000u, 	3500000000u},
+    {"6cm", 	5650000000u, 	5925000000u},
+    {"3cm", 	10000000000u,	10500000000u},
+    {"1.25cm", 	24000000000u,	24250000000u},
+    {"6mm", 	47000000000u,	47200000000u},
+    {"4mm", 	75500000000u,	81000000000u},
+    {"2.5mm", 	119980000000u,	120020000000u},
+    {"2mm", 	142000000000u,	149000000000u},
+    {"1mm", 	241000000000u,	250000000000u},
+  };
+
+  auto constexpr out_of_band = "OOB";
+
+  int constexpr table_rows ()
+  {
+    return sizeof (ADIF_bands) / sizeof (ADIF_bands[0]);
+  }
+}
+
+Bands::Bands (QObject * parent)
+  : QAbstractTableModel {parent}
+{
+}
+
+QModelIndex Bands::find (QVariant const& v) const
+{
+  auto f = v.value<Radio::Frequency> ();
+  auto end_iter = ADIF_bands + table_rows ();
+  auto row_iter = std::find_if (ADIF_bands, end_iter, [f] (ADIF_band const& band) {
+      return band.lower_bound_ <= f && f <= band.upper_bound_;
+    });
+  if (row_iter != end_iter)
+    {
+      return index (row_iter - ADIF_bands, 0); // return the band row index
+    }
+
+  return QModelIndex {};
+}
+
+int Bands::rowCount (QModelIndex const& parent) const
+{
+  return parent.isValid () ? 0 : table_rows ();
+}
+
+int Bands::columnCount (QModelIndex const& parent) const
+{
+  return parent.isValid () ? 0 : 3;
+}
+
+Qt::ItemFlags Bands::flags (QModelIndex const& index) const
+{
+  return QAbstractTableModel::flags (index) | Qt::ItemIsDropEnabled;
+}
+
+QVariant Bands::data (QModelIndex const& index, int role) const
+{
+  QVariant item;
+
+  if (!index.isValid ())
+    {
+      // Hijack root for OOB string.
+      if (Qt::DisplayRole == role)
+        {
+          item = out_of_band;
+        }
+    }
+  else
+    {
+      auto row = index.row ();
+      auto column = index.column ();
+
+      if (row < table_rows ())
+        {
+          switch (role)
+            {
+            case Qt::ToolTipRole:
+            case Qt::AccessibleDescriptionRole:
+              switch (column)
+                {
+                case 0: item = tr ("Band name"); break;
+                case 1: item = tr ("Lower frequency limit"); break;
+                case 2: item = tr ("Upper frequency limit"); break;
+                }
+              break;
+
+            case SortRole:
+            case Qt::DisplayRole:
+            case Qt::EditRole:
+              switch (column)
+                {
+                case 0:
+                  if (SortRole == role)
+                    {
+                      // band name sorts by lower bound
+                      item = ADIF_bands[row].lower_bound_;
+                    }
+                  else
+                    {
+                      item = ADIF_bands[row].name_;
+                    }
+                  break;
+
+                case 1: item = ADIF_bands[row].lower_bound_; break;
+                case 2: item = ADIF_bands[row].upper_bound_; break;
+                }
+              break;
+
+            case Qt::AccessibleTextRole:
+              switch (column)
+                {
+                case 0: item = ADIF_bands[row].name_; break;
+                case 1: item = ADIF_bands[row].lower_bound_; break;
+                case 2: item = ADIF_bands[row].upper_bound_; break;
+                }
+              break;
+
+            case Qt::TextAlignmentRole:
+              switch (column)
+                {
+                case 0:
+                  item = Qt::AlignHCenter + Qt::AlignVCenter;
+                  break;
+
+                case 1:
+                case 2:
+                  item = Qt::AlignRight + Qt::AlignVCenter;
+                  break;
+                }
+              break;
+            }
+        }
+    }
+  return item;
+}
+
+QVariant Bands::headerData (int section, Qt::Orientation orientation, int role) const
+{
+  QVariant result;
+
+  if (Qt::DisplayRole == role && Qt::Horizontal == orientation)
+    {
+      switch (section)
+        {
+        case 0: result = tr ("Band"); break;
+        case 1: result = tr ("Lower Limit"); break;
+        case 2: result = tr ("Upper Limit"); break;
+        }
+    }
+  else
+    {
+      result = QAbstractTableModel::headerData (section, orientation, role);
+    }
+
+  return result;
+}
diff --git a/Bands.hpp b/Bands.hpp
new file mode 100644
index 0000000..41d3810
--- /dev/null
+++ b/Bands.hpp
@@ -0,0 +1,58 @@
+#ifndef BANDS_HPP__
+#define BANDS_HPP__
+
+#include <QAbstractTableModel>
+
+#include "Radio.hpp"
+
+//
+// Class Bands
+//
+//  Encapsulates information  about amateur radio bands  as defined by
+//  the  ADIF specification.  The model  is immutable.   The rows  are
+//  stored in asscending order of frequency.
+//
+// Responsibilities
+//
+//  Provides  a  well  known  band  name mapped  to  lower  and  upper
+//  frequency  limits.  Also  provides   a  convenience  operation  to
+//  determine the band details for  any given frequency, the result of
+//  which may be  invalid if the given frequency doesn't  lie within a
+//  recognised band.
+//
+// Collaborations
+//
+//  Implements the QAbstractTableModel interface as an immutable table
+//  where rows  are bands and  columns are band name,  lower frequency
+//  limit and, upper ferquency limit respectively.
+//
+class Bands final
+  : public QAbstractTableModel
+{
+public:
+  explicit Bands (QObject * parent = nullptr);
+
+  //
+  // Model API
+  //
+  QModelIndex find (QVariant const&) const; // find band Frequency is in
+
+  // Custom role for sorting.
+  static int constexpr SortRole = Qt::UserRole;
+
+  // Implement the QAbstractTableModel interface
+  int rowCount (QModelIndex const& parent = QModelIndex {}) const override;
+  int columnCount (QModelIndex const& parent = QModelIndex {}) const override;
+  Qt::ItemFlags flags (QModelIndex const& = QModelIndex {}) const override;
+  QVariant headerData (int section, Qt::Orientation, int = Qt::DisplayRole) const override;
+
+  // The value return for the Qt::DisplayRole role for the root of the
+  // model (invalid index) is a special string representing out of
+  // band.
+  //
+  // All columns return a number for the custom role SortRole, this
+  // number defines a strict frequency order for the rows.
+  QVariant data (QModelIndex const&, int role = Qt::DisplayRole) const override;
+};
+
+#endif
diff --git a/CMake/Modules/FindFFTW3.cmake b/CMake/Modules/FindFFTW3.cmake
new file mode 100644
index 0000000..97eff3e
--- /dev/null
+++ b/CMake/Modules/FindFFTW3.cmake
@@ -0,0 +1,93 @@
+# - Try to find FFTW3.
+# Usage: find_package(FFTW3 [COMPONENTS [single double long-double threads]])
+#
+# Variables used by this module:
+#  FFTW3_ROOT_DIR             - FFTW3 root directory
+# Variables defined by this module:
+#  FFTW3_FOUND                - system has FFTW3
+#  FFTW3_INCLUDE_DIR          - the FFTW3 include directory (cached)
+#  FFTW3_INCLUDE_DIRS         - the FFTW3 include directories
+#                               (identical to FFTW3_INCLUDE_DIR)
+#  FFTW3[FL]?_LIBRARY         - the FFTW3 library - double, single(F), 
+#                               long-double(L) precision (cached)
+#  FFTW3[FL]?_THREADS_LIBRARY - the threaded FFTW3 library - double, single(F), 
+#                               long-double(L) precision (cached)
+#  FFTW3_LIBRARIES            - list of all FFTW3 libraries found
+
+# Copyright (C) 2009-2010
+# ASTRON (Netherlands Institute for Radio Astronomy)
+# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
+#
+# This file is part of the LOFAR software suite.
+# The LOFAR software suite 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 3 of the License, or
+# (at your option) any later version.
+#
+# The LOFAR software suite 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 the LOFAR software suite. If not, see <http://www.gnu.org/licenses/>.
+#
+# $Id: FindFFTW3.cmake 15918 2010-06-25 11:12:42Z loose $
+
+# Use double precision by default.
+if (FFTW3_FIND_COMPONENTS MATCHES "^$")
+  set (_components double)
+else ()
+  set (_components ${FFTW3_FIND_COMPONENTS})
+endif ()
+
+# Loop over each component.
+set (_libraries)
+foreach (_comp ${_components})
+  if (_comp STREQUAL "single")
+    list (APPEND _libraries fftw3f)
+  elseif (_comp STREQUAL "double")
+    list (APPEND _libraries fftw3)
+  elseif (_comp STREQUAL "long-double")
+    list (APPEND _libraries fftw3l)
+  elseif (_comp STREQUAL "threads")
+    set (_use_threads ON)
+  else (_comp STREQUAL "single")
+    message (FATAL_ERROR "FindFFTW3: unknown component `${_comp}' specified. "
+      "Valid components are `single', `double', `long-double', and `threads'.")
+  endif (_comp STREQUAL "single")
+endforeach (_comp ${_components})
+
+# If using threads, we need to link against threaded libraries as well - except on Windows.
+if (NOT WIN32 AND _use_threads)
+  set (_thread_libs)
+  foreach (_lib ${_libraries})
+    list (APPEND _thread_libs ${_lib}_threads)
+  endforeach (_lib ${_libraries})
+  set (_libraries ${_thread_libs} ${_libraries})
+endif (NOT WIN32 AND _use_threads)
+
+# Keep a list of variable names that we need to pass on to
+# find_package_handle_standard_args().
+set (_check_list)
+
+# Search for all requested libraries.
+foreach (_lib ${_libraries})
+  string (TOUPPER ${_lib} _LIB)
+  find_library (${_LIB}_LIBRARY NAMES ${_lib} ${_lib}-3
+    HINTS ${FFTW3_ROOT_DIR} PATH_SUFFIXES lib)
+  mark_as_advanced (${_LIB}_LIBRARY)
+  list (APPEND FFTW3_LIBRARIES ${${_LIB}_LIBRARY})
+  list (APPEND _check_list ${_LIB}_LIBRARY)
+endforeach (_lib ${_libraries})
+
+# Search for the header file.
+find_path (FFTW3_INCLUDE_DIR fftw3.h 
+  HINTS ${FFTW3_ROOT_DIR} PATH_SUFFIXES include)
+mark_as_advanced (FFTW3_INCLUDE_DIR)
+list(APPEND _check_list FFTW3_INCLUDE_DIR)
+
+# Handle the QUIETLY and REQUIRED arguments and set FFTW_FOUND to TRUE if
+# all listed variables are TRUE
+include (FindPackageHandleStandardArgs)
+find_package_handle_standard_args (FFTW3 DEFAULT_MSG ${_check_list})
diff --git a/CMake/Modules/FindGitSubversion.cmake b/CMake/Modules/FindGitSubversion.cmake
new file mode 100644
index 0000000..c913c37
--- /dev/null
+++ b/CMake/Modules/FindGitSubversion.cmake
@@ -0,0 +1,75 @@
+# - Extract information from a git-svn working copy
+# The module defines the following variables:
+#
+# If the command line client executable is found two macros are defined:
+# GitSubversion_WC_INFO(<dir> <var-prefix>)
+# GitSubversion_WC_INFO extracts information of a subversion working copy at
+# a given location. This macro defines the following variables:
+#  <var-prefix>_WC_URL - url of the repository (at <dir>)
+#  <var-prefix>_WC_ROOT - root url of the repository
+#  <var-prefix>_WC_REVISION - current revision
+#  <var-prefix>_WC_LAST_CHANGED_AUTHOR - author of last commit
+#  <var-prefix>_WC_LAST_CHANGED_DATE - date of last commit
+#  <var-prefix>_WC_LAST_CHANGED_REV - revision of last commit
+#  <var-prefix>_WC_INFO - output of command `svn info <dir>'
+# Example usage:
+#  find_package(Subversion)
+#  if(SUBVERSION_FOUND)
+#    GitSubversion_WC_INFO(${PROJECT_SOURCE_DIR} Project)
+#    message("Current revision is ${Project_WC_REVISION}")
+#  endif()
+
+find_package (Git)
+
+if(GIT_FOUND)
+  # the git-svn commands should be executed with the C locale, otherwise
+  # the message (which are parsed) may be translated, Alex
+  set(_Subversion_SAVED_LC_ALL "$ENV{LC_ALL}")
+  set(ENV{LC_ALL} C)
+
+  # execute_process(COMMAND ${Subversion_SVN_EXECUTABLE} --version
+  #   OUTPUT_VARIABLE Subversion_VERSION_SVN
+  #   OUTPUT_STRIP_TRAILING_WHITESPACE)
+
+  # restore the previous LC_ALL
+  set(ENV{LC_ALL} ${_Subversion_SAVED_LC_ALL})
+
+  # string(REGEX REPLACE "^(.*\n)?svn, version ([.0-9]+).*"
+  #   "\\2" Subversion_VERSION_SVN "${Subversion_VERSION_SVN}")
+
+  macro(GitSubversion_WC_INFO dir prefix)
+    # the subversion commands should be executed with the C locale, otherwise
+    # the message (which are parsed) may be translated, Alex
+    set(_Subversion_SAVED_LC_ALL "$ENV{LC_ALL}")
+    set(ENV{LC_ALL} C)
+
+    execute_process(COMMAND ${GIT_EXECUTABLE} --git-dir=${dir}/.git --work-tree=${dir} svn info
+      OUTPUT_VARIABLE ${prefix}_WC_INFO
+      ERROR_VARIABLE Git_git_svn_info_error
+      RESULT_VARIABLE Git_git_svn_info_result
+      OUTPUT_STRIP_TRAILING_WHITESPACE)
+
+    if(NOT ${Git_git_svn_info_result} EQUAL 0)
+      message(SEND_ERROR "Command \"${GIT_EXECUTABLE} --git-dir=${dir}/.git --work-tree=${dir} svn info\" failed with output:\n${Git_git_svn_info_error}")
+    else()
+
+      string(REGEX REPLACE "^(.*\n)?URL: ([^\n]+).*"
+        "\\2" ${prefix}_WC_URL "${${prefix}_WC_INFO}")
+      string(REGEX REPLACE "^(.*\n)?Repository Root: ([^\n]+).*"
+        "\\2" ${prefix}_WC_ROOT "${${prefix}_WC_INFO}")
+      string(REGEX REPLACE "^(.*\n)?Revision: ([^\n]+).*"
+        "\\2" ${prefix}_WC_REVISION "${${prefix}_WC_INFO}")
+      string(REGEX REPLACE "^(.*\n)?Last Changed Author: ([^\n]+).*"
+        "\\2" ${prefix}_WC_LAST_CHANGED_AUTHOR "${${prefix}_WC_INFO}")
+      string(REGEX REPLACE "^(.*\n)?Last Changed Rev: ([^\n]+).*"
+        "\\2" ${prefix}_WC_LAST_CHANGED_REV "${${prefix}_WC_INFO}")
+      string(REGEX REPLACE "^(.*\n)?Last Changed Date: ([^\n]+).*"
+        "\\2" ${prefix}_WC_LAST_CHANGED_DATE "${${prefix}_WC_INFO}")
+    endif()
+
+    # restore the previous LC_ALL
+    set(ENV{LC_ALL} ${_Subversion_SAVED_LC_ALL})
+
+  endmacro()
+
+endif()
diff --git a/CMake/Modules/Findhamlib.cmake b/CMake/Modules/Findhamlib.cmake
new file mode 100644
index 0000000..abed74b
--- /dev/null
+++ b/CMake/Modules/Findhamlib.cmake
@@ -0,0 +1,59 @@
+# - Try to find hamlib
+# Once done, this will define:
+#
+#  hamlib_FOUND - system has Hamlib-2
+#  hamlib_INCLUDE_DIRS - the Hamlib-2 include directories
+#  hamlib_LIBRARIES - link these to use Hamlib-2
+#  hamlib_STATIC_FOUND - system has Hamlib-2 static archive
+#  hamlib_STATIC_LIBRARIES - link these to use Hamlib-2 static archive
+
+include (LibFindMacros)
+
+# pkg-config?
+find_path (__hamlib_pc_path NAMES hamlib.pc
+  PATH_SUFFIXES lib/pkgconfig
+)
+if (__hamlib_pc_path)
+  set (ENV{PKG_CONFIG_PATH} "${__hamlib_pc_path}" "$ENV{PKG_CONFIG_PATH}")
+  unset (__hamlib_pc_path CACHE)
+endif ()
+
+# Use pkg-config to get hints about paths, libs and, flags
+unset (__pkg_config_checked_hamlib CACHE)
+libfind_pkg_check_modules (PC_HAMLIB hamlib)
+
+if (NOT PC_HAMLIB_STATIC_LIBRARIES)
+  if (WIN32)
+    set (PC_HAMLIB_STATIC_LIBRARIES hamlib ws2_32)
+  else ()
+    set (PC_HAMLIB_STATIC_LIBRARIES hamlib m dl usb)
+  endif ()
+endif ()
+
+# The libraries
+libfind_library (hamlib hamlib)
+libfind_library (hamlib_STATIC libhamlib.a)
+
+find_path (hamlib_INCLUDE_DIR hamlib/rig.h)
+
+# Set the include dir variables and the libraries and let libfind_process do the rest
+set (hamlib_PROCESS_INCLUDES hamlib_INCLUDE_DIR)
+set (hamlib_PROCESS_LIBS hamlib_LIBRARY)
+libfind_process (hamlib)
+
+set (hamlib_STATIC_PROCESS_INCLUDES hamlib_STATIC_INCLUDE_DIR)
+set (hamlib_STATIC_PROCESS_LIBS hamlib_STATIC_LIBRARY PC_HAMLIB_STATIC_LIBRARIES)
+libfind_process (hamlib_STATIC)
+
+# make sure we return a full path for the library we return
+if (hamlib_FOUND)
+  list (REMOVE_ITEM hamlib_LIBRARIES hamlib)
+  if (hamlib_STATIC_LIBRARIES)
+    list (REMOVE_ITEM hamlib_STATIC_LIBRARIES hamlib)
+  endif ()
+endif ()
+
+# Handle the  QUIETLY and REQUIRED  arguments and set  HAMLIB_FOUND to
+# TRUE if all listed variables are TRUE
+include (FindPackageHandleStandardArgs)
+find_package_handle_standard_args (hamlib DEFAULT_MSG hamlib_INCLUDE_DIRS hamlib_LIBRARY hamlib_LIBRARIES)
diff --git a/CMake/Modules/LibFindMacros.cmake b/CMake/Modules/LibFindMacros.cmake
new file mode 100644
index 0000000..aa2143c
--- /dev/null
+++ b/CMake/Modules/LibFindMacros.cmake
@@ -0,0 +1,112 @@
+# Version 1.0 (2013-04-12)
+# Public Domain, originally written by Lasse Kärkkäinen <tronic at zi.fi>
+# Published at http://www.cmake.org/Wiki/CMake:How_To_Find_Libraries
+
+# If you improve the script, please modify the forementioned wiki page because
+# I no longer maintain my scripts (hosted as static files at zi.fi). Feel free
+# to remove this entire header if you use real version control instead.
+
+# Changelog:
+# 2013-04-12  Added version number (1.0) and this header, no other changes
+# 2009-10-08  Originally published
+
+
+# Works the same as find_package, but forwards the "REQUIRED" and "QUIET" arguments
+# used for the current package. For this to work, the first parameter must be the
+# prefix of the current package, then the prefix of the new package etc, which are
+# passed to find_package.
+macro (libfind_package PREFIX)
+  set (LIBFIND_PACKAGE_ARGS ${ARGN})
+  if (${PREFIX}_FIND_QUIETLY)
+    set (LIBFIND_PACKAGE_ARGS ${LIBFIND_PACKAGE_ARGS} QUIET)
+  endif (${PREFIX}_FIND_QUIETLY)
+  if (${PREFIX}_FIND_REQUIRED)
+    set (LIBFIND_PACKAGE_ARGS ${LIBFIND_PACKAGE_ARGS} REQUIRED)
+  endif (${PREFIX}_FIND_REQUIRED)
+  find_package(${LIBFIND_PACKAGE_ARGS})
+endmacro (libfind_package)
+
+# CMake developers made the UsePkgConfig system deprecated in the same release (2.6)
+# where they added pkg_check_modules. Consequently I need to support both in my scripts
+# to avoid those deprecated warnings. Here's a helper that does just that.
+# Works identically to pkg_check_modules, except that no checks are needed prior to use.
+macro (libfind_pkg_check_modules PREFIX PKGNAME)
+  if (${CMAKE_MAJOR_VERSION} EQUAL 2 AND ${CMAKE_MINOR_VERSION} EQUAL 4)
+    include(UsePkgConfig)
+    pkgconfig(${PKGNAME} ${PREFIX}_INCLUDE_DIRS ${PREFIX}_LIBRARY_DIRS ${PREFIX}_LDFLAGS ${PREFIX}_CFLAGS)
+  else (${CMAKE_MAJOR_VERSION} EQUAL 2 AND ${CMAKE_MINOR_VERSION} EQUAL 4)
+    find_package(PkgConfig)
+    if (PKG_CONFIG_FOUND)
+      pkg_check_modules(${PREFIX} ${PKGNAME})
+    endif (PKG_CONFIG_FOUND)
+  endif (${CMAKE_MAJOR_VERSION} EQUAL 2 AND ${CMAKE_MINOR_VERSION} EQUAL 4)
+endmacro (libfind_pkg_check_modules)
+
+# Do the final processing once the paths have been detected.
+# If include dirs are needed, ${PREFIX}_PROCESS_INCLUDES should be set to contain
+# all the variables, each of which contain one include directory.
+# Ditto for ${PREFIX}_PROCESS_LIBS and library files.
+# Will set ${PREFIX}_FOUND, ${PREFIX}_INCLUDE_DIRS and ${PREFIX}_LIBRARIES.
+# Also handles errors in case library detection was required, etc.
+macro (libfind_process PREFIX)
+  # Skip processing if already processed during this run
+  if (NOT ${PREFIX}_FOUND)
+    # Start with the assumption that the library was found
+    set (${PREFIX}_FOUND TRUE)
+
+    # Process all includes and set _FOUND to false if any are missing
+    foreach (i ${${PREFIX}_PROCESS_INCLUDES})
+      if (${i})
+        set (${PREFIX}_INCLUDE_DIRS ${${PREFIX}_INCLUDE_DIRS} ${${i}})
+        mark_as_advanced(${i})
+      else (${i})
+        set (${PREFIX}_FOUND FALSE)
+      endif (${i})
+    endforeach (i)
+
+    # Process all libraries and set _FOUND to false if any are missing
+    foreach (i ${${PREFIX}_PROCESS_LIBS})
+      if (${i})
+        set (${PREFIX}_LIBRARIES ${${PREFIX}_LIBRARIES} ${${i}})
+        mark_as_advanced(${i})
+      else (${i})
+        set (${PREFIX}_FOUND FALSE)
+      endif (${i})
+    endforeach (i)
+
+    # Print message and/or exit on fatal error
+    if (${PREFIX}_FOUND)
+      if (NOT ${PREFIX}_FIND_QUIETLY)
+        message (STATUS "Found ${PREFIX} ${${PREFIX}_VERSION}")
+      endif (NOT ${PREFIX}_FIND_QUIETLY)
+    else (${PREFIX}_FOUND)
+      if (${PREFIX}_FIND_REQUIRED)
+        foreach (i ${${PREFIX}_PROCESS_INCLUDES} ${${PREFIX}_PROCESS_LIBS})
+          message("${i}=${${i}}")
+        endforeach (i)
+        message (FATAL_ERROR "Required library ${PREFIX} NOT FOUND.\nInstall the library (dev version) and try again. If the library is already installed, use ccmake to set the missing variables manually.")
+      endif (${PREFIX}_FIND_REQUIRED)
+    endif (${PREFIX}_FOUND)
+  endif (NOT ${PREFIX}_FOUND)
+endmacro (libfind_process)
+
+macro(libfind_library PREFIX basename)
+  set(TMP "")
+  if(MSVC80)
+    set(TMP -vc80)
+  endif(MSVC80)
+  if(MSVC90)
+    set(TMP -vc90)
+  endif(MSVC90)
+  set(${PREFIX}_LIBNAMES ${basename}${TMP})
+  if(${ARGC} GREATER 2)
+    set(${PREFIX}_LIBNAMES ${basename}${TMP}-${ARGV2})
+    string(REGEX REPLACE "\\." "_" TMP ${${PREFIX}_LIBNAMES})
+    set(${PREFIX}_LIBNAMES ${${PREFIX}_LIBNAMES} ${TMP})
+  endif(${ARGC} GREATER 2)
+  find_library(${PREFIX}_LIBRARY
+    NAMES ${${PREFIX}_LIBNAMES}
+    PATHS ${${PREFIX}_PKGCONF_LIBRARY_DIRS}
+  )
+endmacro(libfind_library)
+
diff --git a/CMake/Modules/NSIS.template.in b/CMake/Modules/NSIS.template.in
new file mode 100644
index 0000000..9e171e2
--- /dev/null
+++ b/CMake/Modules/NSIS.template.in
@@ -0,0 +1,1056 @@
+; CPack install script designed for a nmake build
+
+;--------------------------------
+; You must define these values
+
+  !define VERSION "@CPACK_PACKAGE_VERSION@"
+  !define PATCH  "@CPACK_PACKAGE_VERSION_PATCH@"
+  !define INST_DIR "@CPACK_TEMPORARY_DIRECTORY@"
+
+;--------------------------------
+;Variables
+
+  Var MUI_TEMP
+  Var STARTMENU_FOLDER
+  Var SV_ALLUSERS
+  Var START_MENU
+  Var RB_DO_NOT_ADD_TO_PATH
+  Var DO_NOT_ADD_TO_PATH
+  Var RB_ADD_TO_PATH_ALL_USERS
+  Var ADD_TO_PATH_ALL_USERS
+  Var RB_ADD_TO_PATH_CURRENT_USER
+  Var ADD_TO_PATH_CURRENT_USER
+  Var CB_INSTALL_DESKTOP
+  Var INSTALL_DESKTOP
+  Var IS_DEFAULT_INSTALLDIR
+
+;--------------------------------
+;Include Modern UI
+
+  !include "MUI2.nsh"
+  !include "nsDialogs.nsh"
+
+;--------------------------------
+;Include Logic Lib and add a DirExists command
+
+  !include "LogicLib.nsh"
+;FileExists is already part of LogicLib, but returns true for directories as well as files
+  !macro _FileExists2 _a _b _t _f
+	!insertmacro _LOGICLIB_TEMP
+	StrCpy $_LOGICLIB_TEMP '0'
+	StrCmp `${_b}` `` +4 0 ;if path is not blank, continue to next check
+	IfFileExists `${_b}` `0` +3 ;if path exists, continue to next check (IfFileExists returns true if this is a directory)
+	IfFileExists `${_b}\*.*` +2 0 ;if path is not a directory, continue to confirm exists
+	StrCpy $_LOGICLIB_TEMP '1' ;file exists
+	;now we have a definitive value - the file exists or it does not
+	StrCmp $_LOGICLIB_TEMP '1' `${_t}` `${_f}`
+  !macroend
+  !undef FileExists
+  !define FileExists `'' FileExists2`
+  !macro _DirExists _a _b _t _f
+	!insertmacro _LOGICLIB_TEMP
+	StrCpy $_LOGICLIB_TEMP '0'	
+	StrCmp `${_b}` `` +3 0 ;if path is not blank, continue to next check
+	IfFileExists `${_b}\*.*` 0 +2 ;if directory exists, continue to confirm exists
+	StrCpy $_LOGICLIB_TEMP '1'
+	StrCmp $_LOGICLIB_TEMP '1' `${_t}` `${_f}`
+  !macroend
+  !define DirExists `'' DirExists`
+
+  ;Default installation folder
+  InstallDir "@CPACK_NSIS_INSTALL_ROOT@\@CPACK_PACKAGE_INSTALL_DIRECTORY@"
+
+;--------------------------------
+;General
+
+  ;Name and file
+  Name "@CPACK_NSIS_PACKAGE_NAME@"
+  OutFile "@CPACK_TOPLEVEL_DIRECTORY@/@CPACK_OUTPUT_FILE_NAME@"
+
+  ;Set compression
+  SetCompressor @CPACK_NSIS_COMPRESSOR@
+
+  ;Require administrator access
+  RequestExecutionLevel admin
+
+ at CPACK_NSIS_DEFINES@
+ at CPACK_NSIS_EXTRA_DEFINES@
+
+  !include Sections.nsh
+
+;--- Component support macros: ---
+; The code for the add/remove functionality is from:
+;   http://nsis.sourceforge.net/Add/Remove_Functionality
+; It has been modified slightly and extended to provide
+; inter-component dependencies.
+Var AR_SecFlags
+Var AR_RegFlags
+ at CPACK_NSIS_SECTION_SELECTED_VARS@
+
+; Loads the "selected" flag for the section named SecName into the
+; variable VarName.
+!macro LoadSectionSelectedIntoVar SecName VarName
+ SectionGetFlags ${${SecName}} $${VarName}
+ IntOp $${VarName} $${VarName} & ${SF_SELECTED}  ;Turn off all other bits
+!macroend
+
+; Loads the value of a variable... can we get around this?
+!macro LoadVar VarName
+  IntOp $R0 0 + $${VarName}
+!macroend
+
+; Sets the value of a variable
+!macro StoreVar VarName IntValue
+  IntOp $${VarName} 0 + ${IntValue}
+!macroend
+
+!macro InitSection SecName
+  ;  This macro reads component installed flag from the registry and
+  ;changes checked state of the section on the components page.
+  ;Input: section index constant name specified in Section command.
+
+  ClearErrors
+  ;Reading component status from registry
+  ReadRegDWORD $AR_RegFlags HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@\Components\${SecName}" "Installed"
+  IfErrors "default_${SecName}"
+    ;Status will stay default if registry value not found
+    ;(component was never installed)
+  IntOp $AR_RegFlags $AR_RegFlags & ${SF_SELECTED} ;Turn off all other bits
+  SectionGetFlags ${${SecName}} $AR_SecFlags  ;Reading default section flags
+  IntOp $AR_SecFlags $AR_SecFlags & 0xFFFE  ;Turn lowest (enabled) bit off
+  IntOp $AR_SecFlags $AR_RegFlags | $AR_SecFlags      ;Change lowest bit
+
+  ; Note whether this component was installed before
+  !insertmacro StoreVar ${SecName}_was_installed $AR_RegFlags
+  IntOp $R0 $AR_RegFlags & $AR_RegFlags
+
+  ;Writing modified flags
+  SectionSetFlags ${${SecName}} $AR_SecFlags
+
+ "default_${SecName}:"
+ !insertmacro LoadSectionSelectedIntoVar ${SecName} ${SecName}_selected
+!macroend
+
+!macro FinishSection SecName
+  ;  This macro reads section flag set by user and removes the section
+  ;if it is not selected.
+  ;Then it writes component installed flag to registry
+  ;Input: section index constant name specified in Section command.
+
+  SectionGetFlags ${${SecName}} $AR_SecFlags  ;Reading section flags
+  ;Checking lowest bit:
+  IntOp $AR_SecFlags $AR_SecFlags & ${SF_SELECTED}
+  IntCmp $AR_SecFlags 1 "leave_${SecName}"
+    ;Section is not selected:
+    ;Calling Section uninstall macro and writing zero installed flag
+    !insertmacro "Remove_${${SecName}}"
+    WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@\Components\${SecName}" \
+  "Installed" 0
+    Goto "exit_${SecName}"
+
+ "leave_${SecName}:"
+    ;Section is selected:
+    WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@\Components\${SecName}" \
+  "Installed" 1
+
+ "exit_${SecName}:"
+!macroend
+
+!macro RemoveSection_CPack SecName
+  ;  This macro is used to call section's Remove_... macro
+  ;from the uninstaller.
+  ;Input: section index constant name specified in Section command.
+
+  !insertmacro "Remove_${${SecName}}"
+!macroend
+
+; Determine whether the selection of SecName changed
+!macro MaybeSelectionChanged SecName
+  !insertmacro LoadVar ${SecName}_selected
+  SectionGetFlags ${${SecName}} $R1
+  IntOp $R1 $R1 & ${SF_SELECTED} ;Turn off all other bits
+
+  ; See if the status has changed:
+  IntCmp $R0 $R1 "${SecName}_unchanged"
+  !insertmacro LoadSectionSelectedIntoVar ${SecName} ${SecName}_selected
+
+  IntCmp $R1 ${SF_SELECTED} "${SecName}_was_selected"
+  !insertmacro "Deselect_required_by_${SecName}"
+  goto "${SecName}_unchanged"
+
+  "${SecName}_was_selected:"
+  !insertmacro "Select_${SecName}_depends"
+
+  "${SecName}_unchanged:"
+!macroend
+;--- End of Add/Remove macros ---
+
+;--------------------------------
+;Interface Settings
+
+  !define MUI_HEADERIMAGE
+  !define MUI_ABORTWARNING
+  !define MUI_FINISHPAGE_NOAUTOCLOSE
+
+;--------------------------------
+; path functions
+
+!verbose 3
+!include "WinMessages.NSH"
+!verbose 4
+
+;----------------------------------------
+; based upon a script of "Written by KiCHiK 2003-01-18 05:57:02"
+;----------------------------------------
+!verbose 3
+!include "WinMessages.NSH"
+!verbose 4
+;====================================================
+; get_NT_environment
+;     Returns: the selected environment
+;     Output : head of the stack
+;====================================================
+!macro select_NT_profile UN
+Function ${UN}select_NT_profile
+   ${If} $ADD_TO_PATH_ALL_USERS = ${BST_CHECKED}
+      DetailPrint "Selected environment for all users"
+      Push "all"
+   ${Else}
+      DetailPrint "Selected environment for current user only."
+      Push "current"
+   ${EndIf}
+FunctionEnd
+!macroend
+!insertmacro select_NT_profile ""
+!insertmacro select_NT_profile "un."
+;----------------------------------------------------
+!define NT_current_env 'HKCU "Environment"'
+!define NT_all_env     'HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"'
+
+!ifndef WriteEnvStr_RegKey
+  !ifdef ALL_USERS
+    !define WriteEnvStr_RegKey \
+       'HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"'
+  !else
+    !define WriteEnvStr_RegKey 'HKCU "Environment"'
+  !endif
+!endif
+
+; AddToPath - Adds the given dir to the search path.
+;        Input - head of the stack
+;        Note - Win9x systems requires reboot
+
+Function AddToPath
+  Exch $0
+  Push $1
+  Push $2
+  Push $3
+
+  # don't add if the path doesn't exist
+  IfFileExists "$0\*.*" "" AddToPath_done
+
+  ReadEnvStr $1 PATH
+  ; if the path is too long for a NSIS variable NSIS will return a 0
+  ; length string.  If we find that, then warn and skip any path
+  ; modification as it will trash the existing path.
+  StrLen $2 $1
+  IntCmp $2 0 CheckPathLength_ShowPathWarning CheckPathLength_Done CheckPathLength_Done
+    CheckPathLength_ShowPathWarning:
+    Messagebox MB_OK|MB_ICONEXCLAMATION "Warning! PATH too long installer unable to modify PATH!"
+    Goto AddToPath_done
+  CheckPathLength_Done:
+  Push "$1;"
+  Push "$0;"
+  Call StrStr
+  Pop $2
+  StrCmp $2 "" "" AddToPath_done
+  Push "$1;"
+  Push "$0\;"
+  Call StrStr
+  Pop $2
+  StrCmp $2 "" "" AddToPath_done
+  GetFullPathName /SHORT $3 $0
+  Push "$1;"
+  Push "$3;"
+  Call StrStr
+  Pop $2
+  StrCmp $2 "" "" AddToPath_done
+  Push "$1;"
+  Push "$3\;"
+  Call StrStr
+  Pop $2
+  StrCmp $2 "" "" AddToPath_done
+
+  Call IsNT
+  Pop $1
+  StrCmp $1 1 AddToPath_NT
+    ; Not on NT
+    StrCpy $1 $WINDIR 2
+    FileOpen $1 "$1\autoexec.bat" a
+    FileSeek $1 -1 END
+    FileReadByte $1 $2
+    IntCmp $2 26 0 +2 +2 # DOS EOF
+      FileSeek $1 -1 END # write over EOF
+    FileWrite $1 "$\r$\nSET PATH=%PATH%;$3$\r$\n"
+    FileClose $1
+    SetRebootFlag true
+    Goto AddToPath_done
+
+  AddToPath_NT:
+    ${If} $ADD_TO_PATH_ALL_USERS = ${BST_CHECKED}
+      ReadRegStr $1 ${NT_all_env} "PATH"
+    ${Else}
+      ReadRegStr $1 ${NT_current_env} "PATH"
+    ${EndIf}
+    StrCmp $1 "" AddToPath_NTdoIt
+      Push $1
+      Call Trim
+      Pop $1
+      StrCpy $0 "$1;$0"
+    AddToPath_NTdoIt:
+      ${If} $ADD_TO_PATH_ALL_USERS = ${BST_CHECKED}
+        WriteRegExpandStr ${NT_all_env} "PATH" $0
+      ${Else}
+        WriteRegExpandStr ${NT_current_env} "PATH" $0
+      ${EndIf}
+      SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000
+
+  AddToPath_done:
+    Pop $3
+    Pop $2
+    Pop $1
+    Pop $0
+FunctionEnd
+
+
+; RemoveFromPath - Remove a given dir from the path
+;     Input: head of the stack
+
+Function un.RemoveFromPath
+  Exch $0
+  Push $1
+  Push $2
+  Push $3
+  Push $4
+  Push $5
+  Push $6
+
+  IntFmt $6 "%c" 26 # DOS EOF
+
+  Call un.IsNT
+  Pop $1
+  StrCmp $1 1 unRemoveFromPath_NT
+    ; Not on NT
+    StrCpy $1 $WINDIR 2
+    FileOpen $1 "$1\autoexec.bat" r
+    GetTempFileName $4
+    FileOpen $2 $4 w
+    GetFullPathName /SHORT $0 $0
+    StrCpy $0 "SET PATH=%PATH%;$0"
+    Goto unRemoveFromPath_dosLoop
+
+    unRemoveFromPath_dosLoop:
+      FileRead $1 $3
+      StrCpy $5 $3 1 -1 # read last char
+      StrCmp $5 $6 0 +2 # if DOS EOF
+        StrCpy $3 $3 -1 # remove DOS EOF so we can compare
+      StrCmp $3 "$0$\r$\n" unRemoveFromPath_dosLoopRemoveLine
+      StrCmp $3 "$0$\n" unRemoveFromPath_dosLoopRemoveLine
+      StrCmp $3 "$0" unRemoveFromPath_dosLoopRemoveLine
+      StrCmp $3 "" unRemoveFromPath_dosLoopEnd
+      FileWrite $2 $3
+      Goto unRemoveFromPath_dosLoop
+      unRemoveFromPath_dosLoopRemoveLine:
+        SetRebootFlag true
+        Goto unRemoveFromPath_dosLoop
+
+    unRemoveFromPath_dosLoopEnd:
+      FileClose $2
+      FileClose $1
+      StrCpy $1 $WINDIR 2
+      Delete "$1\autoexec.bat"
+      CopyFiles /SILENT $4 "$1\autoexec.bat"
+      Delete $4
+      Goto unRemoveFromPath_done
+
+  unRemoveFromPath_NT:
+    ${If} $ADD_TO_PATH_ALL_USERS = ${BST_CHECKED}
+      ReadRegStr $1 ${NT_all_env} "PATH"
+    ${Else}
+      ReadRegStr $1 ${NT_current_env} "PATH"
+    ${EndIf}
+    StrCpy $5 $1 1 -1 # copy last char
+    StrCmp $5 ";" +2 # if last char != ;
+      StrCpy $1 "$1;" # append ;
+    Push $1
+    Push "$0;"
+    Call un.StrStr ; Find `$0;` in $1
+    Pop $2 ; pos of our dir
+    StrCmp $2 "" unRemoveFromPath_done
+      ; else, it is in path
+      # $0 - path to add
+      # $1 - path var
+      StrLen $3 "$0;"
+      StrLen $4 $2
+      StrCpy $5 $1 -$4 # $5 is now the part before the path to remove
+      StrCpy $6 $2 "" $3 # $6 is now the part after the path to remove
+      StrCpy $3 $5$6
+
+      StrCpy $5 $3 1 -1 # copy last char
+      StrCmp $5 ";" 0 +2 # if last char == ;
+        StrCpy $3 $3 -1 # remove last char
+
+      ${If} $ADD_TO_PATH_ALL_USERS = ${BST_CHECKED}
+        WriteRegExpandStr ${NT_all_env} "PATH" $3
+      ${Else}
+        WriteRegExpandStr ${NT_current_env} "PATH" $3
+      ${EndIf}
+      SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000
+
+  unRemoveFromPath_done:
+    Pop $6
+    Pop $5
+    Pop $4
+    Pop $3
+    Pop $2
+    Pop $1
+    Pop $0
+FunctionEnd
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; Uninstall sutff
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+###########################################
+#            Utility Functions            #
+###########################################
+
+;====================================================
+; IsNT - Returns 1 if the current system is NT, 0
+;        otherwise.
+;     Output: head of the stack
+;====================================================
+; IsNT
+; no input
+; output, top of the stack = 1 if NT or 0 if not
+;
+; Usage:
+;   Call IsNT
+;   Pop $R0
+;  ($R0 at this point is 1 or 0)
+
+!macro IsNT un
+Function ${un}IsNT
+  Push $0
+  ReadRegStr $0 HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion" CurrentVersion
+  StrCmp $0 "" 0 IsNT_yes
+  ; we are not NT.
+  Pop $0
+  Push 0
+  Return
+
+  IsNT_yes:
+    ; NT!!!
+    Pop $0
+    Push 1
+FunctionEnd
+!macroend
+!insertmacro IsNT ""
+!insertmacro IsNT "un."
+
+; StrStr
+; input, top of stack = string to search for
+;        top of stack-1 = string to search in
+; output, top of stack (replaces with the portion of the string remaining)
+; modifies no other variables.
+;
+; Usage:
+;   Push "this is a long ass string"
+;   Push "ass"
+;   Call StrStr
+;   Pop $R0
+;  ($R0 at this point is "ass string")
+
+!macro StrStr un
+Function ${un}StrStr
+Exch $R1 ; st=haystack,old$R1, $R1=needle
+  Exch    ; st=old$R1,haystack
+  Exch $R2 ; st=old$R1,old$R2, $R2=haystack
+  Push $R3
+  Push $R4
+  Push $R5
+  StrLen $R3 $R1
+  StrCpy $R4 0
+  ; $R1=needle
+  ; $R2=haystack
+  ; $R3=len(needle)
+  ; $R4=cnt
+  ; $R5=tmp
+  loop:
+    StrCpy $R5 $R2 $R3 $R4
+    StrCmp $R5 $R1 done
+    StrCmp $R5 "" done
+    IntOp $R4 $R4 + 1
+    Goto loop
+done:
+  StrCpy $R1 $R2 "" $R4
+  Pop $R5
+  Pop $R4
+  Pop $R3
+  Pop $R2
+  Exch $R1
+FunctionEnd
+!macroend
+!insertmacro StrStr ""
+!insertmacro StrStr "un."
+
+Function Trim ; Added by Pelaca
+	Exch $R1
+	Push $R2
+Loop:
+	StrCpy $R2 "$R1" 1 -1
+	StrCmp "$R2" " " RTrim
+	StrCmp "$R2" "$\n" RTrim
+	StrCmp "$R2" "$\r" RTrim
+	StrCmp "$R2" ";" RTrim
+	GoTo Done
+RTrim:
+	StrCpy $R1 "$R1" -1
+	Goto Loop
+Done:
+	Pop $R2
+	Exch $R1
+FunctionEnd
+
+Function ConditionalAddToRegisty
+  Pop $0
+  Pop $1
+  StrCmp "$0" "" ConditionalAddToRegisty_EmptyString
+    WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" \
+    "$1" "$0"
+    ;MessageBox MB_OK "Set Registry: '$1' to '$0'"
+    DetailPrint "Set install registry entry: '$1' to '$0'"
+  ConditionalAddToRegisty_EmptyString:
+FunctionEnd
+
+;--------------------------------
+
+!ifdef CPACK_USES_DOWNLOAD
+Function DownloadFile
+    IfFileExists $INSTDIR\* +2
+    CreateDirectory $INSTDIR
+    Pop $0
+
+    ; Skip if already downloaded
+    IfFileExists $INSTDIR\$0 0 +2
+    Return
+
+    StrCpy $1 "@CPACK_DOWNLOAD_SITE@"
+
+  try_again:
+    NSISdl::download "$1/$0" "$INSTDIR\$0"
+
+    Pop $1
+    StrCmp $1 "success" success
+    StrCmp $1 "Cancelled" cancel
+    MessageBox MB_OK "Download failed: $1"
+  cancel:
+    Return
+  success:
+FunctionEnd
+!endif
+
+;--------------------------------
+; Installation types
+ at CPACK_NSIS_INSTALLATION_TYPES@
+
+;--------------------------------
+; Component sections
+ at CPACK_NSIS_COMPONENT_SECTIONS@
+
+;--------------------------------
+; Define some macro setting for the gui
+ at CPACK_NSIS_INSTALLER_MUI_ICON_CODE@
+ at CPACK_NSIS_INSTALLER_ICON_CODE@
+ at CPACK_NSIS_INSTALLER_MUI_COMPONENTS_DESC@
+ at CPACK_NSIS_INSTALLER_MUI_FINISHPAGE_RUN_CODE@
+
+;--------------------------------
+;Pages
+  !insertmacro MUI_PAGE_WELCOME
+
+  !insertmacro MUI_PAGE_LICENSE "@CPACK_RESOURCE_FILE_LICENSE@"
+  Page custom InstallOptionsPage InstallOptionsPageLeave
+  !insertmacro MUI_PAGE_DIRECTORY
+
+  ;Start Menu Folder Page Configuration
+  !define MUI_STARTMENUPAGE_REGISTRY_ROOT "SHCTX"
+  !define MUI_STARTMENUPAGE_REGISTRY_KEY "Software\@CPACK_PACKAGE_VENDOR@\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@"
+  !define MUI_STARTMENUPAGE_REGISTRY_VALUENAME "Start Menu Folder"
+  !insertmacro MUI_PAGE_STARTMENU Application $STARTMENU_FOLDER
+
+  @CPACK_NSIS_PAGE_COMPONENTS@
+
+  @CPACK_NSIS_EXTRA_PAGES@
+
+  !insertmacro MUI_PAGE_INSTFILES
+  !insertmacro MUI_PAGE_FINISH
+
+  !insertmacro MUI_UNPAGE_CONFIRM
+  !insertmacro MUI_UNPAGE_INSTFILES
+
+;--------------------------------
+;Languages
+
+  !insertmacro MUI_LANGUAGE "English" ;first language is the default language
+  !insertmacro MUI_LANGUAGE "Albanian"
+  !insertmacro MUI_LANGUAGE "Arabic"
+  !insertmacro MUI_LANGUAGE "Basque"
+  !insertmacro MUI_LANGUAGE "Belarusian"
+  !insertmacro MUI_LANGUAGE "Bosnian"
+  !insertmacro MUI_LANGUAGE "Breton"
+  !insertmacro MUI_LANGUAGE "Bulgarian"
+  !insertmacro MUI_LANGUAGE "Croatian"
+  !insertmacro MUI_LANGUAGE "Czech"
+  !insertmacro MUI_LANGUAGE "Danish"
+  !insertmacro MUI_LANGUAGE "Dutch"
+  !insertmacro MUI_LANGUAGE "Estonian"
+  !insertmacro MUI_LANGUAGE "Farsi"
+  !insertmacro MUI_LANGUAGE "Finnish"
+  !insertmacro MUI_LANGUAGE "French"
+  !insertmacro MUI_LANGUAGE "German"
+  !insertmacro MUI_LANGUAGE "Greek"
+  !insertmacro MUI_LANGUAGE "Hebrew"
+  !insertmacro MUI_LANGUAGE "Hungarian"
+  !insertmacro MUI_LANGUAGE "Icelandic"
+  !insertmacro MUI_LANGUAGE "Indonesian"
+  !insertmacro MUI_LANGUAGE "Irish"
+  !insertmacro MUI_LANGUAGE "Italian"
+  !insertmacro MUI_LANGUAGE "Japanese"
+  !insertmacro MUI_LANGUAGE "Korean"
+  !insertmacro MUI_LANGUAGE "Kurdish"
+  !insertmacro MUI_LANGUAGE "Latvian"
+  !insertmacro MUI_LANGUAGE "Lithuanian"
+  !insertmacro MUI_LANGUAGE "Luxembourgish"
+  !insertmacro MUI_LANGUAGE "Macedonian"
+  !insertmacro MUI_LANGUAGE "Malay"
+  !insertmacro MUI_LANGUAGE "Mongolian"
+  !insertmacro MUI_LANGUAGE "Norwegian"
+  !insertmacro MUI_LANGUAGE "Polish"
+  !insertmacro MUI_LANGUAGE "Portuguese"
+  !insertmacro MUI_LANGUAGE "PortugueseBR"
+  !insertmacro MUI_LANGUAGE "Romanian"
+  !insertmacro MUI_LANGUAGE "Russian"
+  !insertmacro MUI_LANGUAGE "Serbian"
+  !insertmacro MUI_LANGUAGE "SerbianLatin"
+  !insertmacro MUI_LANGUAGE "SimpChinese"
+  !insertmacro MUI_LANGUAGE "Slovak"
+  !insertmacro MUI_LANGUAGE "Slovenian"
+  !insertmacro MUI_LANGUAGE "Spanish"
+  !insertmacro MUI_LANGUAGE "Swedish"
+  !insertmacro MUI_LANGUAGE "Thai"
+  !insertmacro MUI_LANGUAGE "TradChinese"
+  !insertmacro MUI_LANGUAGE "Turkish"
+  !insertmacro MUI_LANGUAGE "Ukrainian"
+  !insertmacro MUI_LANGUAGE "Welsh"
+
+
+;--------------------------------
+;Reserve Files
+
+  ;These files should be inserted before other files in the data block
+  ;Keep these lines before any File command
+  ;Only for solid compression (by default, solid compression is enabled for BZIP2 and LZMA)
+
+;--------------------------------
+;Installer Sections
+
+Section "-Core installation"
+  ;Use the entire tree produced by the INSTALL target.  Keep the
+  ;list of directories here in sync with the RMDir commands below.
+  SetOutPath "$INSTDIR"
+  @CPACK_NSIS_EXTRA_PREINSTALL_COMMANDS@
+  @CPACK_NSIS_FULL_INSTALL@
+
+  ;Store installation folder
+  WriteRegStr SHCTX "Software\@CPACK_PACKAGE_VENDOR@\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" "" $INSTDIR
+
+  ;Create uninstaller
+  WriteUninstaller "$INSTDIR\Uninstall.exe"
+  Push "DisplayName"
+  Push "@CPACK_NSIS_DISPLAY_NAME@"
+  Call ConditionalAddToRegisty
+  Push "DisplayVersion"
+  Push "@CPACK_PACKAGE_VERSION@"
+  Call ConditionalAddToRegisty
+  Push "Publisher"
+  Push "@CPACK_PACKAGE_VENDOR@"
+  Call ConditionalAddToRegisty
+  Push "UninstallString"
+  Push "$INSTDIR\Uninstall.exe"
+  Call ConditionalAddToRegisty
+  Push "NoRepair"
+  Push "1"
+  Call ConditionalAddToRegisty
+
+  !ifdef CPACK_NSIS_ADD_REMOVE
+  ;Create add/remove functionality
+  Push "ModifyPath"
+  Push "$INSTDIR\AddRemove.exe"
+  Call ConditionalAddToRegisty
+  !else
+  Push "NoModify"
+  Push "1"
+  Call ConditionalAddToRegisty
+  !endif
+
+  ; Optional registration
+  Push "DisplayIcon"
+  Push "$INSTDIR\@CPACK_NSIS_INSTALLED_ICON_NAME@"
+  Call ConditionalAddToRegisty
+  Push "HelpLink"
+  Push "@CPACK_NSIS_HELP_LINK@"
+  Call ConditionalAddToRegisty
+  Push "URLInfoAbout"
+  Push "@CPACK_NSIS_URL_INFO_ABOUT@"
+  Call ConditionalAddToRegisty
+  Push "Contact"
+  Push "@CPACK_NSIS_CONTACT@"
+  Call ConditionalAddToRegisty
+  !insertmacro MUI_STARTMENU_WRITE_BEGIN Application
+
+  ;Create shortcuts
+  CreateDirectory "$SMPROGRAMS\$STARTMENU_FOLDER"
+ at CPACK_NSIS_CREATE_ICONS@
+ at CPACK_NSIS_CREATE_ICONS_EXTRA@
+  CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\Uninstall.lnk" "$INSTDIR\Uninstall.exe"
+
+  ; Write special uninstall registry entries
+  Push "StartMenu"
+  Push "$STARTMENU_FOLDER"
+  Call ConditionalAddToRegisty
+  WriteRegDWORD SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" \
+    "DoNotAddToPath" $DO_NOT_ADD_TO_PATH
+  WriteRegDWORD SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" \
+    "AddToPathAllUsers" $ADD_TO_PATH_ALL_USERS
+  WriteRegDWORD SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" \
+    "AddToPathCurrentUser" $ADD_TO_PATH_CURRENT_USER
+  WriteRegDWORD SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" \
+    "InstallToDesktop" $INSTALL_DESKTOP
+
+  !insertmacro MUI_STARTMENU_WRITE_END
+
+ at CPACK_NSIS_EXTRA_INSTALL_COMMANDS@
+
+SectionEnd
+
+Section "-Add to path"
+  Push $INSTDIR\bin
+  ${If} "@CPACK_NSIS_MODIFY_PATH@" == "ON"
+    ${If} $DO_NOT_ADD_TO_PATH = ${BST_UNCHECKED}
+      Call AddToPath
+    ${EndIf}
+  ${EndIf}
+SectionEnd
+
+;--------------------------------
+; Create custom pages
+Function InstallOptionsPage
+  Push $R0
+  Push $0
+
+  !insertmacro MUI_HEADER_TEXT "Install Options" "Choose options for installing @CPACK_NSIS_PACKAGE_NAME@"
+
+  nsDialogs::Create 1018
+  Pop $R0
+  ${If} $R0 == error
+    Abort
+  ${EndIf}
+
+  ${NSD_CreateLabel} 0u 0u 100% 20u 'By default @CPACK_PACKAGE_INSTALL_DIRECTORY@ does not add its directory to the system PATH.'
+  Pop $0
+
+  ${NSD_CreateRadioButton} 0u 30u 100% 10u 'Do not add @CPACK_PACKAGE_NAME@ to the system PATH'
+  Pop $RB_DO_NOT_ADD_TO_PATH
+  ${NSD_SetState} $RB_DO_NOT_ADD_TO_PATH $DO_NOT_ADD_TO_PATH
+
+  ${NSD_CreateRadioButton} 0u 40u 100% 10u 'Add @CPACK_PACKAGE_NAME@ to the system PATH for all users'
+  Pop $RB_ADD_TO_PATH_ALL_USERS
+  ${NSD_SetState} $RB_ADD_TO_PATH_ALL_USERS $ADD_TO_PATH_ALL_USERS
+
+  ${NSD_CreateRadioButton} 0u 50u 100% 10u 'Add @CPACK_PACKAGE_NAME@ to the system PATH for the current user'
+  Pop $RB_ADD_TO_PATH_CURRENT_USER
+  ${NSD_SetState} $RB_ADD_TO_PATH_CURRENT_USER $ADD_TO_PATH_CURRENT_USER
+
+  ${NSD_CreateCheckBox} 0u 80u 100% 10u 'Create @CPACK_PACKAGE_NAME@ Desktop Icon'
+  Pop $CB_INSTALL_DESKTOP
+  ${NSD_SetState} $CB_INSTALL_DESKTOP $INSTALL_DESKTOP
+
+  @CPACK_NSIS_EXTRA_INSTALL_OPTIONS@
+
+  nsDialogs::Show
+
+  Pop $0
+  Pop $R0
+FunctionEnd
+
+Function InstallOptionsPageLeave
+  ${NSD_GetState} $RB_DO_NOT_ADD_TO_PATH $DO_NOT_ADD_TO_PATH
+  ${NSD_GetState} $RB_ADD_TO_PATH_ALL_USERS $ADD_TO_PATH_ALL_USERS
+  ${NSD_GetState} $RB_ADD_TO_PATH_CURRENT_USER $ADD_TO_PATH_CURRENT_USER
+
+  ${NSD_GetState} $CB_INSTALL_DESKTOP $INSTALL_DESKTOP
+
+  @CPACK_NSIS_EXTRA_INSTALL_OPTIONS_READ@
+FunctionEnd
+
+;--------------------------------
+; determine admin versus local install
+Function un.onInit
+  Push $0
+  Push $1
+
+  ClearErrors
+  UserInfo::GetName
+  IfErrors noLM
+  Pop $0
+  UserInfo::GetAccountType
+  Pop $1
+  StrCmp $1 "Admin" 0 +3
+    SetShellVarContext all
+    ;MessageBox MB_OK 'User "$0" is in the Admin group'
+    Goto done
+  StrCmp $1 "Power" 0 +3
+    SetShellVarContext all
+    ;MessageBox MB_OK 'User "$0" is in the Power Users group'
+    Goto done
+
+  noLM:
+    ;Get installation folder from registry if available
+
+  done:
+
+  Pop $1
+  Pop $0
+FunctionEnd
+
+;--- Add/Remove callback functions: ---
+!macro SectionList MacroName
+  ;This macro used to perform operation on multiple sections.
+  ;List all of your components in following manner here.
+ at CPACK_NSIS_COMPONENT_SECTION_LIST@
+!macroend
+
+Section -FinishComponents
+  ;Removes unselected components and writes component status to registry
+  !insertmacro SectionList "FinishSection"
+
+!ifdef CPACK_NSIS_ADD_REMOVE
+  ; Get the name of the installer executable
+  System::Call 'kernel32::GetModuleFileNameA(i 0, t .R0, i 1024) i r1'
+  StrCpy $R3 $R0
+
+  ; Strip off the last 13 characters, to see if we have AddRemove.exe
+  StrLen $R1 $R0
+  IntOp $R1 $R0 - 13
+  StrCpy $R2 $R0 13 $R1
+  StrCmp $R2 "AddRemove.exe" addremove_installed
+
+  ; We're not running AddRemove.exe, so install it
+  CopyFiles $R3 $INSTDIR\AddRemove.exe
+
+  addremove_installed:
+!endif
+SectionEnd
+;--- End of Add/Remove callback functions ---
+
+;--------------------------------
+; Component dependencies
+Function .onSelChange
+  !insertmacro SectionList MaybeSelectionChanged
+FunctionEnd
+
+;--------------------------------
+;Uninstaller Section
+
+Section "Uninstall"
+  ReadRegStr $START_MENU SHCTX \
+   "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" "StartMenu"
+  ;MessageBox MB_OK "Start menu is in: $START_MENU"
+  ReadRegDWORD $DO_NOT_ADD_TO_PATH SHCTX \
+    "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" "DoNotAddToPath"
+  ReadRegDWORD $ADD_TO_PATH_ALL_USERS SHCTX \
+    "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" "AddToPathAllUsers"
+  ReadRegDWORD $ADD_TO_PATH_CURRENT_USER SHCTX \
+    "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" "AddToPathCurrentUser"
+  ;MessageBox MB_OK "Add to path: $DO_NOT_ADD_TO_PATH all users: $ADD_TO_PATH_ALL_USERS"
+  ReadRegDWORD $INSTALL_DESKTOP SHCTX \
+    "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" "InstallToDesktop"
+  ;MessageBox MB_OK "Install to desktop: $INSTALL_DESKTOP "
+
+ at CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS@
+
+  ;Remove files we installed.
+  ;Keep the list of directories here in sync with the File commands above.
+ at CPACK_NSIS_DELETE_FILES@
+ at CPACK_NSIS_DELETE_DIRECTORIES@
+
+!ifdef CPACK_NSIS_ADD_REMOVE
+  ;Remove the add/remove program
+  Delete "$INSTDIR\AddRemove.exe"
+!endif
+
+  ;Remove the uninstaller itself.
+  Delete "$INSTDIR\Uninstall.exe"
+  DeleteRegKey SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@"
+
+  ;Remove the installation directory if it is empty.
+  RMDir "$INSTDIR"
+
+  ; Remove the registry entries.
+  DeleteRegKey SHCTX "Software\@CPACK_PACKAGE_VENDOR@\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@"
+
+  ; Removes all optional components
+  !insertmacro SectionList "RemoveSection_CPack"
+
+  !insertmacro MUI_STARTMENU_GETFOLDER Application $MUI_TEMP
+
+  Delete "$SMPROGRAMS\$MUI_TEMP\Uninstall.lnk"
+ at CPACK_NSIS_DELETE_ICONS@
+ at CPACK_NSIS_DELETE_ICONS_EXTRA@
+
+  ;Delete empty start menu parent diretories
+  StrCpy $MUI_TEMP "$SMPROGRAMS\$MUI_TEMP"
+
+  startMenuDeleteLoop:
+    ClearErrors
+    RMDir $MUI_TEMP
+    GetFullPathName $MUI_TEMP "$MUI_TEMP\.."
+
+    IfErrors startMenuDeleteLoopDone
+
+    StrCmp "$MUI_TEMP" "$SMPROGRAMS" startMenuDeleteLoopDone startMenuDeleteLoop
+  startMenuDeleteLoopDone:
+
+  ; If the user changed the shortcut, then untinstall may not work. This should
+  ; try to fix it.
+  StrCpy $MUI_TEMP "$START_MENU"
+  Delete "$SMPROGRAMS\$MUI_TEMP\Uninstall.lnk"
+ at CPACK_NSIS_DELETE_ICONS_EXTRA@
+
+  ;Delete empty start menu parent diretories
+  StrCpy $MUI_TEMP "$SMPROGRAMS\$MUI_TEMP"
+
+  secondStartMenuDeleteLoop:
+    ClearErrors
+    RMDir $MUI_TEMP
+    GetFullPathName $MUI_TEMP "$MUI_TEMP\.."
+
+    IfErrors secondStartMenuDeleteLoopDone
+
+    StrCmp "$MUI_TEMP" "$SMPROGRAMS" secondStartMenuDeleteLoopDone secondStartMenuDeleteLoop
+  secondStartMenuDeleteLoopDone:
+
+  DeleteRegKey /ifempty SHCTX "Software\@CPACK_PACKAGE_VENDOR@\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@"
+
+  Push $INSTDIR\bin
+  ${Unless} $DO_NOT_ADD_TO_PATH = ${BST_CHECKED}
+    Call un.RemoveFromPath
+  ${EndUnless}
+SectionEnd
+
+;--------------------------------
+; determine admin versus local install
+; Is install for "AllUsers" or "JustMe"?
+; Default to "JustMe" - set to "AllUsers" if admin or on Win9x
+; This function is used for the very first "custom page" of the installer.
+; This custom page does not show up visibly, but it executes prior to the
+; first visible page and sets up $INSTDIR properly...
+; Choose different default installation folder based on SV_ALLUSERS...
+; "Program Files" for AllUsers, "My Documents" for JustMe...
+
+Function .onInit
+  Push $0
+  Push $1
+  Push $2
+  Push $3
+
+  StrCmp "@CPACK_NSIS_ENABLE_UNINSTALL_BEFORE_INSTALL@" "ON" 0 inst
+
+  ReadRegStr $0 HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" "UninstallString"
+  StrCmp $0 "" inst
+
+  MessageBox MB_YESNOCANCEL|MB_ICONEXCLAMATION \
+  "@CPACK_NSIS_PACKAGE_NAME@ is already installed. $\n$\nDo you want to uninstall the old version before installing the new one?" \
+  IDYES uninst IDNO inst
+  Abort
+
+;Run the uninstaller
+uninst:
+  ClearErrors
+  StrLen $2 "\Uninstall.exe"
+  StrCpy $3 $0 -$2 # remove "\Uninstall.exe" from UninstallString to get path
+  ExecWait '$0 _?=$3' ;Do not copy the uninstaller to a temp file
+
+  IfErrors uninst_failed inst
+uninst_failed:
+  MessageBox MB_OK|MB_ICONSTOP "Uninstall failed."
+  Abort
+
+
+inst:
+  ; Reads components status for registry
+  !insertmacro SectionList "InitSection"
+
+  ; check to see if /D has been used to change
+  ; the install directory by comparing it to the
+  ; install directory that is expected to be the
+  ; default
+  StrCpy $IS_DEFAULT_INSTALLDIR 0
+  StrCmp "$INSTDIR" "@CPACK_NSIS_INSTALL_ROOT@\@CPACK_PACKAGE_INSTALL_DIRECTORY@" 0 +2
+    StrCpy $IS_DEFAULT_INSTALLDIR 1
+
+  StrCpy $SV_ALLUSERS "JustMe"
+  ; if default install dir then change the default
+  ; if it is installed for JustMe
+  StrCmp "$IS_DEFAULT_INSTALLDIR" "1" 0 +2
+    StrCpy $INSTDIR "$DOCUMENTS\@CPACK_PACKAGE_INSTALL_DIRECTORY@"
+
+  ClearErrors
+  UserInfo::GetName
+  IfErrors noLM
+  Pop $0
+  UserInfo::GetAccountType
+  Pop $1
+  StrCmp $1 "Admin" 0 +4
+    SetShellVarContext all
+    ;MessageBox MB_OK 'User "$0" is in the Admin group'
+    StrCpy $SV_ALLUSERS "AllUsers"
+    Goto done
+  StrCmp $1 "Power" 0 +4
+    SetShellVarContext all
+    ;MessageBox MB_OK 'User "$0" is in the Power Users group'
+    StrCpy $SV_ALLUSERS "AllUsers"
+    Goto done
+
+  noLM:
+    StrCpy $SV_ALLUSERS "AllUsers"
+    ;Get installation folder from registry if available
+
+  done:
+  StrCmp $SV_ALLUSERS "AllUsers" 0 +3
+    StrCmp "$IS_DEFAULT_INSTALLDIR" "1" 0 +2
+      StrCpy $INSTDIR "@CPACK_NSIS_INSTALL_ROOT@\@CPACK_PACKAGE_INSTALL_DIRECTORY@"
+
+  IntOp $DO_NOT_ADD_TO_PATH 0 + ${BST_CHECKED} ; set to checked
+  IntOp $ADD_TO_PATH_ALL_USERS 0 + ${BST_UNCHECKED} ; set to unchecked
+  IntOp $ADD_TO_PATH_CURRENT_USER 0 + ${BST_UNCHECKED} ; ditto
+  IntOp $INSTALL_DESKTOP 0 + ${BST_UNCHECKED} ; set to unchecked
+
+  @CPACK_NSIS_EXTRA_INIT_COMMANDS@
+
+  Pop $3
+  Pop $2
+  Pop $1
+  Pop $0
+FunctionEnd
diff --git a/CMake/Modules/QtAxMacros.cmake b/CMake/Modules/QtAxMacros.cmake
new file mode 100644
index 0000000..6a4cd14
--- /dev/null
+++ b/CMake/Modules/QtAxMacros.cmake
@@ -0,0 +1,36 @@
+#
+# Macros for processing ActiveX and COM controls with ActiveQt
+#
+
+if (WIN32)
+  include (CMakeParseArguments)
+
+  find_program (DUMPCPP_Executable dumpcpp.exe)
+
+  # wrap_ax_server (outfiles inputfile ...)
+
+  function (WRAP_AX_SERVER outfiles)
+    set (options)
+    set (oneValueArgs)
+    set (multiValueArgs OPTIONS)
+    
+    cmake_parse_arguments (_WRAP_AX_SERVER "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+    
+    set (ax_server_files ${_WRAP_AX_SERVER_UNPARSED_ARGUMENTS})
+    set (ax_server_options ${_WRAP_AX_SERVER_OPTIONS})
+
+    foreach (it ${ax_server_files})
+      get_filename_component (outfile ${it} NAME_WE)
+      get_filename_component (infile ${it} ABSOLUTE)
+      set (outfile ${CMAKE_CURRENT_BINARY_DIR}/${outfile})
+      add_custom_command (
+	OUTPUT ${outfile}.h ${outfile}.cpp
+	COMMAND ${DUMPCPP_Executable}
+	ARGS ${AX_SERVER_options} -o "${outfile}" "${infile}"
+	MAIN_DEPENDENCY ${infile} VERBATIM)
+      list (APPEND ${outfiles} ${outfile}.cpp)
+    endforeach()
+    set(${outfiles} ${${outfiles}} PARENT_SCOPE)
+  endfunction ()
+
+endif (WIN32)
\ No newline at end of file
diff --git a/CMake/VersionCompute.cmake b/CMake/VersionCompute.cmake
new file mode 100644
index 0000000..b69bbfc
--- /dev/null
+++ b/CMake/VersionCompute.cmake
@@ -0,0 +1,11 @@
+# Load version number components.
+include (${CMAKE_SOURCE_DIR}/Versions.cmake)
+
+# Compute the full version string.
+if (WSJTX_RC AND NOT WSJTX_VERSION_IS_RELEASE)
+  set (WSJTX_VERSION_PATCH ${WSJTX_VERSION_PATCH}-rc${WSJTX_RC})
+elseif (NOT WSJTX_VERSION_IS_RELEASE)
+  set (WSJTX_VERSION_PATCH ${WSJTX_VERSION_PATCH}-devel)
+endif (WSJTX_RC AND NOT WSJTX_VERSION_IS_RELEASE)
+
+set (wsjtx_VERSION ${WSJTX_VERSION_MAJOR}.${WSJTX_VERSION_MINOR}.${WSJTX_VERSION_PATCH})
diff --git a/CMake/cmake_uninstall.cmake.in b/CMake/cmake_uninstall.cmake.in
new file mode 100644
index 0000000..23b3064
--- /dev/null
+++ b/CMake/cmake_uninstall.cmake.in
@@ -0,0 +1,22 @@
+if (NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
+  message (FATAL_ERROR "Cannot find install manifest: \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\"")
+endif ()
+
+file (READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files)
+string (REGEX REPLACE "\n" ";" files "${files}")
+foreach (file ${files})
+  message (STATUS "Uninstalling \"$ENV{DESTDIR}${file}\"")
+  if (EXISTS "$ENV{DESTDIR}${file}")
+    exec_program (
+      "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\""
+      OUTPUT_VARIABLE rm_out
+      RETURN_VALUE rm_retval
+      )
+    if ("${rm_retval}" STREQUAL 0)
+    else ()
+      message (FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"")
+    endif ()
+  else ()
+    message (STATUS "File \"$ENV{DESTDIR}${file}\" does not exist.")
+  endif ()
+endforeach ()
diff --git a/CMake/download_html_manual.cmake b/CMake/download_html_manual.cmake
new file mode 100644
index 0000000..8128bfe
--- /dev/null
+++ b/CMake/download_html_manual.cmake
@@ -0,0 +1,16 @@
+#
+# CMake script to fetch the current HTML manual
+#
+message (STATUS "file: ${URL}/${NAME}")
+file (
+  DOWNLOAD ${URL}/${NAME} contrib/${NAME}
+  TIMEOUT 120
+  STATUS manual_STATUS
+  LOG manual_LOG
+  SHOW_PROGRESS
+  )
+list (GET manual_STATUS 0 manual_RC)
+if (manual_RC)
+  message (WARNING "${manual_STATUS}")
+  message (FATAL_ERROR "${manual_LOG}")
+endif (manual_RC)
diff --git a/CMake/download_kvasd.cmake b/CMake/download_kvasd.cmake
new file mode 100644
index 0000000..750052f
--- /dev/null
+++ b/CMake/download_kvasd.cmake
@@ -0,0 +1,43 @@
+#
+# CMake script to fetch kvasd binary for the current platform
+#
+set (kvasd_NAME "${URL}/${SYSTEM_NAME}/kvasd${EXECUTABLE_SUFFIX}")
+set (kvasd_target "contrib/kvasd${EXECUTABLE_SUFFIX}")
+
+message (STATUS "downloading file: ${kvasd_NAME}.md5")
+file (
+  DOWNLOAD "${kvasd_NAME}.md5" "${kvasd_target}.md5"
+  TIMEOUT 120
+  STATUS status
+  LOG log
+  SHOW_PROGRESS
+  )
+list (GET status 0 rc)
+if (rc)
+  message (WARNING "${status}")
+  message (FATAL_ERROR "${log}")
+endif (rc)
+file (READ "${kvasd_target}.md5" md5sum)
+string (REGEX MATCH "[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]" md5sum "${md5sum}")
+
+if (EXISTS "${kvasd_target}")
+  file (MD5 "${kvasd_target}" current_md5sum)
+endif (EXISTS "${kvasd_target}")
+if (NOT "${md5sum}" STREQUAL "${current_md5sum}")
+  message (STATUS "downloading file: ${kvasd_NAME}")
+  file (
+    DOWNLOAD ${kvasd_NAME} contrib/kvasd${EXECUTABLE_SUFFIX}
+    TIMEOUT 120
+    STATUS status
+    LOG log
+    SHOW_PROGRESS
+    EXPECTED_MD5 "${md5sum}"
+    )
+  list (GET status 0 rc)
+  if (rc)
+    message (WARNING "${status}")
+    message (FATAL_ERROR "${log}")
+  endif (rc)
+else (NOT "${md5sum}" STREQUAL "${current_md5sum}")
+  message (STATUS "file: ${kvasd_NAME} up to date")
+endif (NOT "${md5sum}" STREQUAL "${current_md5sum}")
diff --git a/CMake/getsvn.cmake b/CMake/getsvn.cmake
new file mode 100644
index 0000000..7549636
--- /dev/null
+++ b/CMake/getsvn.cmake
@@ -0,0 +1,54 @@
+find_package (Subversion)
+if (Subversion_FOUND AND EXISTS "${SOURCE_DIR}/.svn")
+  # the FindSubversion.cmake module is part of the standard distribution
+  include (FindSubversion)
+  # extract working copy information for SOURCE_DIR into MY_XXX variables
+  Subversion_WC_INFO (${SOURCE_DIR} MY)
+  message ("${MY_WC_INFO}")
+  # determine if the working copy has outstanding changes
+  execute_process (COMMAND ${Subversion_SVN_EXECUTABLE} status ${SOURCE_DIR}
+    OUTPUT_FILE "${OUTPUT_DIR}/svn_status.txt"
+    OUTPUT_STRIP_TRAILING_WHITESPACE)
+  file (STRINGS "${OUTPUT_DIR}/svn_status.txt" __svn_changes
+    REGEX "^[^?].*$"
+    )
+  if (__svn_changes)
+    message (WARNING "Source tree based on revision ${MY_WC_LAST_CHANGED_REV} appears to have local changes")
+    set (MY_WC_LAST_CHANGED_REV "${MY_WC_LAST_CHANGED_REV}-dirty")
+    foreach (__svn_change ${__svn_changes})
+      message (STATUS "${__svn_change}")
+    endforeach (__svn_change ${__svn_changes})
+  endif (__svn_changes)
+  message (STATUS "${SOURCE_DIR} contains a .svn and is revision ${MY_WC_LAST_CHANGED_REV}")
+  # write a file with the SVNVERSION define
+  file (WRITE "${OUTPUT_DIR}/svnversion.h.txt" "#define SVNVERSION ${MY_WC_LAST_CHANGED_REV}\n")
+else (Subversion_FOUND AND EXISTS "${SOURCE_DIR}/.svn")
+  # try git-svn
+  if (Subversion_FOUND AND EXISTS "${SOURCE_DIR}/.git")
+    include (${SOURCE_DIR}/CMake/Modules/FindGitSubversion.cmake)
+    # extract working copy information for SOURCE_DIR into MY_XXX variables
+    GitSubversion_WC_INFO (${SOURCE_DIR} MY)
+    message ("${MY_WC_INFO}")
+    # try and determine if the working copy has outstanding changes
+    execute_process (COMMAND ${GIT_EXECUTABLE} --git-dir=${SOURCE_DIR}/.git --work-tree=${SOURCE_DIR} svn dcommit --dry-run
+      RESULT_VARIABLE __git_svn_status
+      OUTPUT_FILE "${OUTPUT_DIR}/svn_status.txt"
+      ERROR_QUIET
+      OUTPUT_STRIP_TRAILING_WHITESPACE)
+    file (STRINGS "${OUTPUT_DIR}/svn_status.txt" __svn_changes
+      REGEX "^diff-tree"
+      )
+    if ((NOT ${__git_svn_status} EQUAL 0) OR __svn_changes)
+      message (WARNING "Source tree based on revision ${MY_WC_LAST_CHANGED_REV} appears to have local changes")
+      set (MY_WC_LAST_CHANGED_REV "${MY_WC_LAST_CHANGED_REV}-dirty")
+    endif ()
+    # write a file with the SVNVERSION define
+    file (WRITE "${OUTPUT_DIR}/svnversion.h.txt" "#define SVNVERSION r${MY_WC_LAST_CHANGED_REV}\n")
+  else (Subversion_FOUND AND EXISTS "${SOURCE_DIR}/.svn")
+    file (WRITE "${OUTPUT_DIR}/svnversion.h.txt" "#define SVNVERSION\n")
+  endif (Subversion_FOUND AND EXISTS "${SOURCE_DIR}/.git")
+endif (Subversion_FOUND AND EXISTS "${SOURCE_DIR}/.svn")
+
+# copy the file to the final header only if the version changes
+# reduces needless rebuilds
+execute_process (COMMAND ${CMAKE_COMMAND} -E copy_if_different "${OUTPUT_DIR}/svnversion.h.txt" "${OUTPUT_DIR}/svnversion.h")
diff --git a/CMakeCPackOptions.cmake.in b/CMakeCPackOptions.cmake.in
new file mode 100644
index 0000000..6b498be
--- /dev/null
+++ b/CMakeCPackOptions.cmake.in
@@ -0,0 +1,280 @@
+# This file is configured at cmake time, and loaded at cpack time.
+# To pass variables to cpack from cmake, they must be configured
+# in this file.
+
+set (CPACK_PACKAGE_VENDOR "@PROJECT_VENDOR@")
+set (CPACK_PACKAGE_CONTACT "@PROJECT_CONTACT@")
+set (CPACK_PACKAGE_DESCRIPTION_SUMMARY "@PROJECT_SUMMARY_DESCRIPTION@")
+set (CPACK_RESOURCE_FILE_LICENSE "@PROJECT_SOURCE_DIR@/COPYING")
+set (CPACK_PACKAGE_INSTALL_DIRECTORY ${CPACK_PACKAGE_NAME})
+set (CPACK_PACKAGE_EXECUTABLES wsjtx "@PROJECT_NAME@")
+set (CPACK_CREATE_DESKTOP_LINKS wsjtx)
+set (CPACK_STRIP_FILES TRUE)
+
+#
+# components
+#
+#set (CPACK_COMPONENTS_ALL runtime kvasd)
+#set (CPACK_COMPONENT_RUNTIME_DISPLAY_NAME "@PROJECT_NAME@ Application")
+#set (CPACK_COMPONENT_RUNTIME_DESCRIPTION "@WSJTX_DESCRIPTION_SUMMARY@")
+#set (CPACK_COMPONENT_KVASD_DISPLAY_NAME "KVASD Reed Solomon Decoder")
+#set (CPACK_COMPONENT_KVASD_DESCRIPTION "Optional decoder component")
+
+if (CPACK_GENERATOR MATCHES "NSIS")
+  set (CPACK_STRIP_FILES FALSE)	# breaks Qt packaging on Windows
+
+  set (CPACK_NSIS_INSTALL_ROOT "C:\\WSJT")
+
+  # set the install/unistall icon used for the installer itself
+  # There is a bug in NSI that does not handle full unix paths properly.
+  set (CPACK_NSIS_MUI_ICON "@PROJECT_SOURCE_DIR@/icons/windows-icons\\wsjtx.ico")
+  set (CPACK_NSIS_MUI_UNIICON "@PROJECT_SOURCE_DIR@/icons/windows-icons\\wsjtx.ico")
+  # set the package header icon for MUI
+  set (CPACK_PACKAGE_ICON "@PROJECT_SOURCE_DIR@/icons/windows-icons\\installer_logo.bmp")
+  # tell cpack to create links to the doc files
+  set (CPACK_NSIS_MENU_LINKS
+    "@PROJECT_MANUAL_DIRECTORY_URL@/@PROJECT_MANUAL@" "@PROJECT_NAME@ Documentation"
+    "@PROJECT_HOMEPAGE@" "@PROJECT_NAME@ Web Site"
+    )
+  # Use the icon from wsjtx for add-remove programs
+  set (CPACK_NSIS_INSTALLED_ICON_NAME "bin\\\\wsjtx.exe")
+
+  set (CPACK_NSIS_DISPLAY_NAME "${CPACK_PACKAGE_DESCRIPTION_SUMMARY}")
+  set (CPACK_NSIS_HELP_LINK "@PROJECT_MANUAL_DIRECTORY_URL@/@PROJECT_MANUAL@")
+  set (CPACK_NSIS_URL_INFO_ABOUT "@PROJECT_HOMEPAGE@")
+  set (CPACK_NSIS_CONTACT "${CPACK_PACKAGE_CONTACT}")
+  set (CPACK_NSIS_MUI_FINISHPAGE_RUN "wsjtx.exe")
+  set (CPACK_NSIS_MODIFY_PATH ON)
+
+  set (CPACK_NSIS_EXTRA_DEFINES "
+    ;
+    ; enable local plugins
+    ;
+    !ifdef NSIS_WIN32_MAKENSIS
+      !define NSISCONF_3 ';' ; NSIS 2 tries to parse some preprocessor instructions inside \"!if 0\" blocks!
+      !addincludedir '@CMAKE_CURRENT_SOURCE_DIR@\\contrib\\NSIS\\Include'
+      !if \${NSIS_PACKEDVERSION} > 0x02ffffff ; NSIS 3+:
+        !define /redef NSISCONF_3 ''
+    \${NSISCONF_3}  !addplugindir /x86-ansi '@CMAKE_CURRENT_SOURCE_DIR@\\contrib\\NSIS\\Plugins-i386-ansi'
+    \${NSISCONF_3}  !addplugindir /x86-unicode '@CMAKE_CURRENT_SOURCE_DIR@\\contrib\\NSIS\\Plugins-i386-unicode'
+      !else ; NSIS 2:
+        !addplugindir '@CMAKE_CURRENT_SOURCE_DIR@\\contrib\\NSIS\\Plugins-i386-ansi'
+      !endif ;~ NSIS_PACKEDVERSION
+      !undef NSISCONF_3
+    !endif ;~ NSIS_WIN32_MAKENSIS
+
+    ; global variables
+    Var KVASD_EXECUTABLE
+    Var CB_INSTALL_KVASD
+    Var INSTALL_KVASD
+    Var RichEditLicense
+    Var CheckBoxAgree
+    Var KVASD_LICENSE
+
+    ; page callbacks
+    Function KVASD_page_create
+      Push $R0
+
+      \${If} $INSTALL_KVASD = \${BST_CHECKED}
+          \${AndIfNot} \${FileExists} $KVASD_LICENSE
+        GetTempFileName $KVASD_LICENSE
+retry_eula:
+        NSISdl::download /TIMEOUT=30000 @PROJECT_KVASD_URL@/kvasd_eula.txt $KVASD_LICENSE
+        Pop $R0
+        \${If} $R0 != success
+          MessageBox MB_RETRYCANCEL|MB_ICONQUESTION 'Download: @PROJECT_KVASD_URL@/kvasd_eula.txt$\\nFailed: $R0' IDRETRY retry_eula
+          StrCpy $INSTALL_KVASD \${BST_UNCHECKED}
+          Delete $KVASD_LICENSE
+        \${EndIf}
+      \${EndIf}
+
+      \${If} $INSTALL_KVASD = \${BST_CHECKED}
+          \${AndIf} \${FileExists} $KVASD_LICENSE
+        !insertmacro MUI_HEADER_TEXT `$(MUI_TEXT_LICENSE_TITLE)` `Please agree the terms of this license before installing KVASD`
+
+        ; disable install button until agreed
+        GetDlgItem $R0 $HWNDPARENT 1
+        EnableWindow $R0 0
+
+        nsDialogs::Create 1018
+        Pop $R0
+;        \${If} $R0 == error
+;          Abort
+;        \${EndIf}
+
+        nsDialogs::CreateControl RichEdit20A \${WS_VISIBLE}|\${WS_CHILD}|\${WS_TABSTOP}|\${WS_VSCROLL}|\${ES_MULTILINE}|\${ES_READONLY} \${__NSD_Text_EXSTYLE} 0 0 100% -24u ''
+        Pop $RichEditLicense
+
+        nsRichEdit::Load $RichEditLicense $KVASD_LICENSE
+
+        \${NSD_CreateCheckBox} 0 -20u 160u 12u `$(^AcceptBtn)`
+        Pop $CheckBoxAgree
+        \${NSD_OnClick} $CheckBoxAgree KVASD_Page_CheckBoxAgree_Click
+        nsDialogs::Show
+      \${Else}
+        Abort ; skip page
+      \${EndIf}
+
+      Pop $R0
+    FunctionEnd
+
+    Function KVASD_page_leave
+    FunctionEnd
+
+    ; field callbacks
+    Function KVASD_Page_CheckBoxAgree_Click
+      Pop $0
+
+      \${NSD_GetState} $CheckBoxAgree $R0
+      \${If} $R0 = \${BST_CHECKED}
+        GetDlgItem $R0 $HWNDPARENT 1
+        EnableWindow $R0 1
+      \${Else}
+        GetDlgItem $R0 $HWNDPARENT 1
+        EnableWindow $R0 0
+      \${EndIf}
+    FunctionEnd"
+    )
+
+  set (CPACK_NSIS_EXTRA_INIT_COMMANDS "
+    ; initial value of $INSATLL_KVASD chack box
+    IntOp $INSTALL_KVASD 0 + \${BST_CHECKED}"
+    )
+
+  set (CPACK_NSIS_EXTRA_PAGES "
+    ; custom page for KVASD license display and acceptance
+    Page custom KVASD_page_create KVASD_page_leave"
+    )
+
+  set (CPACK_NSIS_EXTRA_INSTALL_OPTIONS "
+    ; add a chackbox for installing KVASD
+    \${NSD_CreateCheckBox} 0u 110u 100% 10u 'Install the optional KVASD decoder'
+    Pop $CB_INSTALL_KVASD
+    \${NSD_SetState} $CB_INSTALL_KVASD $INSTALL_KVASD"
+    )
+
+  set (CPACK_NSIS_EXTRA_INSTALL_OPTIONS_READ "
+    \${NSD_GetState} $CB_INSTALL_KVASD $INSTALL_KVASD"
+    )
+
+  set (CPACK_NSIS_EXTRA_PREINSTALL_COMMANDS "
+    \${If} $INSTALL_KVASD = \${BST_CHECKED}
+      ;
+      ; fetch KVASD license
+      ;
+      StrCpy $5 @PROJECT_KVASD_URL@/@SYSTEM_NAME@/kvasd at CMAKE_EXECUTABLE_SUFFIX@
+      GetTempFileName $1
+retry:
+      NSISdl::download /TIMEOUT=30000 $5.md5 $1
+      Pop $R0
+      \${If} $R0 != success
+        MessageBox MB_RETRYCANCEL|MB_ICONQUESTION 'Download: $5.md5$\\nFailed: $R0' IDRETRY retry
+        Abort
+      \${EndIf}
+      ClearErrors
+      FileOpen $2 $1 r
+      \${If} \${Errors}
+        MessageBox MB_RETRYCANCEL|MB_ICONQUESTION 'Failed to read MD5 hash file: $5.md5' IDRETRY retry
+        Abort
+      \${EndIf}
+
+      ; extract MD5 hash
+      FileRead $2 $3 32
+      FileClose $2
+
+      ;
+      ; fetch kvasd executable
+      ;
+      GetTempFileName $KVASD_EXECUTABLE  
+      NSISdl::download /TIMEOUT=30000 $5 $KVASD_EXECUTABLE
+      Pop $R0
+      \${If} $R0 != success
+        MessageBox MB_RETRYCANCEL|MB_ICONQUESTION 'Download: $5$\\nFailed: $R0' IDRETRY retry
+        Abort
+      \${EndIf}
+
+      ; calculate MD5 hash
+      md5dll::GetMD5File $KVASD_EXECUTABLE
+      Pop $0
+
+      \${If} $3 != $0
+        MessageBox MB_RETRYCANCEL|MB_ICONQUESTION 'MD5 hash check failed on: $5$\\nExpected: [$4]$\\n  Actual: [$0]' IDRETRY retry
+        Abort
+      \${EndIf}
+
+skip_kvasd:
+      Delete $1 ; MD5 hash file
+    \${EndIf}
+
+    ; save $INSTALL_KVASD to registry for use in teh un-installer
+    WriteRegDWORD SHCTX 'Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\${CPACK_PACKAGE_INSTALL_REGISTRY_KEY}' \\
+      'InstallKvasd' $INSTALL_KVASD"
+    )
+
+  set (CPACK_NSIS_EXTRA_INSTALL_COMMANDS "
+    ; install the kvasd executable and ensure it can be executed
+    \${If} $INSTALL_KVASD = \${BST_CHECKED}
+        \${AndIf} \${FileExists} $KVASD_EXECUTABLE
+      DetailPrint 'Installing: $INSTDIR\\@WSJT_BIN_DESTINATION@\\kvasd at CMAKE_EXECUTABLE_SUFFIX@'
+      Rename $KVASD_EXECUTABLE '$INSTDIR\\@WSJT_BIN_DESTINATION@\\kvasd at CMAKE_EXECUTABLE_SUFFIX@'
+      AccessControl::ClearOnFile '$INSTDIR\\@WSJT_BIN_DESTINATION@\\kvasd at CMAKE_EXECUTABLE_SUFFIX@' '(BU)' 'GenericRead + GenericExecute'
+      Pop $R0
+      \${If} $R0 != ok
+        Pop $R0
+        MessageBox MB_OK 'Failed to set KVASD file permissions.\\n$R0'
+        Abort
+      \${EndIf}
+    \${EndIf}"
+    )
+
+  set (CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS "
+    ; fetch $INSTALL_KVASD from registry
+    ReadRegDWORD $INSTALL_KVASD SHCTX \\
+      'Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\${CPACK_PACKAGE_INSTALL_REGISTRY_KEY}' 'InstallKvasd'
+
+    ; conditionally un-install the kvasd executable
+    \${If} $INSTALL_KVASD = \${BST_CHECKED}
+      Delete '$INSTDIR\\@WSJT_BIN_DESTINATION@\\kvasd at CMAKE_EXECUTABLE_SUFFIX@'
+    \${EndIf}"
+    )
+endif ()
+
+if ("${CPACK_GENERATOR}" STREQUAL "PackageMaker")
+  set (CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}-pkg")
+  set (CPACK_PACKAGE_DEFAULT_LOCATION "/Applications")
+  set (CPACK_PACKAGING_INSTALL_PREFIX "/")
+endif ()
+
+if ("${CPACK_GENERATOR}" STREQUAL "DragNDrop")
+  set (CPACK_DMG_VOLUME_NAME "@PROJECT_NAME@")
+  set (CPACK_DMG_BACKGROUND_IMAGE "@PROJECT_SOURCE_DIR@/icons/Darwin/DragNDrop Background.png")
+  set (CPACK_DMG_DS_STORE "@PROJECT_SOURCE_DIR@/Darwin/wsjtx_DMG.DS_Store")
+  set (CPACK_BUNDLE_NAME "@WSJTX_BUNDLE_NAME@")
+  set (CPACK_PACKAGE_ICON "@PROJECT_BINARY_DIR@/wsjtx.icns")
+  set (CPACK_BUNDLE_ICON "@PROJECT_BINARY_DIR@/wsjtx.icns")
+  set (CPACK_BUNDLE_STARTUP_COMMAND "@PROJECT_SOURCE_DIR@/Mac-wsjtx-startup.sh")
+endif ()
+
+if ("${CPACK_GENERATOR}" STREQUAL "WIX")
+  # Reset CPACK_PACKAGE_VERSION to deal with WiX restriction.
+  # But the file names still use the full CMake_VERSION value:
+  set (CPACK_PACKAGE_FILE_NAME
+    "${CPACK_PACKAGE_NAME}- at wsjtx_VERSION@-${CPACK_SYSTEM_NAME}")
+  set (CPACK_SOURCE_PACKAGE_FILE_NAME
+    "${CPACK_PACKAGE_NAME}- at wsjtx_VERSION@-Source")
+
+  if (NOT CPACK_WIX_SIZEOF_VOID_P)
+    set (CPACK_WIX_SIZEOF_VOID_P "@CMAKE_SIZEOF_VOID_P@")
+  endif ()
+endif ()
+
+if ("${CPACK_GENERATOR}" STREQUAL "DEB")
+  set (CPACK_PACKAGE_FILE_NAME ${CPACK_PACKAGE_NAME}_${CPACK_PACKAGE_VERSION}_${CPACK_DEBIAN_PACKAGE_ARCHITECTURE})
+  set (CPACK_COMPONENTS_ALL ${CPACK_COMPONENTS_ALL} Debian)
+endif ("${CPACK_GENERATOR}" STREQUAL "DEB")
+
+if ("${CPACK_GENERATOR}" STREQUAL "RPM")
+  set (CPACK_PACKAGE_FILE_NAME ${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}.${CPACK_RPM_PACKAGE_ARCHITECTURE})
+endif ("${CPACK_GENERATOR}" STREQUAL "RPM")
+
+message (STATUS "CMAKE_INSTALL_PREFIX: ${CMAKE_INSTALL_PREFIX}")
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..24e45f3
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,1245 @@
+cmake_minimum_required (VERSION 2.8.10 FATAL_ERROR)
+
+if (APPLE)
+  #
+  # The following variables define the portability and compatability attributes of the Mac OS X build
+  # they are choosen with care and should not be changed without good cause. Note that they preclude
+  # doing a default build on OS X 10.7 since there is no 10.9 SDK available for Mac OS X 10.7. This doesn't
+  # preclude builds on newer versions of OS X being installed on Mac OS X 10.7, in fact it is exacty these
+  # options that ensure offcial build run on 10.7 and newer versions of Mac OS X. At some point it may
+  # be that some new version cannot be supported as well as 10.7, at that point the deployment target below
+  # must be moved on to 10.8 and we can no longer support Mac OS X 10.7.
+  #
+  # Among other things these options are chosen to match the portability and compatability options of the
+  # Qt framework dylibs which can be checked as follows:
+  #
+  # otool -l <binary> | grep -A3 LC_VERSION_MIN_MACOSX
+  #
+  set (CMAKE_OSX_DEPLOYMENT_TARGET 10.7
+    CACHE STRING "Earliest version of OS X supported
+
+Earliest version we can support with C++11 & libc++ is 10.7.
+Do not override this if you intend to build an official deployable installer.")
+  set (CMAKE_OSX_SYSROOT /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk
+    CACHE STRING "Mac OS X SDK to build with
+
+Change this to the newest SDK available that you can install on your system (10.9 preferred).
+Do not override this if you intend to build an official deployable installer.")
+endif (APPLE)
+
+project (wsjtx C CXX Fortran)
+
+#
+# CMake policies
+#
+if (POLICY CMP0020)
+  cmake_policy (SET CMP0020 NEW) # link to Qt winmain on Windows
+endif (POLICY CMP0020)
+
+if (POLICY CMP0043)
+  cmake_policy (SET CMP0043 NEW) # ignore COMPILE_DEFINITIONS_<CONFIG>
+endif (POLICY CMP0043)
+
+
+include (${PROJECT_SOURCE_DIR}/CMake/VersionCompute.cmake)
+message (STATUS "Building ${CMAKE_PROJECT_NAME}-${wsjtx_VERSION}")
+
+#
+# project information
+#
+set (PROJECT_NAME "WSJT-X")
+set (PROJECT_VENDOR "Joe Taylor, K1JT")
+set (PROJECT_CONTACT "Joe Taylor <k1jt at arrl.net>")
+set (PROJECT_COPYRIGHT "Copyright (C) 2001-2014 by Joe Taylor, K1JT")
+set (PROJECT_HOMEPAGE "http://www.physics.princeton.edu/pulsar/K1JT/wsjtx.html")
+set (PROJECT_MANUAL wsjtx-main-${wsjtx_VERSION}.html)
+set (PROJECT_MANUAL_DIRECTORY_URL http://www.physics.princeton.edu/pulsar/K1JT/wsjtx-doc)
+set (PROJECT_SUMMARY_DESCRIPTION "${PROJECT_NAME} - JT9 and JT65 Modes for LF, MF and HF Amateur Radio.")
+set (PROJECT_DESCRIPTION "${PROJECT_SUMMARY_DESCRIPTION}
+ ${PROJECT_NAME} implements JT9, a new mode designed especially for the LF, MF,
+ and HF bands, as well as the popular mode JT65. Both modes were
+ designed for making reliable, confirmed QSOs under extreme
+ weak-signal conditions. They use nearly identical message structure
+ and source encoding. JT65 was designed for EME (“moonbounce”) on the
+ VHF/UHF bands and has also proved very effective for worldwide QRP
+ communication at HF; in contrast, JT9 is optimized for HF and lower
+ frequencies. JT9 is about 2 dB more sensitive than JT65A while using
+ less than 10% of the bandwidth. World-wide QSOs are possible with
+ power levels of a few watts and compromise antennas. A 2 kHz slice
+ of spectrum is essentially full when occupied by ten JT65 signals.
+ As many as 100 JT9 signals can fit into the same space, without
+ overlap.
+ .
+ ${PROJECT_NAME} offers a “bi-lingual“ operating mode in which you can transmit
+ and receive JT65 and JT9 signals, switching between modes
+ automatically as needed. Displayed bandwidth can be as large as 5
+ kHz. If your receiver has as upper-sideband filter at least 4 kHz
+ wide, you can have all the typical JT65 and JT9 activity on screen at
+ once, available for making QSOs with a click of the mouse. Even with
+ standard SSB-width IF filters, switching between JT65 and JT9 modes
+ is quick and convenient. Be sure to read the online ${PROJECT_NAME} User's
+ Guide.")
+set (PROJECT_KVASD_URL http://svn.code.sf.net/p/wsjt/wsjt/trunk/kvasd-binary)
+
+set (CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/CMake/Modules ${CMAKE_MODULE_PATH})
+
+# make sure that the default configuration is a RELEASE
+if (NOT CMAKE_BUILD_TYPE)
+  set (CMAKE_BUILD_TYPE RELEASE CACHE STRING
+    "Choose the type of build, options are: None Debug Release."
+    FORCE)
+endif (NOT CMAKE_BUILD_TYPE)
+if (CMAKE_BUILD_TYPE MATCHES "[Dd][Ee][Bb][Uu][Gg]")
+  set (is_debug_build 1)
+endif ()
+
+
+#
+# Options & features
+#
+#	Some of these directly effect compilation by being defined in
+#	wsjtx_config.h.in which makes them available to the C/C++
+#	pre-processor.
+#
+include (CMakeDependentOption)
+
+option (UPDATE_TRANSLATIONS "Update source translation translations/*.ts
+files (WARNING: make clean will delete the source .ts files! Danger!)")
+option (WSJT_SHARED_RUNTIME "Debugging option that allows running from a shared Cloud directory.")
+option (WSJT_QDEBUG_TO_FILE "Redirect Qt debuging messages to a trace file.")
+option (WSJT_TRACE_CAT "Debugging option that turns on CAT diagnostics.")
+option (WSJT_TRACE_CAT_POLLS "Debugging option that turns on CAT diagnostics during polling.")
+option (WSJT_HAMLIB_TRACE "Debugging option that turns on minimal Hamlib internal diagnostics.")
+option (WSJT_SOFT_KEYING "Apply a ramp to CW keying envelope to reduce transients." ON)
+option (WSJT_SKIP_MANPAGES "Skip *nix manpage generation.")
+option (WSJT_EMBED_SAMPLES "Embed sample files into WSJT-X resources." ON)
+option (WSJT_GENERATE_DOCS "Generate documentation files." ON)
+
+CMAKE_DEPENDENT_OPTION (WSJT_HAMLIB_VERBOSE_TRACE "Debugging option that turns on full Hamlib internal diagnostics." OFF WSJT_HAMLIB_TRACE OFF)
+CMAKE_DEPENDENT_OPTION (WSJT_QDEBUG_IN_RELEASE "Leave Qt debugging statements in Release configuration." OFF
+  "NOT is_debug_build" OFF)
+CMAKE_DEPENDENT_OPTION (WSJT_ENABLE_EXPERIMENTAL_FEATURES "Enable features not fully ready for public releases." ON
+  is_debug_build OFF)
+CMAKE_DEPENDENT_OPTION (WSJT_CREATE_WINMAIN
+  "The wsjtx target is normally built as GUI executable with a WinMain entry point on Windows,
+if you want a console application instead then set this option to OFF.
+
+If you just want to see the debug output from the application then the easiest way is to
+attach a debugger which will then receive the console output inside its console." ON
+  "WIN32" OFF)
+
+#
+# decide if we are bundling kvasd (non-FOSS)
+#
+CMAKE_DEPENDENT_OPTION (WSJT_INCLUDE_KVASD "Include kvasd in the package." OFF
+  "NOT is_debug_build" ON)
+
+
+set (PROJECT_ARCHITECTURE "${CMAKE_SYSTEM_PROCESSOR}")
+if (NOT PROJECT_ARCHITECTURE)
+  # This is supposed to happen already on Windows
+  set (PROJECT_ARCHITECTURE "$ENV{PROCESSOR_ARCHITECTURE}")
+endif (NOT PROJECT_ARCHITECTURE)
+message (STATUS "******************************************************")
+message (STATUS "Building for for: ${CMAKE_SYSTEM_NAME}-${PROJECT_ARCHITECTURE}")
+message (STATUS "******************************************************")
+
+
+#
+# install locations
+#
+set (WSJT_BIN_DESTINATION bin)
+set (WSJT_LIB_DESTINATION lib)
+set (WSJT_SHARE_DESTINATION share)
+set (WSJT_DOC_DESTINATION doc/${CMAKE_PROJECT_NAME})
+set (WSJT_MANPAGE_DESTINATION share)
+set (WSJT_PLUGIN_DESTINATION lib/plugins)
+set (WSJT_QT_CONF_DESTINATION bin)
+
+if (WIN32)
+  set (WSJT_SHARE_DESTINATION bin)
+  set (WSJT_DOC_DESTINATION doc)
+  set (WSJT_PLUGIN_DESTINATION plugins)
+endif (WIN32)
+
+if (APPLE)
+  set (WSJT_BIN_DESTINATION ${CMAKE_PROJECT_NAME}.app/Contents/MacOS)
+  set (WSJT_SHARE_DESTINATION ${CMAKE_PROJECT_NAME}.app/Contents/Resources)
+  set (WSJT_MANPAGE_DESTINATION ${CMAKE_PROJECT_NAME}.app/Contents/Resources)
+  set (WSJT_DOC_DESTINATION doc)
+  set (WSJT_PLUGIN_DESTINATION ${CMAKE_PROJECT_NAME}.app/Contents/PlugIns)
+  set (WSJT_QT_CONF_DESTINATION ${CMAKE_PROJECT_NAME}.app/Contents/Resources)
+endif (APPLE)
+
+
+#
+# Project sources
+#
+set (wsjt_qt_CXXSRCS
+  qt_helpers.cpp
+  NetworkServerLookup.cpp
+  revision_utils.cpp
+  WFPalette.cpp
+  Radio.cpp
+  Bands.cpp
+  FrequencyList.cpp
+  StationList.cpp
+  FrequencyLineEdit.cpp
+  FrequencyItemDelegate.cpp
+  CandidateKeyFilter.cpp
+  ForeignKeyDelegate.cpp
+  LiveFrequencyValidator.cpp
+  GetUserId.cpp
+  TraceFile.cpp
+  AudioDevice.cpp
+  Transceiver.cpp
+  TransceiverBase.cpp
+  EmulateSplitTransceiver.cpp
+  TransceiverFactory.cpp
+  PollingTransceiver.cpp
+  HamlibTransceiver.cpp
+  HRDTransceiver.cpp
+  DXLabSuiteCommanderTransceiver.cpp
+  NetworkMessage.cpp
+  MessageClient.cpp
+  )
+
+set (jt9_CXXSRCS
+  lib/ipcomm.cpp
+  )
+
+set (wsjtx_CXXSRCS
+  logbook/adif.cpp
+  logbook/countrydat.cpp
+  logbook/countriesworked.cpp
+  logbook/logbook.cpp
+  psk_reporter.cpp
+  Modulator.cpp
+  Detector.cpp
+  logqso.cpp
+  displaytext.cpp
+  decodedtext.cpp
+  getfile.cpp
+  soundout.cpp
+  soundin.cpp
+  meterwidget.cpp
+  signalmeter.cpp
+  plotter.cpp
+  widegraph.cpp
+  about.cpp
+  astro.cpp
+  mainwindow.cpp
+  Configuration.cpp
+  main.cpp
+  )
+
+if (WIN32)
+  set (wsjt_CXXSRCS
+    ${wsjt_CXXSRCS}
+    killbyname.cpp
+    )
+
+  set (wsjt_qt_CXXSRCS
+    ${wsjt_qt_CXXSRCS}
+    OmniRigTransceiver.cpp
+    )
+endif (WIN32)
+
+set (wsjt_FSRCS
+  lib/afc65b.f90
+  lib/afc9.f90
+  lib/analytic.f90
+  lib/astro.f90
+  lib/astrosub.f90
+  lib/astro0.f90
+  lib/azdist.f90
+  lib/baddata.f90
+  lib/ccf2.f90
+  lib/ccf65.f90
+  lib/chkhist.f90
+  lib/chkmsg.f90
+  lib/chkss2.f90
+  lib/coord.f90
+  lib/db.f90
+  lib/dcoord.f90
+  lib/decode65a.f90
+  lib/decode65b.f90
+  lib/fftw3mod.f90
+  lib/jt9fano.f90
+  lib/decoder.f90
+  lib/decjt9.f90
+  lib/deg2grid.f90
+  lib/demod64a.f90
+  lib/determ.f90
+  lib/dot.f90
+  lib/downsam9.f90
+  lib/encode232.f90
+  lib/entail.f90
+  lib/extract.F90
+  lib/geocentric.f90
+  lib/fano232.f90
+  lib/fchisq.f90
+  lib/fchisq65.f90
+  lib/fil3.f90
+  lib/fil4.f90
+  lib/fil6521.f90
+  lib/filbig.f90
+  lib/fillcom.f90
+  lib/flat1.f90
+  lib/flat2.f90
+  lib/flat4.f90
+  lib/flat65.f90
+  lib/four2a.f90
+  lib/fmtmsg.f90
+  lib/gen65.f90
+  lib/genjt9.f90
+  lib/geodist.f90
+  lib/getlags.f90
+  lib/getpfx1.f90
+  lib/getpfx2.f90
+  lib/graycode.f90
+  lib/graycode65.f90
+  lib/grid2deg.f90
+  lib/grid2k.f90
+  lib/grid2n.f90
+  lib/indexx.f90
+  lib/interleave63.f90
+  lib/interleave9.f90
+  lib/jt65a.f90
+  lib/k2grid.f90
+  lib/moon2.f90
+  lib/moondop.f90
+  lib/morse.f90
+  lib/move.f90
+  lib/n2grid.f90
+  lib/nchar.f90
+  lib/options.f90
+  lib/packbits.f90
+  lib/packcall.f90
+  lib/packgrid.f90
+  lib/packmsg.f90
+  lib/packtext.f90
+  lib/pctile.f90
+  lib/peakdt9.f90
+  lib/pfxdump.f90
+  lib/polfit.f90
+  lib/prog_args.f90
+  lib/sec_midn.f90
+  lib/setup65.f90
+  lib/sleep_msec.f90
+  lib/smo.f90
+  lib/smo121.f90
+  lib/softsym.f90
+  lib/sort.f90
+  lib/stdmsg.f90
+  lib/sun.f90
+  lib/symspec.f90
+  lib/symspec2.f90
+  lib/symspec65.f90
+  lib/sync9.f90
+  lib/timer.f90
+  lib/tm2.f90
+  lib/toxyz.f90
+  lib/twkfreq.f90
+  lib/twkfreq65.f90
+  lib/unpackbits.f90
+  lib/unpackcall.f90
+  lib/unpackgrid.f90
+  lib/unpackmsg.f90
+  lib/unpacktext.f90
+  lib/wavhdr.f90
+  lib/zplot9.f90
+  )
+
+set (wsjt_CSRCS
+  lib/decode_rs.c
+  lib/encode_rs.c
+  lib/gran.c
+  lib/igray.c
+  lib/init_rs.c
+  lib/tmoonsub.c
+  lib/usleep.c
+  lib/wisdom.c
+  lib/wrapkarn.c
+  )
+
+set (wsjt_qt_UISRCS
+  wf_palette_design_dialog.ui
+  )
+
+set (wsjtx_UISRCS
+  mainwindow.ui
+  about.ui
+  astro.ui
+  widegraph.ui
+  logqso.ui
+  Configuration.ui
+  )
+
+set (message_aggregator_CXXSRCS
+  MessageServer.cpp
+  MessageAggregator.cpp
+  )
+
+set (all_CXXSRCS
+  ${wsjt_CXXSRCS}
+  ${wsjt_qt_CXXSRCS}
+  ${jt9_CXXSRCS}
+  ${wsjtx_CXXSRCS}
+  ${message_aggregator_CXXSRCS}
+  )
+
+set (all_C_and_CXXSRCS
+  ${wsjt_CSRCS}
+  ${all_CXXSRCS}
+  )
+
+set (message_aggregator_STYLESHEETS
+  qss/default.qss
+  )
+
+set (TOP_LEVEL_RESOURCES
+  shortcuts.txt
+  mouse_commands.txt
+  prefixes.txt
+  cty.dat
+  )
+
+set (PALETTE_FILES
+  Palettes/Banana.pal
+  Palettes/Blue1.pal
+  Palettes/Blue2.pal
+  Palettes/Blue3.pal
+  Palettes/Brown.pal
+  Palettes/Cyan1.pal
+  Palettes/Cyan2.pal
+  Palettes/Cyan3.pal
+  Palettes/Default.pal
+  Palettes/Digipan.pal
+  Palettes/Fldigi.pal
+  Palettes/Gray1.pal
+  Palettes/Gray2.pal
+  Palettes/Green1.pal
+  Palettes/Green2.pal
+  Palettes/Jungle.pal
+  Palettes/Linrad.pal
+  Palettes/Negative.pal
+  Palettes/Orange.pal
+  Palettes/Pink.pal
+  Palettes/Rainbow.pal
+  Palettes/Scope.pal
+  Palettes/Sunburst.pal
+  Palettes/VK4BDJ.pal
+  Palettes/YL2KF.pal
+  Palettes/Yellow1.pal
+  Palettes/Yellow2.pal
+  Palettes/ZL1FZ.pal
+)
+
+set (SAMPLE_FILES
+  samples/130418_1742.wav
+  samples/130610_2343.wav
+  )
+
+if (APPLE)
+  set (WSJTX_ICON_FILE ${CMAKE_PROJECT_NAME}.icns)
+  set (ICONSRCS
+    icons/Darwin/${CMAKE_PROJECT_NAME}.iconset/icon_16x16.png
+    icons/Darwin/${CMAKE_PROJECT_NAME}.iconset/icon_16x16 at 2x.png
+    icons/Darwin/${CMAKE_PROJECT_NAME}.iconset/icon_32x32.png
+    icons/Darwin/${CMAKE_PROJECT_NAME}.iconset/icon_32x32 at 2x.png
+    icons/Darwin/${CMAKE_PROJECT_NAME}.iconset/icon_128x128.png
+    icons/Darwin/${CMAKE_PROJECT_NAME}.iconset/icon_128x128 at 2x.png
+    icons/Darwin/${CMAKE_PROJECT_NAME}.iconset/icon_256x256.png
+    icons/Darwin/${CMAKE_PROJECT_NAME}.iconset/icon_256x256 at 2x.png
+    icons/Darwin/${CMAKE_PROJECT_NAME}.iconset/icon_512x512.png
+    icons/Darwin/${CMAKE_PROJECT_NAME}.iconset/icon_512x512 at 2x.png
+    )
+  add_custom_command (
+    OUTPUT ${WSJTX_ICON_FILE}
+    COMMAND iconutil -c icns --output "${CMAKE_BINARY_DIR}/${WSJTX_ICON_FILE}" "${CMAKE_SOURCE_DIR}/icons/Darwin/${CMAKE_PROJECT_NAME}.iconset"
+    DEPENDS ${ICONSRCS}
+    COMMENT "Building Icons"
+    )
+endif (APPLE)
+
+set_source_files_properties (${WSJTX_ICON_FILE} PROPERTIES MACOSX_PACKAGE_LOCATION Resources)
+
+if (NOT WSJT_QDEBUG_IN_RELEASE)
+  set_property (DIRECTORY APPEND PROPERTY
+    COMPILE_DEFINITIONS $<$<NOT:$<CONFIG:Debug>>:QT_NO_DEBUG_OUTPUT;QT_NO_WARNING_OUTPUT>
+    )
+endif (NOT WSJT_QDEBUG_IN_RELEASE)
+
+set_property (SOURCE ${all_C_and_CXXSRCS} APPEND_STRING PROPERTY COMPILE_FLAGS " -include wsjtx_config.h")
+set_property (SOURCE ${all_C_and_CXXSRCS} APPEND PROPERTY OBJECT_DEPENDS wsjtx_config.h)
+
+if (WIN32)
+  # generate the OmniRig COM interface source
+  find_program (DUMPCPP dumpcpp)
+  if (DUMPCPP-NOTFOUND)
+    message (FATAL_ERROR "dumpcpp tool not found")
+  endif (DUMPCPP-NOTFOUND)
+  execute_process (
+    COMMAND ${DUMPCPP} -getfile {4FE359C5-A58F-459D-BE95-CA559FB4F270}
+    OUTPUT_VARIABLE AXSERVER
+    OUTPUT_STRIP_TRAILING_WHITESPACE
+    )
+  string (STRIP "${AXSERVER}" AXSERVER)
+  if (NOT AXSERVER)
+    message (FATAL_ERROR "You need to install OmniRig on this computer")
+  endif (NOT AXSERVER)
+  string (REPLACE "\"" "" AXSERVER ${AXSERVER})
+  file (TO_CMAKE_PATH ${AXSERVER} AXSERVERSRCS)
+endif (WIN32)
+
+
+#
+# decide on platform specifc packing and fixing up
+#
+if (APPLE)
+  set (WSJTX_BUNDLE_VERSION ${wsjtx_VERSION})
+
+  # make sure CMAKE_INSTALL_PREFIX ends in /
+  string (LENGTH "${CMAKE_INSTALL_PREFIX}" LEN)
+  math (EXPR LEN "${LEN} -1" )
+  string (SUBSTRING "${CMAKE_INSTALL_PREFIX}" ${LEN} 1 ENDCH)
+  if (NOT "${ENDCH}" STREQUAL "/")
+    set (CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}/")
+  endif ()
+endif (APPLE)
+
+
+#
+# find some useful tools
+#
+find_program(CTAGS ctags)
+find_program(ETAGS etags)
+if (WSJT_GENERATE_DOCS)
+  add_subdirectory (doc)
+endif (WSJT_GENERATE_DOCS)
+
+#
+# C & C++ setup
+#
+set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra")
+
+set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -std=c++11 -fexceptions -frtti")
+
+if (NOT APPLE)
+  set (CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -fdata-sections -ffunction-sections")
+  set (CMAKE_C_FLAGS_MINSIZEREL "${CMAKE_C_FLAGS_MINSIZEREL} -fdata-sections -ffunction-sections")
+  set (CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fdata-sections -ffunction-sections")
+  set (CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} -fdata-sections -ffunction-sections")
+endif (NOT APPLE)
+
+if (WIN32)
+  set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-keep-inline-dllexport")
+endif (WIN32)
+if (APPLE)
+  if (${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang")
+    set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
+  endif (${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang")
+else (APPLE)
+  set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pthread")
+  set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
+endif (APPLE)
+
+
+#
+# Fortran setup
+#
+set (General_FFLAGS "-Wall -Wno-conversion -fno-second-underscore")
+
+# FFLAGS depend on the compiler
+get_filename_component (Fortran_COMPILER_NAME ${CMAKE_Fortran_COMPILER} NAME)
+
+if (Fortran_COMPILER_NAME MATCHES "gfortran.*")
+  # gfortran
+
+  # CMake compiler test is supposed to do this but doesn't yet
+  if (CMAKE_OSX_DEPLOYMENT_TARGET)
+    set (CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET}")
+  endif (CMAKE_OSX_DEPLOYMENT_TARGET)
+  if (CMAKE_OSX_SYSROOT)
+    set (CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -isysroot ${CMAKE_OSX_SYSROOT}")
+  endif (CMAKE_OSX_SYSROOT)
+
+  set (CMAKE_Fortran_FLAGS_RELEASE "${CMAKE_Fortran_FLAGS_RELEASE} -funroll-all-loops -fno-f2c ${General_FFLAGS}")
+  set (CMAKE_Fortran_FLAGS_DEBUG   "${CMAKE_Fortran_FLAGS_DEBUG} -fbounds-check -fno-f2c ${General_FFLAGS}")
+elseif (Fortran_COMPILER_NAME MATCHES "ifort.*")
+  # ifort (untested)
+  set (CMAKE_Fortran_FLAGS_RELEASE "${CMAKE_Fortran_FLAGS_RELEASE} -f77rtl ${General_FFLAGS}")
+  set (CMAKE_Fortran_FLAGS_DEBUG   "${CMAKE_Fortran_FLAGS_DEBUG} -f77rtl ${General_FFLAGS}")
+elseif (Fortran_COMPILER_NAME MATCHES "g77")
+  # g77
+  set (CMAKE_Fortran_FLAGS_RELEASE "${CMAKE_Fortran_FLAGS_RELEASE} -funroll-all-loops -fno-f2c -m32 ${General_FFLAGS}")
+  set (CMAKE_Fortran_FLAGS_DEBUG   "${CMAKE_Fortran_FLAGS_DEBUG} -fbounds-check -fno-f2c -m32 ${General_FFLAGS}")
+else (Fortran_COMPILER_NAME MATCHES "gfortran.*")
+  message ("CMAKE_Fortran_COMPILER full path: " ${CMAKE_Fortran_COMPILER})
+  message ("Fortran compiler: " ${Fortran_COMPILER_NAME})
+  message ("No optimized Fortran compiler flags are known, we just try -O3...")
+  set (CMAKE_Fortran_FLAGS_RELEASE "${CMAKE_Fortran_FLAGS_RELEASE} -O3 ${General_FFLAGS}")
+  set (CMAKE_Fortran_FLAGS_DEBUG   "${CMAKE_Fortran_FLAGS_DEBUG} -fbounds-check ${General_FFLAGS}")
+endif (Fortran_COMPILER_NAME MATCHES "gfortran.*")
+
+
+#
+# Linker setup
+#
+if (NOT APPLE)
+  set (CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} -Wl,--gc-sections")
+  set (CMAKE_EXE_LINKER_FLAGS_MINSIZEREL "${CMAKE_EXE_LINKER_FLAGS_MINSIZEREL} -Wl,--gc-sections")
+endif (NOT APPLE)
+
+
+#
+# setup and test Fortran C/C++ interaction
+#
+
+include (FortranCInterface)
+FortranCInterface_VERIFY (CXX QUIET)
+FortranCInterface_HEADER (FC.h MACRO_NAMESPACE "FC_" SYMBOL_NAMESPACE "FC_"
+  SYMBOLS )
+
+
+#
+# sort out pre-requisites
+#
+
+#
+# fetch latest HTML manual
+#
+#set (WSJT_MANUAL_DIRECTORY "${PROJECT_MANUAL_DIRECTORY_URL}"
+#  CACHE STRING "Can be overridden to a local URI")
+#add_custom_target (user_manual ALL
+#  ${CMAKE_COMMAND} -D URL=${WSJT_MANUAL_DIRECTORY} -D NAME=${PROJECT_MANUAL} -P ${CMAKE_SOURCE_DIR}/CMake/download_html_manual.cmake
+#  COMMENT "Downloading ${PROJECT_NAME} HTML manual"
+#  VERBATIM
+#  )
+
+#
+# Setup RPATH so that built executable targets will run in both the
+# build tree and the install location without having to set a
+# (DYLD|LD)_LIBRARY_PATH override.
+#
+
+# use the full RPATH of the build tree
+set (CMAKE_SKIP_BUILD_RPATH FALSE)
+
+# when building, don't use the install RPATH, it will still be used
+# later on in the install phase
+set (CMAKE_BUILD_WITH_INSTALL_RPATH FALSE)
+
+# set (CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${WSJT_LIB_DESTINATION}")
+
+# add the automaticaly determined parts of the RPATH which point to
+# directories outside of the build tree to the install RPATH
+set (CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
+
+# the RPATH to be used when installing, but only if it's not a system
+# directory
+# list (FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES "${CMAKE_INSTALL_PREFIX}/${WSJT_LIB_DESTINATION}" isSystemDir)
+# if ("${isSystemDir}" STREQUAL "-1")
+#   set (CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${WSJT_LIB_DESTINATION}")
+# endif ("${isSystemDir}" STREQUAL "-1")
+
+set (QT_NEED_RPATH FALSE)
+if (NOT "${QT_LIBRARY_DIR}" STREQUAL "/lib" AND NOT "${QT_LIBRARY_DIR}" STREQUAL "/usr/lib" AND NOT "${QT_LIBRARY_DIR}" STREQUAL "/lib64" AND NOT "${QT_LIBRARY_DIR}" STREQUAL "/usr/lib64")
+  set (QT_NEED_RPATH TRUE)
+endif ()
+
+
+#
+# OpenMP
+#
+find_package (OpenMP)
+
+
+#
+# fftw3 single precsion library
+#
+find_package (FFTW3 COMPONENTS single threads REQUIRED)
+include_directories (${FFTW3_INCLUDE_DIRS})
+
+
+#
+# libhamlib setup
+#
+find_package (hamlib 3 REQUIRED)
+include_directories (${hamlib_INCLUDE_DIRS})
+if (hamlib_STATIC_LIBRARY)
+  # static link hamlib if archive library available
+  set (hamlib_LIBRARY "${hamlib_STATIC_LIBRARY}")
+  set (hamlib_LIBRARIES "${hamlib_STATIC_LIBRARIES}")
+endif ()
+find_program (RIGCTL_EXE rigctl)
+find_program (RIGCTLD_EXE rigctld)
+
+message (STATUS "hamlib_INCLUDE_DIRS: ${hamlib_INCLUDE_DIRS}")
+message (STATUS "hamlib_LIBRARY: ${hamlib_LIBRARY}")
+message (STATUS "hamlib_LIBRARIES: ${hamlib_LIBRARIES}")
+message (STATUS "hamlib_STATIC_LIBRARY: ${hamlib_STATIC_LIBRARY}")
+message (STATUS "hamlib_STATIC_LIBRARIES: ${hamlib_STATIC_LIBRARIES}")
+
+# if (WIN32)
+#   find_library (hamlib_RUNTIME NAMES hamlib hamlib-2 PATH_SUFFIXES bin)
+#   get_filename_component (_hamlib_runtime_path "${hamlib_RUNTIME}" PATH)
+#   file (GLOB hamlib_BACKENDS ${_hamlib_runtime_path}/hamlib*.dll)
+#   find_library (usb_RUNTIME NAMES usb0 PATH_SUFFIXES bin)
+# endif (WIN32)
+
+
+#
+# Qt5 setup
+#
+
+# Widgets finds its own dependencies.
+find_package (Qt5Widgets 5 REQUIRED)
+find_package (Qt5Multimedia 5 REQUIRED)
+
+if (WIN32)
+  add_definitions (-DQT_NEEDS_QTMAIN)
+  find_package (Qt5AxContainer REQUIRED)
+endif (WIN32)
+
+#
+# stuff only qmake can tell us
+#
+get_target_property (QMAKE_EXECUTABLE Qt5::qmake LOCATION)
+function (QUERY_QMAKE VAR RESULT)
+  exec_program (${QMAKE_EXECUTABLE} ARGS "-query ${VAR}" RETURN_VALUE return_code OUTPUT_VARIABLE output)
+  if (NOT return_code)
+    file (TO_CMAKE_PATH "${output}" output)
+    set (${RESULT} ${output} PARENT_SCOPE)
+  endif (NOT return_code)
+  message (STATUS "Asking qmake for ${RESULT} and got ${output}")
+endfunction (QUERY_QMAKE)
+
+query_qmake (QT_INSTALL_PLUGINS QT_PLUGINS_DIR)
+query_qmake (QT_INSTALL_IMPORTS QT_IMPORTS_DIR)
+query_qmake (QT_HOST_DATA QT_DATA_DIR)
+set (QT_MKSPECS_DIR ${QT_DATA_DIR}/mkspecs)
+
+# Tell CMake to run moc when necessary
+set (CMAKE_AUTOMOC ON)
+
+# don't use Qt "keywords" signal, slot, emit in generated files to
+# avoid compatability issue with other libraries
+# ADD_DEFINITIONS (-DQT_NO_KEYWORDS)
+# ADD_DEFINITIONS (-DUNICODE)	#as per qmake
+
+# As moc files are generated in the binary dir, tell CMake to always
+# look for includes there:
+set (CMAKE_INCLUDE_CURRENT_DIR ON)
+
+# project definitions
+add_definitions (-DQT5 -DCMAKE_BUILD -DBIGSYM=1)
+if (CMAKE_HOST_UNIX)
+  add_definitions (-DUNIX)
+elseif (CMAKE_HOST_WIN32)
+  add_definitions (-DWIN32)
+endif ()
+
+#
+# source navigation
+#
+set (sources
+  ${CMAKE_SOURCE_DIR}/*
+  ${CMAKE_SOURCE_DIR}/logbook/*
+  ${CMAKE_SOURCE_DIR}/lib/*
+  )
+add_custom_target (ctags COMMAND ${CTAGS} -o ${CMAKE_SOURCE_DIR}/tags -R ${sources})
+add_custom_target (etags COMMAND ${ETAGS} -o ${CMAKE_SOURCE_DIR}/TAGS -R ${sources})
+
+
+# embedded resources
+function (add_resources resources path)
+  foreach (resource_file_ ${ARGN})
+    get_filename_component (name_ ${resource_file_} NAME)
+    file (TO_NATIVE_PATH ${CMAKE_SOURCE_DIR}/${resource_file_} source_)
+    file (TO_NATIVE_PATH ${path}/${name_} dest_)
+    set (resources_ "${resources_}\n    <file alias=\"${dest_}\">${source_}</file>")
+    set (${resources} ${${resources}}${resources_} PARENT_SCOPE)
+  endforeach (resource_file_ ${ARGN})
+endfunction (add_resources resources path)
+
+add_resources (wsjtx_RESOURCES "" ${TOP_LEVEL_RESOURCES})
+add_resources (wsjtx_RESOURCES /Palettes ${PALETTE_FILES})
+if (WSJT_EMBED_SAMPLES)
+  add_resources (wsjtx_RESOURCES /samples ${SAMPLE_FILES})
+endif (WSJT_EMBED_SAMPLES)
+
+configure_file (wsjtx.qrc.in wsjtx.qrc @ONLY)
+
+
+# UI generation
+qt5_wrap_ui (wsjt_qt_GENUISRCS ${wsjt_qt_UISRCS})
+qt5_wrap_ui (wsjtx_GENUISRCS ${wsjtx_UISRCS})
+
+# Resource generation
+qt5_add_resources (wsjtx_RESOURCES_RCC ${CMAKE_BINARY_DIR}/wsjtx.qrc)
+
+# AX COM servers
+if (WIN32)
+  include (QtAxMacros)
+  wrap_ax_server (GENAXSRCS ${AXSERVERSRCS})
+endif (WIN32)
+
+
+#
+# targets
+#
+
+# build a library of package functionality (without and optionally with OpenMP support)
+add_library (wsjt_cxx STATIC ${wsjt_CSRCS} ${wsjt_CXXSRCS})
+
+# build an OpenMP variant of the Fortran library routines
+add_library (wsjt_fort STATIC ${wsjt_FSRCS})
+if (${OPENMP_FOUND} OR APPLE)
+  add_library (wsjt_fort_omp STATIC ${wsjt_FSRCS})
+  set_target_properties (wsjt_fort_omp
+    PROPERTIES
+    COMPILE_FLAGS "${OpenMP_C_FLAGS}"
+    Fortran_MODULE_DIRECTORY ${CMAKE_BINARY_DIR}/fortran_modules_omp
+    )
+  file (MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/fortran_modules_omp)
+  if (APPLE)
+    # On  Mac  we don't  have  working  OpenMP  support in  the  C/C++
+    # compilers so  we have to manually  set the correct flags  to get
+    # OpenMP support in jt9.
+    set_target_properties (wsjt_fort_omp
+      PROPERTIES
+      COMPILE_FLAGS "-fopenmp"	# assumes GNU style Fortran compiler
+      )
+  endif (APPLE)
+endif (${OPENMP_FOUND} OR APPLE)
+
+# build a library of package Qt functionality
+add_library (wsjt_qt STATIC ${wsjt_qt_CXXSRCS} ${wsjt_qt_GENUISRCS} ${GENAXSRCS})
+qt5_use_modules (wsjt_qt Widgets OpenGL Network)
+if (WIN32)
+  qt5_use_modules (wsjt_qt AxContainer AxBase)
+endif (WIN32)
+
+add_executable (jt9sim lib/jt9sim.f90 wsjtx.rc)
+target_link_libraries (jt9sim wsjt_fort wsjt_cxx)
+
+add_executable (jt65code lib/jt65code.f90 wsjtx.rc)
+target_link_libraries (jt65code wsjt_fort wsjt_cxx)
+
+add_executable (jt9code lib/jt9code.f90 wsjtx.rc)
+target_link_libraries (jt9code wsjt_fort wsjt_cxx)
+
+add_executable (jt9 lib/jt9.f90 lib/jt9a.f90 lib/jt9b.f90 lib/jt9c.f90 ${jt9_CXXSRCS} wsjtx.rc)
+if (${OPENMP_FOUND} OR APPLE)
+  if (APPLE)
+    # On  Mac  we don't  have  working  OpenMP  support in  the  C/C++
+    # compilers so we  have to manually set the  correct linking flags
+    # and libraries to get OpenMP support in jt9.
+    set_target_properties (jt9
+      PROPERTIES
+      COMPILE_FLAGS "-fopenmp"	# assumes GNU style Fortran compiler
+      Fortran_MODULE_DIRECTORY ${CMAKE_BINARY_DIR}/fortran_modules_omp
+      LINK_LIBRARIES "gomp;gcc_s.1" # assume GNU libgcc OpenMP
+      )
+  else (APPLE)
+    set_target_properties (jt9
+      PROPERTIES
+      COMPILE_FLAGS "${OpenMP_C_FLAGS}"
+      LINK_FLAGS "${OpenMP_C_FLAGS}"
+      Fortran_MODULE_DIRECTORY ${CMAKE_BINARY_DIR}/fortran_modules_omp
+      )
+  endif (APPLE)
+  target_link_libraries (jt9 wsjt_fort_omp wsjt_cxx ${FFTW3_LIBRARIES})
+else (${OPENMP_FOUND} OR APPLE)
+  target_link_libraries (jt9 wsjt_fort wsjt_cxx ${FFTW3_LIBRARIES})
+endif (${OPENMP_FOUND} OR APPLE)
+qt5_use_modules (jt9 Core)
+
+# build the main application
+add_executable (wsjtx MACOSX_BUNDLE
+  ${wsjtx_CXXSRCS}
+  ${wsjtx_GENUISRCS}
+  wsjtx.rc
+  ${WSJTX_ICON_FILE}
+  ${wsjtx_RESOURCES_RCC}
+  )
+
+if (WSJT_CREATE_WINMAIN)
+  set_target_properties (wsjtx PROPERTIES WIN32_EXECUTABLE ON)
+endif (WSJT_CREATE_WINMAIN)
+
+set_target_properties (wsjtx PROPERTIES
+  MACOSX_BUNDLE_INFO_STRING "${WSJTX_DESCRIPTION_SUMMARY}"
+  MACOSX_BUNDLE_ICON_FILE "${WSJTX_ICON_FILE}"
+  MACOSX_BUNDLE_BUNDLE_VERSION ${wsjtx_VERSION}
+  MACOSX_BUNDLE_SHORT_VERSION_STRING "v${wsjtx_VERSION}"
+  MACOSX_BUNDLE_LONG_VERSION_STRING "Version ${wsjtx_VERSION}"
+  MACOSX_BUNDLE_BUNDLE_NAME "${PROJECT_NAME}"
+  MACOSX_BUNDLE_COPYRIGHT "${PROJECT_COPYRIGHT}"
+  MACOSX_BUNDLE_GUI_IDENTIFIER "org.k1jt.wsjtx"
+  )
+
+target_link_libraries (wsjtx wsjt_fort wsjt_cxx wsjt_qt ${hamlib_LIBRARIES} ${FFTW3_LIBRARIES})
+qt5_use_modules (wsjtx Widgets OpenGL Network Multimedia SerialPort)
+
+add_resources (message_aggregator_RESOURCES /qss ${message_aggregator_STYLESHEETS})
+configure_file (message_aggregator.qrc.in message_aggregator.qrc @ONLY)
+qt5_add_resources (message_aggregator_RESOURCES_RCC ${CMAKE_BINARY_DIR}/message_aggregator.qrc)
+add_executable (message_aggregator
+  ${message_aggregator_CXXSRCS}
+  wsjtx.rc
+  ${message_aggregator_RESOURCES_RCC}
+  )
+target_link_libraries (message_aggregator wsjt_qt)
+qt5_use_modules (message_aggregator Widgets OpenGL Network)
+
+if (WSJT_CREATE_WINMAIN)
+  set_target_properties (message_aggregator PROPERTIES WIN32_EXECUTABLE ON)
+endif (WSJT_CREATE_WINMAIN)
+
+set (SYSTEM_NAME ${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR})
+if (WIN32)
+  set (SYSTEM_NAME "${SYSTEM_NAME}i386")
+endif (WIN32)
+if (WSJT_INCLUDE_KVASD)
+  #
+  # fetch and validate kvasd
+  #
+  set (KVASD_BINARY contrib/kvasd${CMAKE_EXECUTABLE_SUFFIX})
+
+  add_custom_target (kvasd ALL
+    ${CMAKE_COMMAND} -D SYSTEM_NAME=${SYSTEM_NAME} -D EXECUTABLE_SUFFIX=${CMAKE_EXECUTABLE_SUFFIX} -D URL=${PROJECT_KVASD_URL} -P ${CMAKE_SOURCE_DIR}/CMake/download_kvasd.cmake
+    COMMENT "Downloading kvasd for ${SYSTEM_NAME}"
+    VERBATIM
+    )
+endif (WSJT_INCLUDE_KVASD)
+
+
+if (UNIX)
+  if (NOT WSJT_SKIP_MANPAGES)
+    add_subdirectory (manpages)
+    add_dependencies (wsjtx manpages)
+  endif (NOT WSJT_SKIP_MANPAGES)
+  if (NOT APPLE)
+    add_subdirectory (debian)
+    add_dependencies (wsjtx debian)
+  endif (NOT APPLE)
+endif (UNIX)
+
+#
+# installation
+#
+install (TARGETS wsjtx
+  RUNTIME DESTINATION ${WSJT_BIN_DESTINATION} COMPONENT runtime
+  BUNDLE DESTINATION . COMPONENT runtime
+  )
+
+install (TARGETS jt9 jt65code jt9code message_aggregator
+  RUNTIME DESTINATION ${WSJT_BIN_DESTINATION} COMPONENT runtime
+  BUNDLE DESTINATION ${WSJT_BIN_DESTINATION} COMPONENT runtime
+  )
+
+if (WSJT_INCLUDE_KVASD)
+  install (PROGRAMS
+    ${CMAKE_BINARY_DIR}/${KVASD_BINARY}
+    DESTINATION ${WSJT_BIN_DESTINATION} COMPONENT runtime
+  )
+else (WSJT_INCLUDE_KVASD)
+  if (APPLE)
+    install (DIRECTORY contrib/Darwin/KVASD-installer.app
+      DESTINATION .
+      USE_SOURCE_PERMISSIONS
+      #COMPONENT Runtime
+      )
+  endif (APPLE)
+endif (WSJT_INCLUDE_KVASD)
+
+install (PROGRAMS
+  ${RIGCTL_EXE}
+  DESTINATION ${WSJT_BIN_DESTINATION}
+  #COMPONENT runtime
+  RENAME rigctl-wsjtx${CMAKE_EXECUTABLE_SUFFIX}
+  )
+
+install (PROGRAMS
+  ${RIGCTLD_EXE}
+  DESTINATION ${WSJT_BIN_DESTINATION}
+  #COMPONENT runtime
+  RENAME rigctld-wsjtx${CMAKE_EXECUTABLE_SUFFIX}
+  )
+
+install (FILES
+  README
+  COPYING
+  AUTHORS
+  THANKS
+  NEWS
+  INSTALL
+  BUGS
+  DESTINATION ${WSJT_SHARE_DESTINATION}/${WSJT_DOC_DESTINATION}
+  #COMPONENT runtime
+  )
+
+#
+# Mac installer files
+#
+if (APPLE)
+    install (FILES
+        Darwin/ReadMe.txt
+        Darwin/sysctl.conf
+        DESTINATION .
+        #COMPONENT runtime
+    )
+endif (APPLE)
+
+
+#
+# uninstall support
+#
+configure_file (
+  "${CMAKE_CURRENT_SOURCE_DIR}/CMake/cmake_uninstall.cmake.in"
+  "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
+  @ONLY)
+add_custom_target (uninstall
+  "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake")
+
+
+# creates svnversion.h using cmake script
+add_custom_target (revisiontag
+  COMMAND ${CMAKE_COMMAND} -D SOURCE_DIR=${CMAKE_CURRENT_SOURCE_DIR} -D OUTPUT_DIR=${PROJECT_BINARY_DIR} -P ${CMAKE_CURRENT_SOURCE_DIR}/CMake/getsvn.cmake
+  COMMENT "Generating Subversion revision information"
+  VERBATIM
+  )
+# explicitly say that the wsjt_qt depends on custom target, this is
+# done indirectly so that the revisiontag target gets built exactly
+# once per build
+add_dependencies(wsjt_qt revisiontag)
+
+
+#
+# versioning and configuration
+#
+configure_file (
+  "${PROJECT_SOURCE_DIR}/wsjtx_config.h.in"
+  "${PROJECT_BINARY_DIR}/wsjtx_config.h"
+  )
+include_directories ("${PROJECT_BINARY_DIR}")
+
+
+if (NOT WIN32 AND NOT APPLE)
+  # install a desktop file so wsjtx appears in the application start
+  # menu with an icon
+  install (
+    FILES wsjtx.desktop
+    DESTINATION share/applications
+    #COMPONENT runtime
+    )
+  install (
+    FILES icons/Unix/wsjtx_icon.png
+    DESTINATION share/pixmaps
+    #COMPONENT runtime
+    )
+endif (NOT WIN32 AND NOT APPLE)
+
+
+#
+# bundle fixup only done in Release or MinSizeRel configurations
+#
+if (NOT is_debug_build)
+
+  # get_target_property (QtCore_location Qt5::Core LOCATION)
+  # get_filename_component (QtCore_location ${QtCore_location} PATH)
+  # list (APPEND fixup_library_dirs ${QtCore_location})
+
+  if (APPLE)
+    set (CMAKE_POSTFLIGHT_SCRIPT
+      "${wsjtx_BINARY_DIR}/postflight.sh")
+    set (CMAKE_POSTUPGRADE_SCRIPT
+      "${wsjtx_BINARY_DIR}/postupgrade.sh")
+    configure_file ("${wsjtx_SOURCE_DIR}/Darwin/postflight.sh.in"
+      "${CMAKE_POSTFLIGHT_SCRIPT}")
+    configure_file ("${wsjtx_SOURCE_DIR}/Darwin/postupgrade.sh.in"
+      "${CMAKE_POSTUPGRADE_SCRIPT}")
+  endif ()
+
+  if (APPLE OR WIN32)
+    # install rules for including 3rd party libs such as Qt
+
+    # install a qt.conf file
+    install (CODE "
+  file (WRITE \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${WSJT_QT_CONF_DESTINATION}/qt.conf\"
+\"[Paths]
+\")
+"
+      #COMPONENT runtime
+      )
+
+    # if a system Qt is used (e.g. installed in /usr/lib/), it will not be included in the installation
+    set (fixup_exe "\${CMAKE_INSTALL_PREFIX}/${WSJT_BIN_DESTINATION}/${CMAKE_PROJECT_NAME}${CMAKE_EXECUTABLE_SUFFIX}")
+
+    #get_filename_component (hamlib_lib_dir ${hamlib_LIBRARIES} PATH)
+
+    if (APPLE)
+      # install required Qt plugins
+      install (
+	DIRECTORY
+	${QT_PLUGINS_DIR}/platforms
+	${QT_PLUGINS_DIR}/audio
+	${QT_PLUGINS_DIR}/accessible
+	DESTINATION ${WSJT_PLUGIN_DESTINATION}
+	CONFIGURATIONS Release MinSizeRel
+	#COMPONENT runtime
+	FILES_MATCHING PATTERN "*${CMAKE_SHARED_LIBRARY_SUFFIX}"
+	PATTERN "*minimal*${CMAKE_SHARED_LIBRARY_SUFFIX}" EXCLUDE
+	PATTERN "*offscreen*${CMAKE_SHARED_LIBRARY_SUFFIX}" EXCLUDE
+	PATTERN "*quick*${CMAKE_SHARED_LIBRARY_SUFFIX}" EXCLUDE
+	PATTERN "*_debug${CMAKE_SHARED_LIBRARY_SUFFIX}" EXCLUDE
+	)
+      # install (
+      # 	DIRECTORY
+      # 	${QT_PLUGINS_DIR}/platforms
+      # 	${QT_PLUGINS_DIR}/audio
+      #         ${QT_PLUGINS_DIR}/accessible
+      # 	DESTINATION ${WSJT_PLUGIN_DESTINATION}
+      # 	CONFIGURATIONS Debug
+      # 	#COMPONENT runtime
+      # 	FILES_MATCHING PATTERN "*_debug${CMAKE_SHARED_LIBRARY_SUFFIX}"
+      # 	PATTERN "*minimal*${CMAKE_SHARED_LIBRARY_SUFFIX}" EXCLUDE
+      # 	PATTERN "*offscreen*${CMAKE_SHARED_LIBRARY_SUFFIX}" EXCLUDE
+      # 	PATTERN "*quick*${CMAKE_SHARED_LIBRARY_SUFFIX}" EXCLUDE
+      # 	)
+
+      # add plugins path for Mac Bundle
+      install (CODE "
+file (APPEND \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${WSJT_QT_CONF_DESTINATION}/qt.conf\"
+\"Plugins = Plugins
+\")
+"
+	#COMPONENT runtime
+	)
+    endif (APPLE)
+
+    if (WIN32)
+      # DLL directory
+      #set (hamlib_lib_dir ${hamlib_lib_dir}/../bin)
+
+      get_filename_component (fftw_lib_dir ${FFTW3F_LIBRARY} PATH)
+      list (APPEND fixup_library_dirs ${fftw_lib_dir})
+
+      # install required Qt plugins
+      install (
+	DIRECTORY
+	${QT_PLUGINS_DIR}/platforms
+	${QT_PLUGINS_DIR}/accessible
+	DESTINATION ${WSJT_PLUGIN_DESTINATION}
+	CONFIGURATIONS Release MinSizeRel
+	#COMPONENT runtime
+	FILES_MATCHING PATTERN "*${CMAKE_SHARED_LIBRARY_SUFFIX}"
+	PATTERN "*minimal*${CMAKE_SHARED_LIBRARY_SUFFIX}" EXCLUDE
+	PATTERN "*offscreen*${CMAKE_SHARED_LIBRARY_SUFFIX}" EXCLUDE
+	PATTERN "*quick*${CMAKE_SHARED_LIBRARY_SUFFIX}" EXCLUDE
+	PATTERN "*d${CMAKE_SHARED_LIBRARY_SUFFIX}" EXCLUDE
+	)
+      # install (
+      # 	DIRECTORY
+      # 	${QT_PLUGINS_DIR}/platforms
+      # 	${QT_PLUGINS_DIR}/accessible
+      # 	DESTINATION ${WSJT_PLUGIN_DESTINATION}
+      # 	CONFIGURATIONS Debug
+      # 	#COMPONENT runtime
+      # 	FILES_MATCHING PATTERN "*d${CMAKE_SHARED_LIBRARY_SUFFIX}"
+      # 	PATTERN "*minimal*${CMAKE_SHARED_LIBRARY_SUFFIX}" EXCLUDE
+      # 	PATTERN "*offscreen*${CMAKE_SHARED_LIBRARY_SUFFIX}" EXCLUDE
+      # 	PATTERN "*quick*${CMAKE_SHARED_LIBRARY_SUFFIX}" EXCLUDE
+      # 	)
+
+      # add plugins path for WIN32
+      file (RELATIVE_PATH _plugins_path "${CMAKE_INSTALL_PREFIX}/${WSJT_QT_CONF_DESTINATION}" "${CMAKE_INSTALL_PREFIX}/${WSJT_PLUGIN_DESTINATION}")
+      install (CODE "
+file (APPEND \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${WSJT_QT_CONF_DESTINATION}/qt.conf\"
+\"Plugins = ${_plugins_path}
+\")
+"
+	#COMPONENT runtime
+	)
+
+      # set (gp_tool "objdump")	# we want MinGW tool - not MSVC (See GetPrerequisites.cmake)
+    endif (WIN32)
+
+    #list (APPEND fixup_library_dirs ${hamlib_lib_dir})
+    list (APPEND fixup_library_dirs ${hamlib_LIBRARY_DIRS})
+
+    install (CODE "
+     file (GLOB_RECURSE QTPLUGINS
+       \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${WSJT_PLUGIN_DESTINATION}/*${CMAKE_SHARED_LIBRARY_SUFFIX}\")
+     include (BundleUtilities)
+     set (BU_CHMOD_BUNDLE_ITEMS ON)
+     set (gp_tool ${gp_tool})
+     # canonicalize path in install context
+     get_filename_component (the_exe ${fixup_exe} REALPATH)
+     message (STATUS \"fixup_exe: \${the_exe}\")
+     fixup_bundle (\"\${the_exe}\" \"\${QTPLUGINS}\" \"${fixup_library_dirs}\")
+   "
+      #COMPONENT runtime
+      )
+  endif (APPLE OR WIN32)
+
+endif (NOT is_debug_build)
+
+
+#
+# packaging
+#
+set (CPACK_MONOLITHIC_INSTALL 1)
+set (CPACK_PACKAGE_NAME "${CMAKE_PROJECT_NAME}")
+set (CPACK_PACKAGE_VERSION_MAJOR ${WSJTX_VERSION_MAJOR})
+set (CPACK_PACKAGE_VERSION_MINOR ${WSJTX_VERSION_MINOR})
+set (CPACK_PACKAGE_VERSION_PATCH ${WSJTX_VERSION_PATCH})
+
+if (WIN32)
+  set (CPACK_GENERATOR "NSIS")
+elseif (APPLE)
+  set (CPACK_GENERATOR "DragNDrop")
+else ()
+  find_program (DPKG_BUILDER dpkg-buildpackage DOC "Debian package builder")
+  if (DPKG_BUILDER)
+    #
+    # Derive the correct filename for a Debian package because the DEB
+    # generator doesn't do this correctly at present.
+    #
+    find_program (DPKG_PROGRAM dpkg DOC "dpkg program of Debian-based systems")
+    if (DPKG_PROGRAM)
+      execute_process (
+	COMMAND ${DPKG_PROGRAM} --print-architecture
+	OUTPUT_VARIABLE CPACK_DEBIAN_PACKAGE_ARCHITECTURE
+	OUTPUT_STRIP_TRAILING_WHITESPACE
+	)
+    else (DPKG_PROGRAM)
+      set (CPACK_DEBIAN_PACKAGE_ARCHITECTURE noarch)
+    endif (DPKG_PROGRAM)
+
+    list (APPEND CPACK_GENERATOR "DEB")
+  endif (DPKG_BUILDER)
+
+  find_program (RPMBUILDER rpmbuild DOC "RPM package builder")
+  if (RPMBUILDER)
+    list (APPEND CPACK_GENERATOR "RPM")
+  endif (RPMBUILDER)
+endif ()
+
+set (CPACK_DEBIAN_PACKAGE_DESCRIPTION "${PROJECT_DESCRIPTION}")
+set (CPACK_DEBIAN_PACKAGE_HOMEPAGE "${PROJECT_HOMEPAGE}")
+set (CPACK_DEBIAN_PACKAGE_DEPENDS "libgfortran3 (>=4.8.2), libqt5serialport5 (>=5.2), libqt5multimedia5-plugins (>=5.2), libqt5widgets5 (>=5.2), libc6 (>=2.19)")
+set (CPACK_DEBIAN_PACKAGE_PACKAGE_SHLIBDEPS ON)
+
+set (CPACK_RPM_PACKAGE_ARCHITECTURE ${CMAKE_SYSTEM_PROCESSOR})
+set (CPACK_RPM_PACKAGE_REQUIRES "qt5-qtserialport >= 5.2, qt5-qtmultimedia >= 5.2, glibc >= 2, libgfortran >= 4.8.2")
+set (CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION /usr/share/pixmaps /usr/share/applications /usr/share/man /usr/share/man1)
+
+configure_file ("${PROJECT_SOURCE_DIR}/CMakeCPackOptions.cmake.in"
+  "${PROJECT_BINARY_DIR}/CMakeCPackOptions.cmake" @ONLY)
+set (CPACK_PROJECT_CONFIG_FILE "${PROJECT_BINARY_DIR}/CMakeCPackOptions.cmake")
+
+include (CPack)
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..b74cdd1
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,151 @@
+GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007
+
+Copyright (C) 2007 Free Software Foundation, Inc.
+
+Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.
+
+Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works.
+
+The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it [...]
+
+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 them 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 prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others.
+
+For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. 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.
+
+Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it.
+
+For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions.
+
+Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If  [...]
+
+Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free.
+
+The precise terms and conditions for copying, distribution and modification follow.
+
+TERMS AND CONDITIONS 0. Definitions. “This License” refers to version 3 of the GNU General Public License.
+
+“Copyright” also means copyright-like laws that apply to other kinds of works, such as semiconductor masks.
+
+“The Program” refers to any copyrightable work licensed under this License. Each licensee is addressed as “you”. “Licensees” and “recipients” may be individuals or organizations.
+
+To “modify” a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a “modified version” of the earlier work or a work “based on” the earlier work.
+
+A “covered work” means either the unmodified Program or a work based on the Program.
+
+To “propagate” a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well.
+
+To “convey” a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying.
+
+An interactive user interface displays “Appropriate Legal Notices” to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominen [...]
+
+1. Source Code. The “source code” for a work means the preferred form of the work for making modifications to it. “Object code” means any non-source form of a work.
+
+A “Standard Interface” means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language.
+
+The “System Libraries” of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A “Major Component”, in this context, means a major essential component (kernel, window syst [...]
+
+The “Corresponding Source” for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes int [...]
+
+The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source.
+
+The Corresponding Source for a work in source code form is that same work.
+
+2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law.
+
+You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you mus [...]
+
+Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary.
+
+3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures.
+
+When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures.
+
+4. Conveying Verbatim Copies. You may convey 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; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program.
+
+You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee.
+
+5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions:
+
+a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to “keep intact all notices”. c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable se [...]
+
+6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways:
+
+a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to [...]
+
+A “User Product” is either (1) a “consumer product”, which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, “normally used” refers to a typical or common use of that class of product, regardless of the [...]
+
+“Installation Information” for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made.
+
+If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neithe [...]
+
+The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network.
+
+Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying.
+
+7. Additional Terms. “Additional permissions” are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains gov [...]
+
+When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission.
+
+Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms:
+
+a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limitin [...]
+
+If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms.
+
+Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way.
+
+8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11).
+
+However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation.
+
+Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice.
+
+Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10.
+
+9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by m [...]
+
+10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License.
+
+An “entity transaction” is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source o [...]
+
+You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it.
+
+11. Patents. A “contributor” is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's “contributor version”.
+
+A contributor's “essential patent claims” are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, “control” includes the right to grant patent sublicenses in a  [...]
+
+Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version.
+
+In the following three paragraphs, a “patent license” is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To “grant” such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party.
+
+If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent w [...]
+
+If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it.
+
+A patent license is “discriminatory” if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and un [...]
+
+Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law.
+
+12. No Surrender of Others' Freedom. If 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 convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalt [...]
+
+13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interact [...]
+
+14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU 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 that a certain numbered version of the GNU General Public License “or any later version” applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation.
+
+If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program.
+
+Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version.
+
+15. Disclaimer of Warranty. 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 [...]
+
+16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 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  [...]
+
+17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee.
+
+END OF TERMS AND CONDITIONS
+
+---------------------------
diff --git a/CandidateKeyFilter.cpp b/CandidateKeyFilter.cpp
new file mode 100644
index 0000000..c0e0485
--- /dev/null
+++ b/CandidateKeyFilter.cpp
@@ -0,0 +1,70 @@
+#include "CandidateKeyFilter.hpp"
+
+#include <QModelIndex>
+#include <QAbstractItemModel>
+
+#include "pimpl_impl.hpp"
+
+class CandidateKeyFilter::impl final
+{
+public:
+  explicit impl (QAbstractItemModel const * referencing_model
+                 , int referencing_key_column
+                 , int referenced_key_column
+                 , int referencing_key_role
+                 , int referenced_key_role)
+    : referencing_ {referencing_model}
+    , referencing_key_column_ {referencing_key_column}
+    , referencing_key_role_ {referencing_key_role}
+    , referenced_key_column_ {referenced_key_column}
+    , referenced_key_role_ {referenced_key_role}
+  {
+  }
+
+  QAbstractItemModel const * referencing_;
+  int referencing_key_column_;
+  int referencing_key_role_;
+  int referenced_key_column_;
+  int referenced_key_role_;
+  QModelIndex active_key_;
+};
+
+CandidateKeyFilter::CandidateKeyFilter (QAbstractItemModel const * referencing_model
+                                        , QAbstractItemModel * referenced_model
+                                        , int referencing_key_column
+                                        , int referenced_key_column
+                                        , int referencing_key_role
+                                        , int referenced_key_role)
+  : QSortFilterProxyModel {nullptr} // ForeignKeyDelegate owns us
+  , m_ {referencing_model, referencing_key_column, referenced_key_column, referencing_key_role, referenced_key_role}
+{
+  setSourceModel (referenced_model);
+}
+
+CandidateKeyFilter::~CandidateKeyFilter ()
+{
+}
+
+void CandidateKeyFilter::set_active_key (QModelIndex const& index)
+{
+  if (index.isValid () )
+    {
+      Q_ASSERT (index.column () == m_->referencing_key_column_);
+      m_->active_key_ = index;
+    }
+  invalidateFilter ();
+}
+
+bool CandidateKeyFilter::filterAcceptsRow (int candidate_row, QModelIndex const& candidate_parent) const
+{
+  auto candidate_key = sourceModel ()->index (candidate_row, m_->referenced_key_column_, candidate_parent).data (m_->referenced_key_role_);
+
+  // Include the current key.
+  if (m_->active_key_.isValid () && candidate_key == m_->active_key_.data (m_->referencing_key_role_))
+    {
+      return true;
+    }
+
+  // Filter out any candidates already in the referencing key rows.
+  return m_->referencing_->match (m_->referencing_->index (0, m_->referencing_key_column_), m_->referencing_key_role_, candidate_key, 1, Qt::MatchExactly).isEmpty ();
+}
diff --git a/CandidateKeyFilter.hpp b/CandidateKeyFilter.hpp
new file mode 100644
index 0000000..1a5304b
--- /dev/null
+++ b/CandidateKeyFilter.hpp
@@ -0,0 +1,36 @@
+#ifndef CANDIDATE_KEY_FILTER_HPP_
+#define CANDIDATE_KEY_FILTER_HPP_
+
+#include <QSortFilterProxyModel>
+#include <QModelIndex>
+
+#include "pimpl_h.hpp"
+
+class QAbstractItemModel;
+
+class CandidateKeyFilter final
+  : public QSortFilterProxyModel
+{
+public:
+  explicit CandidateKeyFilter (QAbstractItemModel const * referencing_model
+                               , QAbstractItemModel * referenced_model
+                               , int referencing_key_column = 0
+                               , int referenced_key_column = 0
+                               , int referencing_key_role = Qt::EditRole
+                               , int referenced_key_role = Qt::EditRole);
+  ~CandidateKeyFilter ();
+
+  // this key is not to be filtered, usually because we want to allow
+  // it since we are editing the row that contains it this it is valid
+  // even though it is in use
+  void set_active_key (QModelIndex const& index = QModelIndex {});
+
+protected:
+  bool filterAcceptsRow (int candidate_row, QModelIndex const& candidate_parent) const override;
+
+private:
+  class impl;
+  pimpl<impl> m_;
+};
+
+#endif
diff --git a/Configuration.cpp b/Configuration.cpp
new file mode 100644
index 0000000..520a5be
--- /dev/null
+++ b/Configuration.cpp
@@ -0,0 +1,2423 @@
+#include "Configuration.hpp"
+
+//
+// Read me!
+//
+// This file defines a configuration dialog with the user. The general
+// strategy is to expose agreed  configuration parameters via a custom
+// interface (See  Configuration.hpp). The state exposed  through this
+// public   interface  reflects   stored  or   derived  data   in  the
+// Configuration::impl object.   The Configuration::impl  structure is
+// an implementation of the PIMPL (a.k.a.  Cheshire Cat or compilation
+// firewall) implementation hiding idiom that allows internal state to
+// be completely removed from the public interface.
+//
+// There  is a  secondary level  of parameter  storage which  reflects
+// current settings UI  state, these parameters are not  copied to the
+// state   store  that   the  public   interface  exposes   until  the
+// Configuration:impl::accept() operation is  successful. The accept()
+// operation is  tied to the settings  OK button. The normal  and most
+// convenient place to store this intermediate settings UI state is in
+// the data models of the UI  controls, if that is not convenient then
+// separate member variables  must be used to store that  state. It is
+// important for the user experience that no publicly visible settings
+// are changed  while the  settings UI are  changed i.e.  all settings
+// changes   must    be   deferred   until   the    "OK"   button   is
+// clicked. Conversely, all changes must  be discarded if the settings
+// UI "Cancel" button is clicked.
+//
+// There is  a complication related  to the radio interface  since the
+// this module offers  the facility to test the  radio interface. This
+// test means  that the  public visibility to  the radio  being tested
+// must be  changed.  To  maintain the  illusion of  deferring changes
+// until they  are accepted, the  original radio related  settings are
+// stored upon showing  the UI and restored if the  UI is dismissed by
+// canceling.
+//
+// It  should be  noted that  the  settings UI  lives as  long as  the
+// application client that uses it does. It is simply shown and hidden
+// as it  is needed rather than  creating it on demand.  This strategy
+// saves a  lot of  expensive UI  drawing at the  expense of  a little
+// storage and  gives a  convenient place  to deliver  settings values
+// from.
+//
+// Here is an overview of the high level flow of this module:
+//
+// 1)  On  construction the  initial  environment  is initialized  and
+// initial   values  for   settings  are   read  from   the  QSettings
+// database. At  this point  default values for  any new  settings are
+// established by  providing a  default value  to the  QSettings value
+// queries. This should be the only place where a hard coded value for
+// a   settings  item   is   defined.   Any   remaining  one-time   UI
+// initialization is also done. At the end of the constructor a method
+// initialize_models()  is called  to  load the  UI  with the  current
+// settings values.
+//
+// 2) When the settings UI is displayed by a client calling the exec()
+// operation, only temporary state need be stored as the UI state will
+// already mirror the publicly visible settings state.
+//
+// 3) As  the user makes  changes to  the settings UI  only validation
+// need be  carried out since the  UI control data models  are used as
+// the temporary store of unconfirmed settings.  As some settings will
+// depend  on each  other a  validate() operation  is available,  this
+// operations implements a check of any complex multi-field values.
+//
+// 4) If the  user discards the settings changes by  dismissing the UI
+// with the  "Cancel" button;  the reject()  operation is  called. The
+// reject() operation calls initialize_models()  which will revert all
+// the  UI visible  state  to  the values  as  at  the initial  exec()
+// operation.  No   changes  are  moved   into  the  data   fields  in
+// Configuration::impl that  reflect the  settings state  published by
+// the public interface (Configuration.hpp).
+//
+// 5) If  the user accepts the  settings changes by dismissing  the UI
+// with the "OK" button; the  accept() operation is called which calls
+// the validate() operation  again and, if it passes,  the fields that
+// are used  to deliver  the settings  state are  updated from  the UI
+// control models  or other temporary  state variables. At the  end of
+// the accept()  operation, just  before hiding  the UI  and returning
+// control to the caller; the new  settings values are stored into the
+// settings database by a call to the write_settings() operation, thus
+// ensuring that  settings changes are  saved even if  the application
+// crashes or is subsequently killed.
+//
+// 6)  On  destruction,  which   only  happens  when  the  application
+// terminates,  the settings  are saved  to the  settings database  by
+// calling the  write_settings() operation. This is  largely redundant
+// but is still done to save the default values of any new settings on
+// an initial run.
+//
+// To add a new setting:
+//
+// 1) Update the UI with the new widget to view and change the value.
+//
+// 2)  Add  a member  to  Configuration::impl  to store  the  accepted
+// setting state. If the setting state is dynamic; add a new signal to
+// broadcast the setting value.
+//
+// 3) Add a  query method to the  public interface (Configuration.hpp)
+// to access the  new setting value. If the settings  is dynamic; this
+// step  is optional  since  value  changes will  be  broadcast via  a
+// signal.
+//
+// 4) Add a forwarding operation to implement the new query (3) above.
+//
+// 5)  Add a  settings read  call to  read_settings() with  a sensible
+// default value. If  the setting value is dynamic, add  a signal emit
+// call to broadcast the setting value change.
+//
+// 6) Add  code to  initialize_models() to  load the  widget control's
+// data model with the current value.
+//
+// 7) If there is no convenient data model field, add a data member to
+// store the proposed new value. Ensure  this member has a valid value
+// on exit from read_settings().
+//
+// 8)  Add  any  required  inter-field validation  to  the  validate()
+// operation.
+//
+// 9) Add code to the accept()  operation to extract the setting value
+// from  the  widget   control  data  model  and  load   it  into  the
+// Configuration::impl  member  that  reflects  the  publicly  visible
+// setting state. If  the setting value is dynamic; add  a signal emit
+// call to broadcast any changed state of the setting.
+//
+// 10) Add  a settings  write call  to save the  setting value  to the
+// settings database.
+//
+
+#include <stdexcept>
+#include <iterator>
+#include <algorithm>
+#include <functional>
+#include <limits>
+
+#include <QApplication>
+#include <QMetaType>
+#include <QList>
+#include <QSettings>
+#include <QAudioDeviceInfo>
+#include <QAudioInput>
+#include <QDialog>
+#include <QMessageBox>
+#include <QAction>
+#include <QFileDialog>
+#include <QDir>
+#include <QFormLayout>
+#include <QString>
+#include <QStringList>
+#include <QStringListModel>
+#include <QLineEdit>
+#include <QRegExpValidator>
+#include <QIntValidator>
+#include <QThread>
+#include <QTimer>
+#include <QStandardPaths>
+#include <QFont>
+#include <QFontDialog>
+#include <QColorDialog>
+#include <QSerialPortInfo>
+#include <QScopedPointer>
+#include <QDebug>
+
+#include "qt_helpers.hpp"
+#include "SettingsGroup.hpp"
+#include "FrequencyLineEdit.hpp"
+#include "FrequencyItemDelegate.hpp"
+#include "CandidateKeyFilter.hpp"
+#include "ForeignKeyDelegate.hpp"
+#include "TransceiverFactory.hpp"
+#include "Transceiver.hpp"
+#include "Bands.hpp"
+#include "FrequencyList.hpp"
+#include "StationList.hpp"
+#include "NetworkServerLookup.hpp"
+
+#include "pimpl_impl.hpp"
+
+#include "ui_Configuration.h"
+#include "moc_Configuration.cpp"
+
+namespace
+{
+  struct init
+  {
+    init ()
+    {
+      qRegisterMetaType<Configuration::DataMode> ("Configuration::DataMode");
+      qRegisterMetaTypeStreamOperators<Configuration::DataMode> ("Configuration::DataMode");
+      qRegisterMetaType<Configuration::Type2MsgGen> ("Configuration::Type2MsgGen");
+      qRegisterMetaTypeStreamOperators<Configuration::Type2MsgGen> ("Configuration::Type2MsgGen");
+    }
+  } static_initializer;
+
+  // these undocumented flag values when stored in (Qt::UserRole - 1)
+  // of a ComboBox item model index allow the item to be enabled or
+  // disabled
+  int const combo_box_item_enabled (32 | 1);
+  int const combo_box_item_disabled (0);
+
+  QRegExp message_alphabet {"[- A-Za-z0-9+./?]*"};
+}
+
+
+//
+// Dialog to get a new Frequency item
+//
+class FrequencyDialog final
+  : public QDialog
+{
+public:
+  using Frequency = Radio::Frequency;
+
+  explicit FrequencyDialog (QWidget * parent = nullptr)
+    : QDialog {parent}
+  {
+    setWindowTitle (QApplication::applicationName () + " - " + tr ("Add Frequency"));
+
+    auto form_layout = new QFormLayout ();
+    form_layout->addRow (tr ("&Frequency (MHz):"), &frequency_line_edit_);
+
+    auto main_layout = new QVBoxLayout (this);
+    main_layout->addLayout (form_layout);
+
+    auto button_box = new QDialogButtonBox {QDialogButtonBox::Ok | QDialogButtonBox::Cancel};
+    main_layout->addWidget (button_box);
+
+    connect (button_box, &QDialogButtonBox::accepted, this, &FrequencyDialog::accept);
+    connect (button_box, &QDialogButtonBox::rejected, this, &FrequencyDialog::reject);
+  }
+
+  Frequency frequency () const
+  {
+    return frequency_line_edit_.frequency ();
+  }
+
+private:
+  FrequencyLineEdit frequency_line_edit_;
+};
+
+
+//
+// Dialog to get a new Station item
+//
+class StationDialog final
+  : public QDialog
+{
+public:
+  explicit StationDialog (StationList const * stations, Bands * bands, QWidget * parent = nullptr)
+    : QDialog {parent}
+    , filtered_bands_ {new CandidateKeyFilter {stations, bands}}
+  {
+    setWindowTitle (QApplication::applicationName () + " - " + tr ("Add Station"));
+
+    band_.setModel (filtered_bands_.data ());
+      
+    auto form_layout = new QFormLayout ();
+    form_layout->addRow (tr ("&Band:"), &band_);
+    form_layout->addRow (tr ("&Offset (MHz):"), &delta_);
+    form_layout->addRow (tr ("&Antenna:"), &description_);
+
+    auto main_layout = new QVBoxLayout (this);
+    main_layout->addLayout (form_layout);
+
+    auto button_box = new QDialogButtonBox {QDialogButtonBox::Ok | QDialogButtonBox::Cancel};
+    main_layout->addWidget (button_box);
+
+    connect (button_box, &QDialogButtonBox::accepted, this, &StationDialog::accept);
+    connect (button_box, &QDialogButtonBox::rejected, this, &StationDialog::reject);
+
+    if (delta_.text ().isEmpty ())
+      {
+        delta_.setText ("0");
+      }
+  }
+
+  StationList::Station station () const
+  {
+    return {band_.currentText (), delta_.frequency_delta (), description_.text ()};
+  }
+
+  int exec () override
+  {
+    filtered_bands_->set_active_key ();
+    return QDialog::exec ();
+  }
+
+private:
+  QScopedPointer<CandidateKeyFilter> filtered_bands_;
+
+  QComboBox band_;
+  FrequencyDeltaLineEdit delta_;
+  QLineEdit description_;
+};
+
+class RearrangableMacrosModel
+  : public QStringListModel
+{
+public:
+  Qt::ItemFlags flags (QModelIndex const& index) const override
+  {
+    auto flags = QStringListModel::flags (index);
+    if (index.isValid ())
+      {
+        // disallow drop onto existing items
+        flags &= ~Qt::ItemIsDropEnabled;
+      }
+    return flags;
+  }
+};
+
+
+// Class MessageItemDelegate
+//
+//	Item delegate for message entry such as free text message macros.
+//
+class MessageItemDelegate final
+  : public QStyledItemDelegate
+{
+public:
+  explicit MessageItemDelegate (QObject * parent = nullptr)
+    : QStyledItemDelegate {parent}
+  {
+  }
+
+  QWidget * createEditor (QWidget * parent
+                          , QStyleOptionViewItem const& /* option*/
+                          , QModelIndex const& /* index */
+                          ) const override
+  {
+    auto editor = new QLineEdit {parent};
+    editor->setFrame (false);
+    editor->setValidator (new QRegExpValidator {message_alphabet, editor});
+    return editor;
+  }
+};
+
+
+// Internal implementation of the Configuration class.
+class Configuration::impl final
+  : public QDialog
+{
+  Q_OBJECT;
+
+public:
+  using FrequencyDelta = Radio::FrequencyDelta;
+  using port_type = Configuration::port_type;
+
+  explicit impl (Configuration * self, QSettings * settings, QWidget * parent);
+  ~impl ();
+
+  bool have_rig (bool open_if_closed = true);
+
+  void transceiver_frequency (Frequency);
+  void transceiver_tx_frequency (Frequency);
+  void transceiver_mode (MODE);
+  void transceiver_ptt (bool);
+  void sync_transceiver (bool force_signal);
+
+  Q_SLOT int exec () override;
+  Q_SLOT void accept () override;
+  Q_SLOT void reject () override;
+  Q_SLOT void done (int) override;
+
+
+private:
+  typedef QList<QAudioDeviceInfo> AudioDevices;
+
+  void read_settings ();
+  void write_settings ();
+
+  bool load_audio_devices (QAudio::Mode, QComboBox *, QAudioDeviceInfo *);
+  void update_audio_channels (QComboBox const *, int, QComboBox *, bool);
+
+  void set_application_font (QFont const&);
+
+  void initialize_models ();
+  bool open_rig ();
+  //bool set_mode ();
+  void close_rig ();
+  TransceiverFactory::ParameterPack gather_rig_data ();
+  void enumerate_rigs ();
+  void set_rig_invariants ();
+  bool validate ();
+  void message_box (QString const& reason, QString const& detail = QString ());
+  void fill_port_combo_box (QComboBox *);
+
+  Q_SLOT void on_font_push_button_clicked ();
+  Q_SLOT void on_decoded_text_font_push_button_clicked ();
+  Q_SLOT void on_PTT_port_combo_box_activated (int);
+  Q_SLOT void on_CAT_port_combo_box_activated (int);
+  Q_SLOT void on_CAT_serial_baud_combo_box_currentIndexChanged (int);
+  Q_SLOT void on_CAT_data_bits_button_group_buttonClicked (int);
+  Q_SLOT void on_CAT_stop_bits_button_group_buttonClicked (int);
+  Q_SLOT void on_CAT_handshake_button_group_buttonClicked (int);
+  Q_SLOT void on_CAT_poll_interval_spin_box_valueChanged (int);
+  Q_SLOT void on_split_mode_button_group_buttonClicked (int);
+  Q_SLOT void on_test_CAT_push_button_clicked ();
+  Q_SLOT void on_test_PTT_push_button_clicked (bool checked);
+  Q_SLOT void on_CAT_control_lines_group_box_toggled (bool);
+  Q_SLOT void on_CAT_DTR_check_box_toggled (bool);
+  Q_SLOT void on_CAT_RTS_check_box_toggled (bool);
+  Q_SLOT void on_rig_combo_box_currentIndexChanged (int);
+  Q_SLOT void on_sound_input_combo_box_currentTextChanged (QString const&);
+  Q_SLOT void on_sound_output_combo_box_currentTextChanged (QString const&);
+  Q_SLOT void on_add_macro_push_button_clicked (bool = false);
+  Q_SLOT void on_delete_macro_push_button_clicked (bool = false);
+  Q_SLOT void on_PTT_method_button_group_buttonClicked (int);
+  Q_SLOT void on_callsign_line_edit_editingFinished ();
+  Q_SLOT void on_grid_line_edit_editingFinished ();
+  Q_SLOT void on_add_macro_line_edit_editingFinished ();
+  Q_SLOT void delete_macro ();
+  void delete_selected_macros (QModelIndexList);
+  Q_SLOT void on_save_path_select_push_button_clicked (bool);
+  Q_SLOT void delete_frequencies ();
+  Q_SLOT void insert_frequency ();
+  Q_SLOT void delete_stations ();
+  Q_SLOT void insert_station ();
+  Q_SLOT void handle_transceiver_update (TransceiverState);
+  Q_SLOT void handle_transceiver_failure (QString reason);
+  Q_SLOT void on_pbCQmsg_clicked();
+  Q_SLOT void on_pbMyCall_clicked();
+  Q_SLOT void on_pbTxMsg_clicked();
+  Q_SLOT void on_pbNewDXCC_clicked();
+  Q_SLOT void on_pbNewCall_clicked();
+
+  // typenames used as arguments must match registered type names :(
+  Q_SIGNAL void start_transceiver () const;
+  Q_SIGNAL void stop_transceiver () const;
+  Q_SIGNAL void frequency (Frequency rx, Transceiver::MODE) const;
+  Q_SIGNAL void tx_frequency (Frequency tx, bool rationalize_mode) const;
+  Q_SIGNAL void mode (Transceiver::MODE, bool rationalize) const;
+  Q_SIGNAL void ptt (bool) const;
+  Q_SIGNAL void sync (bool force_signal) const;
+
+  Configuration * const self_;	// back pointer to public interface
+
+  QThread transceiver_thread_;
+  TransceiverFactory transceiver_factory_;
+  QList<QMetaObject::Connection> rig_connections_;
+
+  Ui::configuration_dialog * ui_;
+
+  QSettings * settings_;
+
+  QDir doc_dir_;
+  QDir temp_dir_;
+  QDir default_save_directory_;
+  QDir save_directory_;
+
+  QFont font_;
+  QFont next_font_;
+
+  QFont decoded_text_font_;
+  QFont next_decoded_text_font_;
+
+  bool restart_sound_input_device_;
+  bool restart_sound_output_device_;
+
+  unsigned jt9w_bw_mult_;
+  float jt9w_min_dt_;
+  float jt9w_max_dt_;
+
+  Type2MsgGen type_2_msg_gen_;
+
+  QStringListModel macros_;
+  RearrangableMacrosModel next_macros_;
+  QAction * macro_delete_action_;
+  
+  Bands bands_;
+  FrequencyList frequencies_;
+  FrequencyList next_frequencies_;
+  StationList stations_;
+  StationList next_stations_;
+
+  QAction * frequency_delete_action_;
+  QAction * frequency_insert_action_;
+  FrequencyDialog * frequency_dialog_;
+
+  QAction * station_delete_action_;
+  QAction * station_insert_action_;
+  StationDialog * station_dialog_;
+
+  TransceiverFactory::ParameterPack rig_params_;
+  TransceiverFactory::ParameterPack saved_rig_params_;
+  bool rig_is_dummy_;
+  bool rig_active_;
+  bool have_rig_;
+  bool rig_changed_;
+  TransceiverState cached_rig_state_;
+
+  // the following members are required to get the rig into split the
+  // first time monitor or tune or Tx occur
+  bool setup_split_;
+  Frequency required_tx_frequency_; // this is needed because DX Lab
+                                    // Suite Commander in particular
+                                    // insists on reporting out of
+                                    // date state after successful
+                                    // commands to change the rig
+                                    // state :( Zero is valid and it
+                                    // means that we don't know the Tx
+                                    // frequency rather than implying
+                                    // no split.
+
+  bool enforce_mode_and_split_;
+  FrequencyDelta transceiver_offset_;
+
+  // configuration fields that we publish
+  QString my_callsign_;
+  QString my_grid_;
+  QColor color_CQ_;
+  QColor next_color_CQ_;
+  QColor color_MyCall_;
+  QColor next_color_MyCall_;
+  QColor color_TxMsg_;
+  QColor next_color_TxMsg_;
+  QColor color_DXCC_;
+  QColor next_color_DXCC_;
+  QColor color_NewCall_;
+  QColor next_color_NewCall_;
+  qint32 id_interval_;
+  bool id_after_73_;
+  bool tx_QSY_allowed_;
+  bool spot_to_psk_reporter_;
+  bool monitor_off_at_startup_;
+  bool monitor_last_used_;
+  bool log_as_RTTY_;
+  bool report_in_comments_;
+  bool prompt_to_log_;
+  bool insert_blank_;
+  bool DXCC_;
+  bool clear_DX_;
+  bool miles_;
+  bool quick_call_;
+  bool disable_TX_on_73_;
+  bool watchdog_;
+  bool TX_messages_;
+  QString udp_server_name_;
+  port_type udp_server_port_;
+  bool accept_udp_requests_;
+  bool udpWindowToFront_;
+  bool udpWindowRestore_;
+  DataMode data_mode_;
+
+  QAudioDeviceInfo audio_input_device_;
+  bool default_audio_input_device_selected_;
+  AudioDevice::Channel audio_input_channel_;
+  QAudioDeviceInfo audio_output_device_;
+  bool default_audio_output_device_selected_;
+  AudioDevice::Channel audio_output_channel_;
+
+  friend class Configuration;
+};
+
+#include "Configuration.moc"
+
+
+// delegate to implementation class
+Configuration::Configuration (QSettings * settings, QWidget * parent)
+  : m_ {this, settings, parent}
+{
+}
+
+Configuration::~Configuration ()
+{
+}
+
+QDir Configuration::doc_dir () const {return m_->doc_dir_;}
+QDir Configuration::temp_dir () const {return m_->temp_dir_;}
+
+int Configuration::exec () {return m_->exec ();}
+
+QAudioDeviceInfo const& Configuration::audio_input_device () const {return m_->audio_input_device_;}
+AudioDevice::Channel Configuration::audio_input_channel () const {return m_->audio_input_channel_;}
+QAudioDeviceInfo const& Configuration::audio_output_device () const {return m_->audio_output_device_;}
+AudioDevice::Channel Configuration::audio_output_channel () const {return m_->audio_output_channel_;}
+bool Configuration::restart_audio_input () const {return m_->restart_sound_input_device_;}
+bool Configuration::restart_audio_output () const {return m_->restart_sound_output_device_;}
+unsigned Configuration::jt9w_bw_mult () const {return m_->jt9w_bw_mult_;}
+float Configuration::jt9w_min_dt () const {return m_->jt9w_min_dt_;}
+float Configuration::jt9w_max_dt () const {return m_->jt9w_max_dt_;}
+auto Configuration::type_2_msg_gen () const -> Type2MsgGen {return m_->type_2_msg_gen_;}
+QString Configuration::my_callsign () const {return m_->my_callsign_;}
+QString Configuration::my_grid () const {return m_->my_grid_;}
+QColor Configuration::color_CQ () const {return m_->color_CQ_;}
+QColor Configuration::color_MyCall () const {return m_->color_MyCall_;}
+QColor Configuration::color_TxMsg () const {return m_->color_TxMsg_;}
+QColor Configuration::color_DXCC () const {return m_->color_DXCC_;}
+QColor Configuration::color_NewCall () const {return m_->color_NewCall_;}
+QFont Configuration::decoded_text_font () const {return m_->decoded_text_font_;}
+qint32 Configuration::id_interval () const {return m_->id_interval_;}
+bool Configuration::id_after_73 () const {return m_->id_after_73_;}
+bool Configuration::tx_QSY_allowed () const {return m_->tx_QSY_allowed_;}
+bool Configuration::spot_to_psk_reporter () const {return m_->spot_to_psk_reporter_;}
+bool Configuration::monitor_off_at_startup () const {return m_->monitor_off_at_startup_;}
+bool Configuration::monitor_last_used () const {return m_->rig_is_dummy_ || m_->monitor_last_used_;}
+bool Configuration::log_as_RTTY () const {return m_->log_as_RTTY_;}
+bool Configuration::report_in_comments () const {return m_->report_in_comments_;}
+bool Configuration::prompt_to_log () const {return m_->prompt_to_log_;}
+bool Configuration::insert_blank () const {return m_->insert_blank_;}
+bool Configuration::DXCC () const {return m_->DXCC_;}
+bool Configuration::clear_DX () const {return m_->clear_DX_;}
+bool Configuration::miles () const {return m_->miles_;}
+bool Configuration::quick_call () const {return m_->quick_call_;}
+bool Configuration::disable_TX_on_73 () const {return m_->disable_TX_on_73_;}
+bool Configuration::watchdog () const {return m_->watchdog_;}
+bool Configuration::TX_messages () const {return m_->TX_messages_;}
+bool Configuration::split_mode () const
+{
+  return !m_->rig_is_dummy_ && m_->rig_params_.split_mode != TransceiverFactory::split_mode_none;
+}
+QString Configuration::udp_server_name () const {return m_->udp_server_name_;}
+auto Configuration::udp_server_port () const -> port_type {return m_->udp_server_port_;}
+bool Configuration::accept_udp_requests () const {return m_->accept_udp_requests_;}
+bool Configuration::udpWindowToFront () const {return m_->udpWindowToFront_;}
+bool Configuration::udpWindowRestore () const {return m_->udpWindowRestore_;}
+Bands * Configuration::bands () {return &m_->bands_;}
+StationList * Configuration::stations () {return &m_->stations_;}
+FrequencyList * Configuration::frequencies () {return &m_->frequencies_;}
+QStringListModel * Configuration::macros () {return &m_->macros_;}
+QDir Configuration::save_directory () const {return m_->save_directory_;}
+QString Configuration::rig_name () const {return m_->rig_params_.rig_name;}
+
+bool Configuration::transceiver_online (bool open_if_closed)
+{
+#if WSJT_TRACE_CAT
+  qDebug () << "Configuration::transceiver_online: open_if_closed:" << open_if_closed << m_->cached_rig_state_;
+#endif
+
+  return m_->have_rig (open_if_closed);
+}
+
+void Configuration::transceiver_offline ()
+{
+#if WSJT_TRACE_CAT
+  qDebug () << "Configuration::transceiver_offline:" << m_->cached_rig_state_;
+#endif
+
+  return m_->close_rig ();
+}
+
+void Configuration::transceiver_frequency (Frequency f)
+{
+#if WSJT_TRACE_CAT
+  qDebug () << "Configuration::transceiver_frequency:" << f << m_->cached_rig_state_;
+#endif
+
+  m_->transceiver_frequency (f);
+}
+
+void Configuration::transceiver_tx_frequency (Frequency f)
+{
+#if WSJT_TRACE_CAT
+  qDebug () << "Configuration::transceiver_tx_frequency:" << f << m_->cached_rig_state_;
+#endif
+
+  m_->setup_split_ = true;
+  m_->required_tx_frequency_ = f;
+  m_->transceiver_tx_frequency (f);
+}
+
+void Configuration::transceiver_mode (MODE mode)
+{
+#if WSJT_TRACE_CAT
+  qDebug () << "Configuration::transceiver_mode:" << mode << m_->cached_rig_state_;
+#endif
+
+  m_->transceiver_mode (mode);
+}
+
+void Configuration::transceiver_ptt (bool on)
+{
+#if WSJT_TRACE_CAT
+  qDebug () << "Configuration::transceiver_ptt:" << on << m_->cached_rig_state_;
+#endif
+
+  m_->transceiver_ptt (on);
+}
+
+void Configuration::sync_transceiver (bool force_signal, bool enforce_mode_and_split)
+{
+#if WSJT_TRACE_CAT
+  qDebug () << "Configuration::sync_transceiver: force signal:" << force_signal << "enforce_mode_and_split:" << enforce_mode_and_split << m_->cached_rig_state_;
+#endif
+
+  m_->enforce_mode_and_split_ = enforce_mode_and_split;
+  m_->setup_split_ = enforce_mode_and_split;
+  m_->required_tx_frequency_ = 0;
+  m_->sync_transceiver (force_signal);
+}
+
+
+Configuration::impl::impl (Configuration * self, QSettings * settings, QWidget * parent)
+  : QDialog {parent}
+  , self_ {self}
+  , ui_ {new Ui::configuration_dialog}
+  , settings_ {settings}
+  , doc_dir_ {QApplication::applicationDirPath ()}
+  , frequencies_ {
+    {
+      136130,
+        474200,
+        1838000,
+        3576000,
+        5357000,
+        7076000,
+        10138000,
+        14076000,
+        18102000,
+        21076000,
+        24917000,
+        28076000,
+        50276000,
+        70091000,
+        144489000,
+        }
+    }
+  , stations_ {&bands_}
+  , next_stations_ {&bands_}
+  , frequency_dialog_ {new FrequencyDialog {this}}
+  , station_dialog_ {new StationDialog {&next_stations_, &bands_, this}}
+  , rig_active_ {false}
+  , have_rig_ {false}
+  , rig_changed_ {false}
+    //  , ptt_state_ {false}
+  , setup_split_ {false}
+  , required_tx_frequency_ {0}
+  , enforce_mode_and_split_ {false}
+  , transceiver_offset_ {0}
+  , default_audio_input_device_selected_ {false}
+  , default_audio_output_device_selected_ {false}
+{
+  ui_->setupUi (this);
+
+
+#if !defined (CMAKE_BUILD)
+#define WSJT_SHARE_DESTINATION "."
+#define WSJT_DOC_DESTINATION "."
+#endif
+
+#if !defined (Q_OS_WIN) || QT_VERSION >= 0x050300
+  auto path = QStandardPaths::locate (QStandardPaths::DataLocation, WSJT_DOC_DESTINATION, QStandardPaths::LocateDirectory);
+  if (path.isEmpty ())
+    {
+      doc_dir_.cdUp ();
+#if defined (Q_OS_MAC)
+      doc_dir_.cdUp ();
+      doc_dir_.cdUp ();
+#endif
+      doc_dir_.cd (WSJT_SHARE_DESTINATION);
+      doc_dir_.cd (WSJT_DOC_DESTINATION);
+    }
+  else
+    {
+      doc_dir_.cd (path);
+    }
+#else
+  doc_dir_.cd (WSJT_DOC_DESTINATION);
+#endif
+
+  {
+    // Create a temporary directory in a suitable location
+    QString temp_location {QStandardPaths::writableLocation (QStandardPaths::TempLocation)};
+    if (!temp_location.isEmpty ())
+      {
+        temp_dir_.setPath (temp_location);
+      }
+
+    QString unique_directory {QApplication::applicationName ()};
+    if (!temp_dir_.mkpath (unique_directory) || !temp_dir_.cd (unique_directory))
+      {
+        QMessageBox::critical (this, "WSJT-X", tr ("Create temporary directory error: ") + temp_dir_.absolutePath ());
+        throw std::runtime_error {"Failed to create usable temporary directory"};
+      }
+  }
+
+  {
+    // Find a suitable data file location
+    QDir data_dir {QStandardPaths::writableLocation (QStandardPaths::DataLocation)};
+    if (!data_dir.mkpath ("."))
+      {
+        QMessageBox::critical (this, "WSJT-X", tr ("Create data directory error: ") + data_dir.absolutePath ());
+        throw std::runtime_error {"Failed to create data directory"};
+      }
+
+    // Make sure the default save directory exists
+    QString save_dir {"save"};
+    default_save_directory_ = data_dir;
+    if (!default_save_directory_.mkpath (save_dir) || !default_save_directory_.cd (save_dir))
+      {
+        QMessageBox::critical (this, "WSJT-X", tr ("Create Directory", "Cannot create directory \"") + default_save_directory_.absoluteFilePath (save_dir) + "\".");
+        throw std::runtime_error {"Failed to create save directory"};
+      }
+
+    // we now have a deafult save path that exists
+
+    // make sure samples directory exists
+    QString samples_dir {"samples"};
+    if (!default_save_directory_.mkpath (samples_dir))
+      {
+        QMessageBox::critical (this, "WSJT-X", tr ("Create Directory", "Cannot create directory \"") + default_save_directory_.absoluteFilePath (samples_dir) + "\".");
+        throw std::runtime_error {"Failed to create save directory"};
+      }
+
+    // copy in any new sample files to the sample directory
+    QDir dest_dir {default_save_directory_};
+    dest_dir.cd (samples_dir);
+    
+    QDir source_dir {":/" + samples_dir};
+    source_dir.cd (save_dir);
+    source_dir.cd (samples_dir);
+    auto list = source_dir.entryInfoList (QStringList {{"*.wav"}}, QDir::Files | QDir::Readable);
+    Q_FOREACH (auto const& item, list)
+      {
+        if (!dest_dir.exists (item.fileName ()))
+          {
+            QFile file {item.absoluteFilePath ()};
+            file.copy (dest_dir.absoluteFilePath (item.fileName ()));
+          }
+      }
+  }
+
+  // this must be done after the default paths above are set
+  read_settings ();
+
+  //
+  // validation
+  //
+  ui_->callsign_line_edit->setValidator (new QRegExpValidator {QRegExp {"[A-Za-z0-9/]+"}, this});
+  ui_->grid_line_edit->setValidator (new QRegExpValidator {QRegExp {"[A-Ra-r]{2,2}[0-9]{2,2}[A-Xa-x]{0,2}"}, this});
+  ui_->add_macro_line_edit->setValidator (new QRegExpValidator {message_alphabet, this});
+
+  ui_->udp_server_port_spin_box->setMinimum (1);
+  ui_->udp_server_port_spin_box->setMaximum (std::numeric_limits<port_type>::max ());
+
+  //
+  // assign ids to radio buttons
+  //
+  ui_->CAT_data_bits_button_group->setId (ui_->CAT_7_bit_radio_button, TransceiverFactory::seven_data_bits);
+  ui_->CAT_data_bits_button_group->setId (ui_->CAT_8_bit_radio_button, TransceiverFactory::eight_data_bits);
+
+  ui_->CAT_stop_bits_button_group->setId (ui_->CAT_one_stop_bit_radio_button, TransceiverFactory::one_stop_bit);
+  ui_->CAT_stop_bits_button_group->setId (ui_->CAT_two_stop_bit_radio_button, TransceiverFactory::two_stop_bits);
+
+  ui_->CAT_handshake_button_group->setId (ui_->CAT_handshake_none_radio_button, TransceiverFactory::handshake_none);
+  ui_->CAT_handshake_button_group->setId (ui_->CAT_handshake_xon_radio_button, TransceiverFactory::handshake_XonXoff);
+  ui_->CAT_handshake_button_group->setId (ui_->CAT_handshake_hardware_radio_button, TransceiverFactory::handshake_hardware);
+
+  ui_->PTT_method_button_group->setId (ui_->PTT_VOX_radio_button, TransceiverFactory::PTT_method_VOX);
+  ui_->PTT_method_button_group->setId (ui_->PTT_CAT_radio_button, TransceiverFactory::PTT_method_CAT);
+  ui_->PTT_method_button_group->setId (ui_->PTT_DTR_radio_button, TransceiverFactory::PTT_method_DTR);
+  ui_->PTT_method_button_group->setId (ui_->PTT_RTS_radio_button, TransceiverFactory::PTT_method_RTS);
+
+  ui_->TX_audio_source_button_group->setId (ui_->TX_source_mic_radio_button, TransceiverFactory::TX_audio_source_front);
+  ui_->TX_audio_source_button_group->setId (ui_->TX_source_data_radio_button, TransceiverFactory::TX_audio_source_rear);
+
+  ui_->TX_mode_button_group->setId (ui_->mode_none_radio_button, data_mode_none);
+  ui_->TX_mode_button_group->setId (ui_->mode_USB_radio_button, data_mode_USB);
+  ui_->TX_mode_button_group->setId (ui_->mode_data_radio_button, data_mode_data);
+
+  ui_->split_mode_button_group->setId (ui_->split_none_radio_button, TransceiverFactory::split_mode_none);
+  ui_->split_mode_button_group->setId (ui_->split_rig_radio_button, TransceiverFactory::split_mode_rig);
+  ui_->split_mode_button_group->setId (ui_->split_emulate_radio_button, TransceiverFactory::split_mode_emulate);
+
+  //
+  // setup PTT port combo box drop down content
+  //
+  fill_port_combo_box (ui_->PTT_port_combo_box);
+  ui_->PTT_port_combo_box->addItem ("CAT");
+
+  //
+  // setup hooks to keep audio channels aligned with devices
+  //
+  {
+    using namespace std;
+    using namespace std::placeholders;
+
+    function<void (int)> cb (bind (&Configuration::impl::update_audio_channels, this, ui_->sound_input_combo_box, _1, ui_->sound_input_channel_combo_box, false));
+    connect (ui_->sound_input_combo_box, static_cast<void (QComboBox::*)(int)> (&QComboBox::currentIndexChanged), cb);
+    cb = bind (&Configuration::impl::update_audio_channels, this, ui_->sound_output_combo_box, _1, ui_->sound_output_channel_combo_box, true);
+    connect (ui_->sound_output_combo_box, static_cast<void (QComboBox::*)(int)> (&QComboBox::currentIndexChanged), cb);
+  }
+
+  //
+  // setup macros list view
+  //
+  ui_->macros_list_view->setModel (&next_macros_);
+  ui_->macros_list_view->setItemDelegate (new MessageItemDelegate {this});
+
+  macro_delete_action_ = new QAction {tr ("&Delete"), ui_->macros_list_view};
+  ui_->macros_list_view->insertAction (nullptr, macro_delete_action_);
+  connect (macro_delete_action_, &QAction::triggered, this, &Configuration::impl::delete_macro);
+
+
+  //
+  // setup working frequencies table model & view
+  //
+  frequencies_.sort (0);
+
+  ui_->frequencies_table_view->setModel (&next_frequencies_);
+  ui_->frequencies_table_view->sortByColumn (0, Qt::AscendingOrder);
+  ui_->frequencies_table_view->setItemDelegateForColumn (0, new FrequencyItemDelegate {&bands_, this});
+  ui_->frequencies_table_view->setColumnHidden (1, true);
+
+  frequency_delete_action_ = new QAction {tr ("&Delete"), ui_->frequencies_table_view};
+  ui_->frequencies_table_view->insertAction (nullptr, frequency_delete_action_);
+  connect (frequency_delete_action_, &QAction::triggered, this, &Configuration::impl::delete_frequencies);
+
+  frequency_insert_action_ = new QAction {tr ("&Insert ..."), ui_->frequencies_table_view};
+  ui_->frequencies_table_view->insertAction (nullptr, frequency_insert_action_);
+  connect (frequency_insert_action_, &QAction::triggered, this, &Configuration::impl::insert_frequency);
+
+
+  //
+  // setup stations table model & view
+  //
+  stations_.sort (0);
+
+  ui_->stations_table_view->setModel (&next_stations_);
+  ui_->stations_table_view->sortByColumn (0, Qt::AscendingOrder);
+  ui_->stations_table_view->setColumnWidth (1, 150);
+  ui_->stations_table_view->setItemDelegateForColumn (0, new ForeignKeyDelegate {&next_stations_, &bands_, 0, 0, this});
+  ui_->stations_table_view->setItemDelegateForColumn (1, new FrequencyDeltaItemDelegate {this});
+
+  station_delete_action_ = new QAction {tr ("&Delete"), ui_->stations_table_view};
+  ui_->stations_table_view->insertAction (nullptr, station_delete_action_);
+  connect (station_delete_action_, &QAction::triggered, this, &Configuration::impl::delete_stations);
+
+  station_insert_action_ = new QAction {tr ("&Insert ..."), ui_->stations_table_view};
+  ui_->stations_table_view->insertAction (nullptr, station_insert_action_);
+  connect (station_insert_action_, &QAction::triggered, this, &Configuration::impl::insert_station);
+
+  //
+  // load combo boxes with audio setup choices
+  //
+  default_audio_input_device_selected_ = load_audio_devices (QAudio::AudioInput, ui_->sound_input_combo_box, &audio_input_device_);
+  default_audio_output_device_selected_ = load_audio_devices (QAudio::AudioOutput, ui_->sound_output_combo_box, &audio_output_device_);
+
+  update_audio_channels (ui_->sound_input_combo_box, ui_->sound_input_combo_box->currentIndex (), ui_->sound_input_channel_combo_box, false);
+  update_audio_channels (ui_->sound_output_combo_box, ui_->sound_output_combo_box->currentIndex (), ui_->sound_output_channel_combo_box, true);
+
+  ui_->sound_input_channel_combo_box->setCurrentIndex (audio_input_channel_);
+  ui_->sound_output_channel_combo_box->setCurrentIndex (audio_output_channel_);
+
+  restart_sound_input_device_ = false;
+  restart_sound_output_device_ = false;
+
+  enumerate_rigs ();
+  initialize_models ();
+
+  transceiver_thread_.start ();
+
+#if !WSJT_ENABLE_EXPERIMENTAL_FEATURES
+  ui_->jt9w_group_box->setEnabled (false);
+#endif
+}
+
+Configuration::impl::~impl ()
+{
+  write_settings ();
+
+  close_rig ();
+
+  transceiver_thread_.quit ();
+  transceiver_thread_.wait ();
+
+  temp_dir_.removeRecursively (); // clean up temp files
+}
+
+void Configuration::impl::initialize_models ()
+{
+  auto pal = ui_->callsign_line_edit->palette ();
+  if (my_callsign_.isEmpty ())
+    {
+      pal.setColor (QPalette::Base, "#ffccff");
+    }
+  else
+    {
+      pal.setColor (QPalette::Base, Qt::white);
+    }
+  ui_->callsign_line_edit->setPalette (pal);
+  ui_->grid_line_edit->setPalette (pal);
+  ui_->callsign_line_edit->setText (my_callsign_);
+  ui_->grid_line_edit->setText (my_grid_);
+  ui_->labCQ->setStyleSheet(QString("background: %1").arg(color_CQ_.name()));
+  ui_->labMyCall->setStyleSheet(QString("background: %1").arg(color_MyCall_.name()));
+  ui_->labTx->setStyleSheet(QString("background: %1").arg(color_TxMsg_.name()));
+  ui_->labDXCC->setStyleSheet(QString("background: %1").arg(color_DXCC_.name()));
+  ui_->labNewCall->setStyleSheet(QString("background: %1").arg(color_NewCall_.name()));
+  ui_->CW_id_interval_spin_box->setValue (id_interval_);
+  ui_->PTT_method_button_group->button (rig_params_.ptt_type)->setChecked (true);
+  ui_->save_path_display_label->setText (save_directory_.absolutePath ());
+  ui_->CW_id_after_73_check_box->setChecked (id_after_73_);
+  ui_->tx_QSY_check_box->setChecked (tx_QSY_allowed_);
+  ui_->psk_reporter_check_box->setChecked (spot_to_psk_reporter_);
+  ui_->monitor_off_check_box->setChecked (monitor_off_at_startup_);
+  ui_->monitor_last_used_check_box->setChecked (monitor_last_used_);
+  ui_->log_as_RTTY_check_box->setChecked (log_as_RTTY_);
+  ui_->report_in_comments_check_box->setChecked (report_in_comments_);
+  ui_->prompt_to_log_check_box->setChecked (prompt_to_log_);
+  ui_->insert_blank_check_box->setChecked (insert_blank_);
+  ui_->DXCC_check_box->setChecked (DXCC_);
+  ui_->clear_DX_check_box->setChecked (clear_DX_);
+  ui_->miles_check_box->setChecked (miles_);
+  ui_->quick_call_check_box->setChecked (quick_call_);
+  ui_->disable_TX_on_73_check_box->setChecked (disable_TX_on_73_);
+  ui_->watchdog_check_box->setChecked (watchdog_);
+  ui_->TX_messages_check_box->setChecked (TX_messages_);
+  ui_->jt9w_bandwidth_mult_combo_box->setCurrentText (QString::number (jt9w_bw_mult_));
+  ui_->jt9w_min_dt_double_spin_box->setValue (jt9w_min_dt_);
+  ui_->jt9w_max_dt_double_spin_box->setValue (jt9w_max_dt_);
+  ui_->type_2_msg_gen_combo_box->setCurrentIndex (type_2_msg_gen_);
+  ui_->rig_combo_box->setCurrentText (rig_params_.rig_name);
+  ui_->TX_mode_button_group->button (data_mode_)->setChecked (true);
+  ui_->split_mode_button_group->button (rig_params_.split_mode)->setChecked (true);
+  ui_->CAT_serial_baud_combo_box->setCurrentText (QString::number (rig_params_.baud));
+  ui_->CAT_data_bits_button_group->button (rig_params_.data_bits)->setChecked (true);
+  ui_->CAT_stop_bits_button_group->button (rig_params_.stop_bits)->setChecked (true);
+  ui_->CAT_handshake_button_group->button (rig_params_.handshake)->setChecked (true);
+  ui_->CAT_control_lines_group_box->setChecked (rig_params_.force_line_control);
+  ui_->CAT_DTR_check_box->setChecked (rig_params_.dtr_high);
+  ui_->CAT_RTS_check_box->setChecked (rig_params_.rts_high);
+  ui_->TX_audio_source_button_group->button (rig_params_.audio_source)->setChecked (true);
+  ui_->CAT_poll_interval_spin_box->setValue (rig_params_.poll_interval);
+  ui_->udp_server_line_edit->setText (udp_server_name_);
+  ui_->udp_server_port_spin_box->setValue (udp_server_port_);
+  ui_->accept_udp_requests_check_box->setChecked (accept_udp_requests_);
+  ui_->udpWindowToFront->setChecked(udpWindowToFront_);
+  ui_->udpWindowRestore->setChecked(udpWindowRestore_);
+
+  if (rig_params_.ptt_port.isEmpty ())
+    {
+      if (ui_->PTT_port_combo_box->count ())
+        {
+          ui_->PTT_port_combo_box->setCurrentText (ui_->PTT_port_combo_box->itemText (0));
+        }
+    }
+  else
+    {
+      ui_->PTT_port_combo_box->setCurrentText (rig_params_.ptt_port);
+    }
+
+  next_macros_.setStringList (macros_.stringList ());
+  next_frequencies_ = frequencies_.frequencies ();
+  next_stations_ = stations_.stations ();
+
+  set_rig_invariants ();
+}
+
+void Configuration::impl::done (int r)
+{
+  // do this here since window is still on screen at this point
+  SettingsGroup g {settings_, "Configuration"};
+  settings_->setValue ("window/size", size ());
+  settings_->setValue ("window/pos", pos ());
+
+  QDialog::done (r);
+}
+
+void Configuration::impl::read_settings ()
+{
+  SettingsGroup g {settings_, "Configuration"};
+
+  resize (settings_->value ("window/size", size ()).toSize ());
+  move (settings_->value ("window/pos", pos ()).toPoint ());
+
+  my_callsign_ = settings_->value ("MyCall", "").toString ();
+  my_grid_ = settings_->value ("MyGrid", "").toString ();
+  next_color_CQ_ = color_CQ_ = settings_->value("colorCQ","#66ff66").toString();
+  next_color_MyCall_ = color_MyCall_ = settings_->value("colorMyCall","#ff6666").toString();
+  next_color_TxMsg_ = color_TxMsg_ = settings_->value("colorTxMsg","#ffff00").toString();
+  next_color_DXCC_ = color_DXCC_ = settings_->value("colorDXCC","#ff00ff").toString();
+  next_color_NewCall_ = color_NewCall_ = settings_->value("colorNewCall","#ffaaff").toString();
+
+  if (next_font_.fromString (settings_->value ("Font", QGuiApplication::font ().toString ()).toString ())
+      && next_font_ != font_)
+    {
+      font_ = next_font_;
+      set_application_font (font_);
+    }
+  else
+    {
+      next_font_ = font_;
+    }
+
+  if (next_decoded_text_font_.fromString (settings_->value ("DecodedTextFont", "Courier, 10").toString ())
+      && next_decoded_text_font_ != decoded_text_font_)
+    {
+      decoded_text_font_ = next_decoded_text_font_;
+      Q_EMIT self_->decoded_text_font_changed (decoded_text_font_);
+    }
+  else
+    {
+      next_decoded_text_font_ = decoded_text_font_;
+    }
+
+  id_interval_ = settings_->value ("IDint", 0).toInt ();
+
+  save_directory_ = settings_->value ("SaveDir", default_save_directory_.absolutePath ()).toString ();
+
+  {
+    //
+    // retrieve audio input device
+    //
+    auto saved_name = settings_->value ("SoundInName").toString ();
+
+    // deal with special Windows default audio devices
+    auto default_device = QAudioDeviceInfo::defaultInputDevice ();
+    if (saved_name == default_device.deviceName ())
+      {
+        audio_input_device_ = default_device;
+        default_audio_input_device_selected_ = true;
+      }
+    else
+      {
+        default_audio_input_device_selected_ = false;
+        Q_FOREACH (auto const& p, QAudioDeviceInfo::availableDevices (QAudio::AudioInput)) // available audio input devices
+          {
+            if (p.deviceName () == saved_name)
+              {
+                audio_input_device_ = p;
+              }
+          }
+      }
+  }
+
+  {
+    //
+    // retrieve audio output device
+    //
+    auto saved_name = settings_->value("SoundOutName").toString();
+
+    // deal with special Windows default audio devices
+    auto default_device = QAudioDeviceInfo::defaultOutputDevice ();
+    if (saved_name == default_device.deviceName ())
+      {
+        audio_output_device_ = default_device;
+        default_audio_output_device_selected_ = true;
+      }
+    else
+      {
+        default_audio_output_device_selected_ = false;
+        Q_FOREACH (auto const& p, QAudioDeviceInfo::availableDevices (QAudio::AudioOutput)) // available audio output devices
+          {
+            if (p.deviceName () == saved_name)
+              {
+                audio_output_device_ = p;
+              }
+          }
+      }
+  }
+
+  // retrieve audio channel info
+  audio_input_channel_ = AudioDevice::fromString (settings_->value ("AudioInputChannel", "Mono").toString ());
+  audio_output_channel_ = AudioDevice::fromString (settings_->value ("AudioOutputChannel", "Mono").toString ());
+
+  jt9w_bw_mult_ = settings_->value ("ToneMult", 1).toUInt ();
+  jt9w_min_dt_ = settings_->value ("DTmin", -2.5).toFloat ();
+  jt9w_max_dt_ = settings_->value ("DTmax", 5.).toFloat ();
+
+  type_2_msg_gen_ = settings_->value ("Type2MsgGen", QVariant::fromValue (Configuration::type_2_msg_3_full)).value<Configuration::Type2MsgGen> ();
+
+  monitor_off_at_startup_ = settings_->value ("MonitorOFF", false).toBool ();
+  monitor_last_used_ = settings_->value ("MonitorLastUsed", false).toBool ();
+  spot_to_psk_reporter_ = settings_->value ("PSKReporter", false).toBool ();
+  id_after_73_ = settings_->value ("After73", false).toBool ();
+  tx_QSY_allowed_ = settings_->value ("TxQSYAllowed", false).toBool ();
+
+  macros_.setStringList (settings_->value ("Macros", QStringList {"TNX 73 GL"}).toStringList ());
+
+  if (settings_->contains ("frequencies"))
+    {
+      frequencies_ = settings_->value ("frequencies").value<Radio::Frequencies> ();
+    }
+
+  stations_ = settings_->value ("stations").value<StationList::Stations> ();
+
+  log_as_RTTY_ = settings_->value ("toRTTY", false).toBool ();
+  report_in_comments_ = settings_->value("dBtoComments", false).toBool ();
+  rig_params_.rig_name = settings_->value ("Rig", TransceiverFactory::basic_transceiver_name_).toString ();
+  rig_is_dummy_ = TransceiverFactory::basic_transceiver_name_ == rig_params_.rig_name;
+  rig_params_.network_port = settings_->value ("CATNetworkPort").toString ();
+  rig_params_.serial_port = settings_->value ("CATSerialPort").toString ();
+  rig_params_.baud = settings_->value ("CATSerialRate", 4800).toInt ();
+  rig_params_.data_bits = settings_->value ("CATDataBits", QVariant::fromValue (TransceiverFactory::eight_data_bits)).value<TransceiverFactory::DataBits> ();
+  rig_params_.stop_bits = settings_->value ("CATStopBits", QVariant::fromValue (TransceiverFactory::two_stop_bits)).value<TransceiverFactory::StopBits> ();
+  rig_params_.handshake = settings_->value ("CATHandshake", QVariant::fromValue (TransceiverFactory::handshake_none)).value<TransceiverFactory::Handshake> ();
+  rig_params_.force_line_control = settings_->value ("CATForceControlLines", false).toBool ();
+  rig_params_.dtr_high = settings_->value ("DTR", false).toBool ();
+  rig_params_.rts_high = settings_->value ("RTS", false).toBool ();
+  rig_params_.ptt_type = settings_->value ("PTTMethod", QVariant::fromValue (TransceiverFactory::PTT_method_VOX)).value<TransceiverFactory::PTTMethod> ();
+  rig_params_.audio_source = settings_->value ("TXAudioSource", QVariant::fromValue (TransceiverFactory::TX_audio_source_front)).value<TransceiverFactory::TXAudioSource> ();
+  rig_params_.ptt_port = settings_->value ("PTTport").toString ();
+  data_mode_ = settings_->value ("DataMode", QVariant::fromValue (data_mode_none)).value<Configuration::DataMode> ();
+  prompt_to_log_ = settings_->value ("PromptToLog", false).toBool ();
+  insert_blank_ = settings_->value ("InsertBlank", false).toBool ();
+  DXCC_ = settings_->value ("DXCCEntity", false).toBool ();
+  clear_DX_ = settings_->value ("ClearCallGrid", false).toBool ();
+  miles_ = settings_->value ("Miles", false).toBool ();
+  quick_call_ = settings_->value ("QuickCall", false).toBool ();
+  disable_TX_on_73_ = settings_->value ("73TxDisable", false).toBool ();
+  watchdog_ = settings_->value ("Runaway", false).toBool ();
+  TX_messages_ = settings_->value ("Tx2QSO", false).toBool ();
+  rig_params_.poll_interval = settings_->value ("Polling", 0).toInt ();
+  rig_params_.split_mode = settings_->value ("SplitMode", QVariant::fromValue (TransceiverFactory::split_mode_none)).value<TransceiverFactory::SplitMode> ();
+  udp_server_name_ = settings_->value ("UDPServer", "127.0.0.1").toString ();
+  udp_server_port_ = settings_->value ("UDPServerPort", 2237).toUInt ();
+  accept_udp_requests_ = settings_->value ("AcceptUDPRequests", false).toBool ();
+  udpWindowToFront_ = settings_->value ("udpWindowToFront",false).toBool ();
+  udpWindowRestore_ = settings_->value ("udpWindowRestore",false).toBool ();
+}
+
+void Configuration::impl::write_settings ()
+{
+  SettingsGroup g {settings_, "Configuration"};
+
+  settings_->setValue ("MyCall", my_callsign_);
+  settings_->setValue ("MyGrid", my_grid_);
+  settings_->setValue("colorCQ",color_CQ_);
+  settings_->setValue("colorMyCall",color_MyCall_);
+  settings_->setValue("colorTxMsg",color_TxMsg_);
+  settings_->setValue("colorDXCC",color_DXCC_);
+  settings_->setValue("colorNewCall",color_NewCall_);
+  settings_->setValue ("Font", font_.toString ());
+  settings_->setValue ("DecodedTextFont", decoded_text_font_.toString ());
+  settings_->setValue ("IDint", id_interval_);
+  settings_->setValue ("PTTMethod", QVariant::fromValue (rig_params_.ptt_type));
+  settings_->setValue ("PTTport", rig_params_.ptt_port);
+  settings_->setValue ("SaveDir", save_directory_.absolutePath ());
+
+  if (default_audio_input_device_selected_)
+    {
+      settings_->setValue ("SoundInName", QAudioDeviceInfo::defaultInputDevice ().deviceName ());
+    }
+  else
+    {
+      settings_->setValue ("SoundInName", audio_input_device_.deviceName ());
+    }
+
+  if (default_audio_output_device_selected_)
+    {
+      settings_->setValue ("SoundOutName", QAudioDeviceInfo::defaultOutputDevice ().deviceName ());
+    }
+  else
+    {
+      settings_->setValue ("SoundOutName", audio_output_device_.deviceName ());
+    }
+
+  settings_->setValue ("AudioInputChannel", AudioDevice::toString (audio_input_channel_));
+  settings_->setValue ("AudioOutputChannel", AudioDevice::toString (audio_output_channel_));
+  settings_->setValue ("ToneMult", jt9w_bw_mult_);
+  settings_->setValue ("DTmin", jt9w_min_dt_);
+  settings_->setValue ("DTmax", jt9w_max_dt_);
+  settings_->setValue ("Type2MsgGen", QVariant::fromValue (type_2_msg_gen_));
+  settings_->setValue ("MonitorOFF", monitor_off_at_startup_);
+  settings_->setValue ("MonitorLastUsed", monitor_last_used_);
+  settings_->setValue ("PSKReporter", spot_to_psk_reporter_);
+  settings_->setValue ("After73", id_after_73_);
+  settings_->setValue ("TxQSYAllowed", tx_QSY_allowed_);
+  settings_->setValue ("Macros", macros_.stringList ());
+  settings_->setValue ("frequencies", QVariant::fromValue (frequencies_.frequencies ()));
+  settings_->setValue ("stations", QVariant::fromValue (stations_.stations ()));
+  settings_->setValue ("toRTTY", log_as_RTTY_);
+  settings_->setValue ("dBtoComments", report_in_comments_);
+  settings_->setValue ("Rig", rig_params_.rig_name);
+  settings_->setValue ("CATNetworkPort", rig_params_.network_port);
+  settings_->setValue ("CATSerialPort", rig_params_.serial_port);
+  settings_->setValue ("CATSerialRate", rig_params_.baud);
+  settings_->setValue ("CATDataBits", QVariant::fromValue (rig_params_.data_bits));
+  settings_->setValue ("CATStopBits", QVariant::fromValue (rig_params_.stop_bits));
+  settings_->setValue ("CATHandshake", QVariant::fromValue (rig_params_.handshake));
+  settings_->setValue ("DataMode", QVariant::fromValue (data_mode_));
+  settings_->setValue ("PromptToLog", prompt_to_log_);
+  settings_->setValue ("InsertBlank", insert_blank_);
+  settings_->setValue ("DXCCEntity", DXCC_);
+  settings_->setValue ("ClearCallGrid", clear_DX_);
+  settings_->setValue ("Miles", miles_);
+  settings_->setValue ("QuickCall", quick_call_);
+  settings_->setValue ("73TxDisable", disable_TX_on_73_);
+  settings_->setValue ("Runaway", watchdog_);
+  settings_->setValue ("Tx2QSO", TX_messages_);
+  settings_->setValue ("CATForceControlLines", rig_params_.force_line_control);
+  settings_->setValue ("DTR", rig_params_.dtr_high);
+  settings_->setValue ("RTS", rig_params_.rts_high);
+  settings_->setValue ("TXAudioSource", QVariant::fromValue (rig_params_.audio_source));
+  settings_->setValue ("Polling", rig_params_.poll_interval);
+  settings_->setValue ("SplitMode", QVariant::fromValue (rig_params_.split_mode));
+  settings_->setValue ("UDPServer", udp_server_name_);
+  settings_->setValue ("UDPServerPort", udp_server_port_);
+  settings_->setValue ("AcceptUDPRequests", accept_udp_requests_);
+  settings_->setValue ("udpWindowToFront", udpWindowToFront_);
+  settings_->setValue ("udpWindowRestore", udpWindowRestore_);
+}
+
+void Configuration::impl::set_rig_invariants ()
+{
+  auto const& rig = ui_->rig_combo_box->currentText ();
+  auto const& ptt_port = ui_->PTT_port_combo_box->currentText ();
+  auto ptt_method = static_cast<TransceiverFactory::PTTMethod> (ui_->PTT_method_button_group->checkedId ());
+
+  auto CAT_PTT_enabled = transceiver_factory_.has_CAT_PTT (rig);
+  auto CAT_indirect_serial_PTT = transceiver_factory_.has_CAT_indirect_serial_PTT (rig);
+  auto asynchronous_CAT = transceiver_factory_.has_asynchronous_CAT (rig);
+  auto is_hw_handshake = ui_->CAT_handshake_group_box->isEnabled ()
+    && TransceiverFactory::handshake_hardware == static_cast<TransceiverFactory::Handshake> (ui_->CAT_handshake_button_group->checkedId ());
+
+  ui_->test_CAT_push_button->setStyleSheet ({});
+
+  ui_->CAT_poll_interval_label->setEnabled (!asynchronous_CAT);
+  ui_->CAT_poll_interval_spin_box->setEnabled (!asynchronous_CAT);
+
+  static auto last_port_type = TransceiverFactory::Capabilities::none;
+  auto port_type = transceiver_factory_.CAT_port_type (rig);
+
+  bool is_serial_CAT (TransceiverFactory::Capabilities::serial == port_type);
+
+  if (TransceiverFactory::basic_transceiver_name_ == rig)
+    {
+      // makes no sense with rig as "None"
+      ui_->monitor_last_used_check_box->setEnabled (false);
+
+      ui_->CAT_control_group_box->setEnabled (false);
+      ui_->test_CAT_push_button->setEnabled (false);
+      ui_->test_PTT_push_button->setEnabled (TransceiverFactory::PTT_method_DTR == ptt_method
+                                             || TransceiverFactory::PTT_method_RTS == ptt_method);
+      ui_->TX_audio_source_group_box->setEnabled (false);
+      ui_->mode_group_box->setEnabled (false);
+      ui_->split_operation_group_box->setEnabled (false);
+    }
+  else
+    {
+      ui_->monitor_last_used_check_box->setEnabled (true);
+      ui_->CAT_control_group_box->setEnabled (true);
+      ui_->test_CAT_push_button->setEnabled (true);
+      ui_->test_PTT_push_button->setEnabled (false);
+      ui_->TX_audio_source_group_box->setEnabled (transceiver_factory_.has_CAT_PTT_mic_data (rig) && TransceiverFactory::PTT_method_CAT == ptt_method);
+      ui_->mode_group_box->setEnabled (true);
+      ui_->split_operation_group_box->setEnabled (true);
+      if (port_type != last_port_type)
+        {
+          last_port_type = port_type;
+          switch (port_type)
+            {
+            case TransceiverFactory::Capabilities::serial:
+              fill_port_combo_box (ui_->CAT_port_combo_box);
+              ui_->CAT_port_combo_box->setCurrentText (rig_params_.serial_port);
+              if (ui_->CAT_port_combo_box->currentText ().isEmpty () && ui_->CAT_port_combo_box->count ())
+                {
+                  ui_->CAT_port_combo_box->setCurrentText (ui_->CAT_port_combo_box->itemText (0));
+                }
+              ui_->CAT_port_label->setText (tr ("Serial Port:"));
+              ui_->CAT_port_combo_box->setToolTip (tr ("Serial port used for CAT control"));
+              ui_->CAT_port_combo_box->setEnabled (true);
+              break;
+
+            case TransceiverFactory::Capabilities::network:
+              ui_->CAT_port_combo_box->clear ();
+              ui_->CAT_port_combo_box->setCurrentText (rig_params_.network_port);
+              ui_->CAT_port_label->setText (tr ("Network Server:"));
+              ui_->CAT_port_combo_box->setToolTip (tr ("Optional hostname and port of network service.\n"
+                                                       "Leave blank for a sensible default on this machine.\n"
+                                                       "Formats:\n"
+                                                       "\thostname:port\n"
+                                                       "\tIPv4-address:port\n"
+                                                       "\t[IPv6-address]:port"));
+              ui_->CAT_port_combo_box->setEnabled (true);
+              break;
+
+            default:
+              ui_->CAT_port_combo_box->clear ();
+              ui_->CAT_port_combo_box->setEnabled (false);
+              break;
+            }
+        }
+      ui_->CAT_serial_port_parameters_group_box->setEnabled (is_serial_CAT);
+      ui_->CAT_control_lines_group_box->setEnabled (is_serial_CAT && !is_hw_handshake);
+    }
+
+  auto const& cat_port = ui_->CAT_port_combo_box->currentText ();
+
+  // only enable CAT option if transceiver has CAT PTT
+  ui_->PTT_CAT_radio_button->setEnabled (CAT_PTT_enabled);
+  
+  auto enable_ptt_port = TransceiverFactory::PTT_method_CAT != ptt_method && TransceiverFactory::PTT_method_VOX != ptt_method;
+  ui_->PTT_port_combo_box->setEnabled (enable_ptt_port);
+  ui_->PTT_port_label->setEnabled (enable_ptt_port);
+
+  ui_->PTT_port_combo_box->setItemData (ui_->PTT_port_combo_box->findText ("CAT")
+                                        , CAT_indirect_serial_PTT ? combo_box_item_enabled : combo_box_item_disabled
+                                        , Qt::UserRole - 1);
+
+  auto control_lines_available = !ui_->CAT_control_lines_group_box->isEnabled ()
+    || !ui_->CAT_control_lines_group_box->isChecked ();
+  ui_->PTT_DTR_radio_button->setEnabled (!(((is_serial_CAT && ptt_port == cat_port)
+                                          && !control_lines_available)
+                                           || ("CAT" == ptt_port && !CAT_indirect_serial_PTT)));
+
+  ui_->PTT_RTS_radio_button->setEnabled (!(((is_serial_CAT && ptt_port == cat_port)
+                                            && (!control_lines_available || is_hw_handshake))
+                                           || ("CAT" == ptt_port && !CAT_indirect_serial_PTT)));
+}
+
+bool Configuration::impl::validate ()
+{
+  if (ui_->sound_input_combo_box->currentIndex () < 0
+      && !QAudioDeviceInfo::availableDevices (QAudio::AudioInput).empty ())
+    {
+      message_box (tr ("Invalid audio input device"));
+      return false;
+    }
+
+  if (ui_->sound_output_combo_box->currentIndex () < 0
+      && !QAudioDeviceInfo::availableDevices (QAudio::AudioOutput).empty ())
+    {
+      message_box (tr ("Invalid audio output device"));
+      return false;
+    }
+
+  if (!ui_->PTT_method_button_group->checkedButton ()->isEnabled ())
+    {
+      message_box (tr ("Invalid PTT method"));
+      return false;
+    }
+
+  auto ptt_method = static_cast<TransceiverFactory::PTTMethod> (ui_->PTT_method_button_group->checkedId ());
+  auto ptt_port = ui_->PTT_port_combo_box->currentText ();
+  if ((TransceiverFactory::PTT_method_DTR == ptt_method || TransceiverFactory::PTT_method_RTS == ptt_method)
+      && (ptt_port.isEmpty ()
+          || combo_box_item_disabled == ui_->PTT_port_combo_box->itemData (ui_->PTT_port_combo_box->findText (ptt_port), Qt::UserRole - 1)))
+    {
+      message_box (tr ("Invalid PTT port"));
+      return false;
+    }
+
+  return true;
+}
+
+int Configuration::impl::exec ()
+{
+  // macros can be modified in the main window
+  next_macros_.setStringList (macros_.stringList ());
+
+  have_rig_ = rig_active_;	// record that we started with a rig open
+  saved_rig_params_ = rig_params_; // used to detect changes that
+                                   // require the Transceiver to be
+                                   // re-opened
+  rig_changed_ = false;
+
+  initialize_models ();
+  return QDialog::exec();
+}
+
+TransceiverFactory::ParameterPack Configuration::impl::gather_rig_data ()
+{
+  TransceiverFactory::ParameterPack result;
+  result.rig_name = ui_->rig_combo_box->currentText ();
+
+  switch (transceiver_factory_.CAT_port_type (result.rig_name))
+    {
+    case TransceiverFactory::Capabilities::network:
+      result.network_port = ui_->CAT_port_combo_box->currentText ();
+      result.serial_port = rig_params_.serial_port;
+      break;
+
+    default:
+      result.serial_port = ui_->CAT_port_combo_box->currentText ();
+      result.network_port = rig_params_.network_port;
+      break;
+    }
+
+  result.baud = ui_->CAT_serial_baud_combo_box->currentText ().toInt ();
+  result.data_bits = static_cast<TransceiverFactory::DataBits> (ui_->CAT_data_bits_button_group->checkedId ());
+  result.stop_bits = static_cast<TransceiverFactory::StopBits> (ui_->CAT_stop_bits_button_group->checkedId ());
+  result.handshake = static_cast<TransceiverFactory::Handshake> (ui_->CAT_handshake_button_group->checkedId ());
+  result.force_line_control = ui_->CAT_control_lines_group_box->isChecked ();
+  result.dtr_high = ui_->CAT_DTR_check_box->isChecked ();
+  result.rts_high = ui_->CAT_RTS_check_box->isChecked ();
+  result.poll_interval = ui_->CAT_poll_interval_spin_box->value ();
+  result.ptt_type = static_cast<TransceiverFactory::PTTMethod> (ui_->PTT_method_button_group->checkedId ());
+  result.ptt_port = ui_->PTT_port_combo_box->currentText ();
+  result.audio_source = static_cast<TransceiverFactory::TXAudioSource> (ui_->TX_audio_source_button_group->checkedId ());
+  result.split_mode = static_cast<TransceiverFactory::SplitMode> (ui_->split_mode_button_group->checkedId ());
+  return result;
+}
+
+void Configuration::impl::accept ()
+{
+  // Called when OK button is clicked.
+
+  if (!validate ())
+    {
+      return;			// not accepting
+    }
+
+  // extract all rig related configuration parameters into temporary
+  // structure for checking if the rig needs re-opening without
+  // actually updating our live state
+  auto temp_rig_params = gather_rig_data ();
+
+  // open_rig() uses values from models so we use it to validate the
+  // Transceiver settings before agreeing to accept the configuration
+  if (temp_rig_params != rig_params_ && !open_rig ())
+    {
+      return;			// not accepting
+    }
+
+  QDialog::accept();            // do this before accessing custom
+                                // models so that any changes in
+                                // delegates in views get flushed to
+                                // the underlying models before we
+                                // access them
+
+  sync_transceiver (true);	// force an update
+
+  //
+  // from here on we are bound to accept the new configuration
+  // parameters so extract values from models and make them live
+  //
+
+  if (next_font_ != font_)
+    {
+      font_ = next_font_;
+      set_application_font (font_);
+    }
+
+  if (next_decoded_text_font_ != decoded_text_font_)
+    {
+      decoded_text_font_ = next_decoded_text_font_;
+      Q_EMIT self_->decoded_text_font_changed (decoded_text_font_);
+    }
+
+  color_CQ_ = next_color_CQ_;
+  color_MyCall_ = next_color_MyCall_;
+  color_TxMsg_ = next_color_TxMsg_;
+  color_DXCC_ = next_color_DXCC_;
+  color_NewCall_ = next_color_NewCall_;
+
+  rig_params_ = temp_rig_params; // now we can go live with the rig
+                                 // related configuration parameters
+  rig_is_dummy_ = TransceiverFactory::basic_transceiver_name_ == rig_params_.rig_name;
+
+  // Check to see whether SoundInThread must be restarted,
+  // and save user parameters.
+  {
+    auto const& device_name = ui_->sound_input_combo_box->currentText ();
+    if (device_name != audio_input_device_.deviceName ())
+      {
+        auto const& default_device = QAudioDeviceInfo::defaultInputDevice ();
+        if (device_name == default_device.deviceName ())
+          {
+            audio_input_device_ = default_device;
+          }
+        else
+          {
+            bool found {false};
+            Q_FOREACH (auto const& d, QAudioDeviceInfo::availableDevices (QAudio::AudioInput))
+              {
+                if (device_name == d.deviceName ())
+                  {
+                    audio_input_device_ = d;
+                    found = true;
+                  }
+              }
+            if (!found)
+              {
+                audio_input_device_ = default_device;
+              }
+          }
+        restart_sound_input_device_ = true;
+      }
+  }
+
+  {
+    auto const& device_name = ui_->sound_output_combo_box->currentText ();
+    if (device_name != audio_output_device_.deviceName ())
+      {
+        auto const& default_device = QAudioDeviceInfo::defaultOutputDevice ();
+        if (device_name == default_device.deviceName ())
+          {
+            audio_output_device_ = default_device;
+          }
+        else
+          {
+            bool found {false};
+            Q_FOREACH (auto const& d, QAudioDeviceInfo::availableDevices (QAudio::AudioOutput))
+              {
+                if (device_name == d.deviceName ())
+                  {
+                    audio_output_device_ = d;
+                    found = true;
+                  }
+              }
+            if (!found)
+              {
+                audio_output_device_ = default_device;
+              }
+          }
+        restart_sound_output_device_ = true;
+      }
+  }
+
+  if (audio_input_channel_ != static_cast<AudioDevice::Channel> (ui_->sound_input_channel_combo_box->currentIndex ()))
+    {
+      audio_input_channel_ = static_cast<AudioDevice::Channel> (ui_->sound_input_channel_combo_box->currentIndex ());
+      restart_sound_input_device_ = true;
+    }
+  Q_ASSERT (audio_input_channel_ <= AudioDevice::Right);
+
+  if (audio_output_channel_ != static_cast<AudioDevice::Channel> (ui_->sound_output_channel_combo_box->currentIndex ()))
+    {
+      audio_output_channel_ = static_cast<AudioDevice::Channel> (ui_->sound_output_channel_combo_box->currentIndex ());
+      restart_sound_output_device_ = true;
+    }
+  Q_ASSERT (audio_output_channel_ <= AudioDevice::Both);
+
+  my_callsign_ = ui_->callsign_line_edit->text ();
+  my_grid_ = ui_->grid_line_edit->text ();
+  spot_to_psk_reporter_ = ui_->psk_reporter_check_box->isChecked ();
+  id_interval_ = ui_->CW_id_interval_spin_box->value ();
+  id_after_73_ = ui_->CW_id_after_73_check_box->isChecked ();
+  tx_QSY_allowed_ = ui_->tx_QSY_check_box->isChecked ();
+  monitor_off_at_startup_ = ui_->monitor_off_check_box->isChecked ();
+  monitor_last_used_ = ui_->monitor_last_used_check_box->isChecked ();
+  jt9w_bw_mult_ = ui_->jt9w_bandwidth_mult_combo_box->currentText ().toUInt ();
+  jt9w_min_dt_ = static_cast<float> (ui_->jt9w_min_dt_double_spin_box->value ());
+  jt9w_max_dt_ = static_cast<float> (ui_->jt9w_max_dt_double_spin_box->value ());
+  type_2_msg_gen_ = static_cast<Type2MsgGen> (ui_->type_2_msg_gen_combo_box->currentIndex ());
+  log_as_RTTY_ = ui_->log_as_RTTY_check_box->isChecked ();
+  report_in_comments_ = ui_->report_in_comments_check_box->isChecked ();
+  prompt_to_log_ = ui_->prompt_to_log_check_box->isChecked ();
+  insert_blank_ = ui_->insert_blank_check_box->isChecked ();
+  DXCC_ = ui_->DXCC_check_box->isChecked ();
+  clear_DX_ = ui_->clear_DX_check_box->isChecked ();
+  miles_ = ui_->miles_check_box->isChecked ();
+  quick_call_ = ui_->quick_call_check_box->isChecked ();
+  disable_TX_on_73_ = ui_->disable_TX_on_73_check_box->isChecked ();
+  watchdog_ = ui_->watchdog_check_box->isChecked ();
+  TX_messages_ = ui_->TX_messages_check_box->isChecked ();
+  data_mode_ = static_cast<DataMode> (ui_->TX_mode_button_group->checkedId ());
+  save_directory_ = ui_->save_path_display_label->text ();
+
+  auto new_server = ui_->udp_server_line_edit->text ();
+  if (new_server != udp_server_name_)
+    {
+      udp_server_name_ = new_server;
+      Q_EMIT self_->udp_server_changed (new_server);
+    }
+
+  auto new_port = ui_->udp_server_port_spin_box->value ();
+  if (new_port != udp_server_port_)
+    {
+      udp_server_port_ = new_port;
+      Q_EMIT self_->udp_server_port_changed (new_port);
+    }
+  
+  accept_udp_requests_ = ui_->accept_udp_requests_check_box->isChecked ();
+  udpWindowToFront_ = ui_->udpWindowToFront->isChecked ();
+  udpWindowRestore_ = ui_->udpWindowRestore->isChecked ();
+
+  if (macros_.stringList () != next_macros_.stringList ())
+    {
+      macros_.setStringList (next_macros_.stringList ());
+    }
+
+  if (frequencies_.frequencies () != next_frequencies_.frequencies ())
+    {
+      frequencies_ = next_frequencies_.frequencies ();
+      frequencies_.sort (0);
+    }
+
+  if (stations_.stations () != next_stations_.stations ())
+    {
+      stations_ = next_stations_.stations ();
+      stations_.sort (0);
+    }
+ 
+  write_settings ();		// make visible to all
+}
+
+void Configuration::impl::reject ()
+{
+  initialize_models ();		// reverts to settings as at exec ()
+
+  // check if the Transceiver instance changed, in which case we need
+  // to re open any prior Transceiver type
+  if (rig_changed_)
+    {
+      if (have_rig_)
+        {
+          // we have to do this since the rig has been opened since we
+          // were exec'ed even though it might fail
+          open_rig ();
+        }
+      else
+        {
+          close_rig ();
+        }
+    }
+
+  QDialog::reject ();
+}
+
+void Configuration::impl::message_box (QString const& reason, QString const& detail)
+{
+  QMessageBox mb;
+  mb.setText (reason);
+  if (!detail.isEmpty ())
+    {
+      mb.setDetailedText (detail);
+    }
+  mb.setStandardButtons (QMessageBox::Ok);
+  mb.setDefaultButton (QMessageBox::Ok);
+  mb.setIcon (QMessageBox::Critical);
+  mb.exec ();
+}
+
+void Configuration::impl::on_font_push_button_clicked ()
+{
+  next_font_ = QFontDialog::getFont (0, next_font_, this);
+}
+
+void Configuration::impl::on_pbCQmsg_clicked()
+{
+  auto new_color = QColorDialog::getColor(next_color_CQ_, this, "CQ Messages Color");
+  if (new_color.isValid ())
+    {
+      next_color_CQ_ = new_color;
+      ui_->labCQ->setStyleSheet(QString("background: %1").arg(next_color_CQ_.name()));
+    }
+}
+
+void Configuration::impl::on_pbMyCall_clicked()
+{
+  auto new_color = QColorDialog::getColor(next_color_MyCall_, this, "My Call Messages Color");
+  if (new_color.isValid ())
+    {
+      next_color_MyCall_ = new_color;
+      ui_->labMyCall->setStyleSheet(QString("background: %1").arg(next_color_MyCall_.name()));
+    }
+}
+
+void Configuration::impl::on_pbTxMsg_clicked()
+{
+  auto new_color = QColorDialog::getColor(next_color_TxMsg_, this, "Tx Messages Color");
+  if (new_color.isValid ())
+    {
+      next_color_TxMsg_ = new_color;
+      ui_->labTx->setStyleSheet(QString("background: %1").arg(next_color_TxMsg_.name()));
+    }
+}
+
+void Configuration::impl::on_pbNewDXCC_clicked()
+{
+  auto new_color = QColorDialog::getColor(next_color_DXCC_, this, "New DXCC Messages Color");
+  if (new_color.isValid ())
+    {
+      next_color_DXCC_ = new_color;
+      ui_->labDXCC->setStyleSheet(QString("background: %1").arg(next_color_DXCC_.name()));
+    }
+}
+
+void Configuration::impl::on_pbNewCall_clicked()
+{
+  auto new_color = QColorDialog::getColor(next_color_NewCall_, this, "New Call Messages Color");
+  if (new_color.isValid ())
+    {
+      next_color_NewCall_ = new_color;
+      ui_->labNewCall->setStyleSheet(QString("background: %1").arg(next_color_NewCall_.name()));
+    }
+}
+
+void Configuration::impl::on_decoded_text_font_push_button_clicked ()
+{
+  next_decoded_text_font_ = QFontDialog::getFont (0, decoded_text_font_ , this
+                                                  , tr ("WSJT-X Decoded Text Font Chooser")
+#if QT_VERSION >= 0x050201
+                                                  , QFontDialog::MonospacedFonts
+#endif
+                                                  );
+}
+
+void Configuration::impl::on_PTT_port_combo_box_activated (int /* index */)
+{
+  set_rig_invariants ();
+}
+
+void Configuration::impl::on_CAT_port_combo_box_activated (int /* index */)
+{
+  set_rig_invariants ();
+}
+
+void Configuration::impl::on_CAT_serial_baud_combo_box_currentIndexChanged (int /* index */)
+{
+  set_rig_invariants ();
+}
+
+void Configuration::impl::on_CAT_handshake_button_group_buttonClicked (int /* id */)
+{
+  set_rig_invariants ();
+}
+
+void Configuration::impl::on_rig_combo_box_currentIndexChanged (int /* index */)
+{
+  set_rig_invariants ();
+}
+
+void Configuration::impl::on_CAT_data_bits_button_group_buttonClicked (int /* id */)
+{
+  set_rig_invariants ();
+}
+
+void Configuration::impl::on_CAT_stop_bits_button_group_buttonClicked (int /* id */)
+{
+  set_rig_invariants ();
+}
+
+void Configuration::impl::on_CAT_poll_interval_spin_box_valueChanged (int /* value */)
+{
+  set_rig_invariants ();
+}
+
+void Configuration::impl::on_split_mode_button_group_buttonClicked (int /* id */)
+{
+  setup_split_ = true;
+  required_tx_frequency_ = 0;
+}
+
+void Configuration::impl::on_test_CAT_push_button_clicked ()
+{
+  if (!validate ())
+    {
+      return;
+    }
+
+  ui_->test_CAT_push_button->setStyleSheet ({});
+  if (open_rig ())
+    {
+      Q_EMIT sync (true);
+    }
+
+  set_rig_invariants ();
+}
+
+void Configuration::impl::on_test_PTT_push_button_clicked (bool checked)
+{
+  ui_->test_PTT_push_button->setChecked (!checked); // let status
+                                                    // update check us
+  if (!validate ())
+    {
+      return;
+    }
+
+  if (open_rig ())
+    {
+      Q_EMIT self_->transceiver_ptt (checked);
+    }
+}
+
+void Configuration::impl::on_CAT_control_lines_group_box_toggled (bool /* checked */)
+{
+  set_rig_invariants ();
+}
+
+void Configuration::impl::on_CAT_DTR_check_box_toggled (bool /* checked */)
+{
+  set_rig_invariants ();
+}
+
+void Configuration::impl::on_CAT_RTS_check_box_toggled (bool /* checked */)
+{
+  set_rig_invariants ();
+}
+
+void Configuration::impl::on_PTT_method_button_group_buttonClicked (int /* id */)
+{
+  set_rig_invariants ();
+}
+
+void Configuration::impl::on_callsign_line_edit_editingFinished ()
+{
+  ui_->callsign_line_edit->setText (ui_->callsign_line_edit->text ().toUpper ());
+}
+
+void Configuration::impl::on_grid_line_edit_editingFinished ()
+{
+  auto text = ui_->grid_line_edit->text ();
+  ui_->grid_line_edit->setText (text.left (4).toUpper () + text.mid (4).toLower ());
+}
+
+void Configuration::impl::on_sound_input_combo_box_currentTextChanged (QString const& text)
+{
+  default_audio_input_device_selected_ = QAudioDeviceInfo::defaultInputDevice ().deviceName () == text;
+}
+
+void Configuration::impl::on_sound_output_combo_box_currentTextChanged (QString const& text)
+{
+  default_audio_output_device_selected_ = QAudioDeviceInfo::defaultOutputDevice ().deviceName () == text;
+}
+
+void Configuration::impl::on_add_macro_line_edit_editingFinished ()
+{
+  ui_->add_macro_line_edit->setText (ui_->add_macro_line_edit->text ().toUpper ());
+}
+
+void Configuration::impl::on_delete_macro_push_button_clicked (bool /* checked */)
+{
+  auto selection_model = ui_->macros_list_view->selectionModel ();
+  if (selection_model->hasSelection ())
+    {
+      // delete all selected items
+      delete_selected_macros (selection_model->selectedRows ());
+    }
+}
+
+void Configuration::impl::delete_macro ()
+{
+  auto selection_model = ui_->macros_list_view->selectionModel ();
+  if (!selection_model->hasSelection ())
+    {
+      // delete item under cursor if any
+      auto index = selection_model->currentIndex ();
+      if (index.isValid ())
+        {
+          next_macros_.removeRow (index.row ());
+        }
+    }
+  else
+    {
+      // delete the whole selection
+      delete_selected_macros (selection_model->selectedRows ());
+    }
+}
+
+void Configuration::impl::delete_selected_macros (QModelIndexList selected_rows)
+{
+  // sort in reverse row order so that we can delete without changing
+  // indices underneath us
+  qSort (selected_rows.begin (), selected_rows.end (), [] (QModelIndex const& lhs, QModelIndex const& rhs)
+         {
+           return rhs.row () < lhs.row (); // reverse row ordering
+         });
+
+  // now delete them
+  Q_FOREACH (auto index, selected_rows)
+    {
+      next_macros_.removeRow (index.row ());
+    }
+}
+
+void Configuration::impl::on_add_macro_push_button_clicked (bool /* checked */)
+{
+  if (next_macros_.insertRow (next_macros_.rowCount ()))
+    {
+      auto index = next_macros_.index (next_macros_.rowCount () - 1);
+      ui_->macros_list_view->setCurrentIndex (index);
+      next_macros_.setData (index, ui_->add_macro_line_edit->text ());
+      ui_->add_macro_line_edit->clear ();
+    }
+}
+
+void Configuration::impl::delete_frequencies ()
+{
+  auto selection_model = ui_->frequencies_table_view->selectionModel ();
+  selection_model->select (selection_model->selection (), QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows);
+  next_frequencies_.removeDisjointRows (selection_model->selectedRows ());
+}
+
+void Configuration::impl::insert_frequency ()
+{
+  if (QDialog::Accepted == frequency_dialog_->exec ())
+    {
+      ui_->frequencies_table_view->setCurrentIndex (next_frequencies_.add (frequency_dialog_->frequency ()));
+    }
+}
+
+void Configuration::impl::delete_stations ()
+{
+  auto selection_model = ui_->stations_table_view->selectionModel ();
+  selection_model->select (selection_model->selection (), QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows);
+  next_stations_.removeDisjointRows (selection_model->selectedRows ());
+}
+
+void Configuration::impl::insert_station ()
+{
+  if (QDialog::Accepted == station_dialog_->exec ())
+    {
+      ui_->stations_table_view->setCurrentIndex (next_stations_.add (station_dialog_->station ()));
+    }
+}
+
+void Configuration::impl::on_save_path_select_push_button_clicked (bool /* checked */)
+{
+  QFileDialog fd {this, tr ("Save Directory"), ui_->save_path_display_label->text ()};
+  fd.setFileMode (QFileDialog::Directory);
+  fd.setOption (QFileDialog::ShowDirsOnly);
+  if (fd.exec ())
+    {
+      if (fd.selectedFiles ().size ())
+        {
+          ui_->save_path_display_label->setText (fd.selectedFiles ().at (0));
+        }
+    }
+}
+
+bool Configuration::impl::have_rig (bool open_if_closed)
+{
+  if (open_if_closed && !open_rig ())
+    {
+      QMessageBox::critical (this, "WSJT-X", tr ("Failed to open connection to rig"));
+    }
+  return rig_active_;
+}
+
+bool Configuration::impl::open_rig ()
+{
+  auto result = false;
+
+  auto const rig_data = gather_rig_data ();
+  if (!rig_active_ || rig_data != saved_rig_params_)
+    {
+      try
+        {
+          close_rig ();
+
+          // create a new Transceiver object
+          auto rig = transceiver_factory_.create (rig_data, &transceiver_thread_);
+
+          // hook up Configuration transceiver control signals to Transceiver slots
+          //
+          // these connections cross the thread boundary
+          rig_connections_ << connect (this, &Configuration::impl::frequency, rig.get (), &Transceiver::frequency);
+          rig_connections_ << connect (this, &Configuration::impl::tx_frequency, rig.get (), &Transceiver::tx_frequency);
+          rig_connections_ << connect (this, &Configuration::impl::mode, rig.get (), &Transceiver::mode);
+          rig_connections_ << connect (this, &Configuration::impl::ptt, rig.get (), &Transceiver::ptt);
+          rig_connections_ << connect (this, &Configuration::impl::sync, rig.get (), &Transceiver::sync);
+
+          // hook up Transceiver signals to Configuration signals
+          //
+          // these connections cross the thread boundary
+          connect (rig.get (), &Transceiver::update, this, &Configuration::impl::handle_transceiver_update);
+          connect (rig.get (), &Transceiver::failure, this, &Configuration::impl::handle_transceiver_failure);
+
+          // setup thread safe startup and close down semantics
+          rig_connections_ << connect (this, &Configuration::impl::start_transceiver, rig.get (), &Transceiver::start);
+          connect (this, &Configuration::impl::stop_transceiver, rig.get (), &Transceiver::stop);
+
+          auto p = rig.release ();	// take ownership
+          // schedule eventual destruction
+          //
+          // must be queued connection to avoid premature self-immolation
+          // since finished signal is going to be emitted from the object
+          // that will get destroyed in its own stop slot i.e. a same
+          // thread signal to slot connection which by default will be
+          // reduced to a method function call.
+          connect (p, &Transceiver::finished, p, &Transceiver::deleteLater, Qt::QueuedConnection);
+
+          ui_->test_CAT_push_button->setStyleSheet ({});
+          rig_active_ = true;
+          Q_EMIT start_transceiver (); // start rig on its thread
+          result = true;
+        }
+      catch (std::exception const& e)
+        {
+          handle_transceiver_failure (e.what ());
+        }
+
+      saved_rig_params_ = rig_data;
+      rig_changed_ = true;
+    }
+  else
+    {
+      result = true;
+    }
+  return result;
+}
+
+void Configuration::impl::transceiver_frequency (Frequency f)
+{
+  Transceiver::MODE mode {Transceiver::UNK};
+  if (ui_->mode_group_box->isEnabled ())
+    {
+      switch (static_cast<DataMode> (ui_->TX_mode_button_group->checkedId ()))
+        {
+        case data_mode_USB: mode = Transceiver::USB; break;
+        case data_mode_data: mode = Transceiver::DIG_U; break;
+        case data_mode_none: break;
+        }
+    }
+
+  if (cached_rig_state_.frequency () != f
+      || (mode != Transceiver::UNK && mode != cached_rig_state_.mode ()))
+    {
+      cached_rig_state_.frequency (f);
+      cached_rig_state_.mode (mode);
+
+      // lookup offset
+      transceiver_offset_ = stations_.offset (f);
+      Q_EMIT frequency (f + transceiver_offset_, mode);
+    }
+}
+
+void Configuration::impl::transceiver_tx_frequency (Frequency f)
+{
+  if (/* set_mode () || */ cached_rig_state_.tx_frequency () != f || cached_rig_state_.split () != !!f)
+    {
+      cached_rig_state_.tx_frequency (f);
+      cached_rig_state_.split (f);
+
+      // lookup offset if we are in split mode
+      if (f)
+        {
+          transceiver_offset_ = stations_.offset (f);
+          f += transceiver_offset_;
+        }
+
+      // Rationalise TX VFO mode if we ask for split and are
+      // responsible for mode.
+      Q_EMIT tx_frequency (f, cached_rig_state_.split ()
+                           && ui_->mode_group_box->isEnabled ()
+                           && data_mode_none != data_mode_);
+    }
+}
+
+void Configuration::impl::transceiver_mode (MODE m)
+{
+  if (cached_rig_state_.mode () != m)
+    {
+      cached_rig_state_.mode (m);
+
+      // Rationalise mode if we are responsible for it and in split mode.
+      Q_EMIT mode (m, cached_rig_state_.split ()
+                   && ui_->mode_group_box->isEnabled ()
+                   && data_mode_none != data_mode_);
+    }
+}
+
+void Configuration::impl::transceiver_ptt (bool on)
+{
+  cached_rig_state_.ptt (on);
+
+  // pass this on regardless of cache
+  Q_EMIT ptt (on);
+}
+
+void Configuration::impl::sync_transceiver (bool force_signal)
+{
+  // pass this on as cache must be ignored
+  Q_EMIT sync (force_signal);
+}
+
+void Configuration::impl::handle_transceiver_update (TransceiverState state)
+{
+#if WSJT_TRACE_CAT
+  qDebug () << "Configuration::handle_transceiver_update: Transceiver State:" << state;
+#endif
+
+  if (state.online ())
+    {
+      ui_->test_PTT_push_button->setChecked (state.ptt ());
+
+      TransceiverFactory::SplitMode split_mode_selected;
+      if (isVisible ())
+        {
+          ui_->test_CAT_push_button->setStyleSheet ("QPushButton {background-color: green;}");
+
+          auto const& rig = ui_->rig_combo_box->currentText ();
+          auto ptt_method = static_cast<TransceiverFactory::PTTMethod> (ui_->PTT_method_button_group->checkedId ());
+          auto CAT_PTT_enabled = transceiver_factory_.has_CAT_PTT (rig);
+          ui_->test_PTT_push_button->setEnabled ((TransceiverFactory::PTT_method_CAT == ptt_method && CAT_PTT_enabled)
+                                                 || TransceiverFactory::PTT_method_DTR == ptt_method
+                                                 || TransceiverFactory::PTT_method_RTS == ptt_method);
+
+
+          // Follow the setup choice.
+          split_mode_selected = static_cast<TransceiverFactory::SplitMode> (ui_->split_mode_button_group->checkedId ());
+        }
+      else
+        {
+          // Follow the rig unless configuration has been changed.
+          split_mode_selected = static_cast<TransceiverFactory::SplitMode> (rig_params_.split_mode);
+
+          if (enforce_mode_and_split_)
+            {
+              if (TransceiverFactory::basic_transceiver_name_ != ui_->rig_combo_box->currentText ()
+                  && ((TransceiverFactory::split_mode_none != split_mode_selected) != state.split ()))
+                {
+                  if (!setup_split_)
+                    {
+                      // Rig split mode isn't consistent with settings so
+                      // change settings.
+                      //
+                      // For rigs that can't report split mode changes
+                      // (e.g.Icom) this is going to confuse operators, but
+                      // what can we do if they change the rig?
+                      // auto split_mode = state.split () ? TransceiverFactory::split_mode_rig : TransceiverFactory::split_mode_none;
+                      // rig_params_.split_mode = split_mode;
+                      // ui_->split_mode_button_group->button (split_mode)->setChecked (true);
+                      // split_mode_selected = split_mode;
+                      setup_split_ = true;
+                      required_tx_frequency_ = 0;
+
+                      // Q_EMIT self_->transceiver_failure (tr ("Rig split mode setting not consistent with WSJT-X settings. Changing WSJT-X settings for you."));
+                      Q_EMIT self_->transceiver_failure (tr ("Rig split mode setting not consistent with WSJT-X settings."));
+                    }
+                }
+            }
+        }
+
+      // One time rig setup split
+      if (setup_split_ && cached_rig_state_.split () != state.split ())
+        {
+          Q_EMIT tx_frequency (TransceiverFactory::split_mode_none != split_mode_selected ? (required_tx_frequency_ ? required_tx_frequency_ : state.tx_frequency ()) : 0, true);
+        }
+      setup_split_ = false;
+      required_tx_frequency_ = 0;
+    }
+  else
+    {
+      close_rig ();
+    }
+
+  cached_rig_state_ = state;
+
+  // take off offset
+  cached_rig_state_.frequency (cached_rig_state_.frequency () - transceiver_offset_);
+  if (cached_rig_state_.tx_frequency ())
+    {
+      cached_rig_state_.tx_frequency (cached_rig_state_.tx_frequency () - transceiver_offset_);
+    }
+
+  // pass on to clients
+  Q_EMIT self_->transceiver_update (cached_rig_state_);
+}
+
+void Configuration::impl::handle_transceiver_failure (QString reason)
+{
+#if WSJT_TRACE_CAT
+  qDebug () << "Configuration::handle_transceiver_failure: reason:" << reason;
+#endif
+
+  close_rig ();
+  ui_->test_PTT_push_button->setChecked (false);
+
+  if (isVisible ())
+    {
+      message_box (tr ("Rig failure"), reason);
+    }
+  else
+    {
+      // pass on if our dialog isn't active
+      Q_EMIT self_->transceiver_failure (reason);
+    }
+}
+
+void Configuration::impl::close_rig ()
+{
+  ui_->test_PTT_push_button->setEnabled (false);
+
+  // revert to no rig configured
+  if (rig_active_)
+    {
+      ui_->test_CAT_push_button->setStyleSheet ("QPushButton {background-color: red;}");
+      Q_EMIT stop_transceiver ();
+      Q_FOREACH (auto const& connection, rig_connections_)
+        {
+          disconnect (connection);
+        }
+      rig_connections_.clear ();
+      rig_active_ = false;
+    }
+}
+
+// load the available audio devices into the selection combo box and
+// select the default device if the current device isn't set or isn't
+// available
+bool Configuration::impl::load_audio_devices (QAudio::Mode mode, QComboBox * combo_box, QAudioDeviceInfo * device)
+{
+  using std::copy;
+  using std::back_inserter;
+
+  bool result {false};
+
+  combo_box->clear ();
+
+  int current_index = -1;
+  int default_index = -1;
+
+  int extra_items {0};
+
+  auto const& default_device = (mode == QAudio::AudioInput ? QAudioDeviceInfo::defaultInputDevice () : QAudioDeviceInfo::defaultOutputDevice ());
+
+  // deal with special default audio devices on Windows
+  if ("Default Input Device" == default_device.deviceName ()
+      || "Default Output Device" == default_device.deviceName ())
+    {
+      default_index = 0;
+
+      QList<QVariant> channel_counts;
+      auto scc = default_device.supportedChannelCounts ();
+      copy (scc.cbegin (), scc.cend (), back_inserter (channel_counts));
+
+      combo_box->addItem (default_device.deviceName (), channel_counts);
+      ++extra_items;
+      if (default_device == *device)
+        {
+          current_index = 0;
+          result = true;
+        }
+    }
+
+  Q_FOREACH (auto const& p, QAudioDeviceInfo::availableDevices (mode))
+    {
+      // convert supported channel counts into something we can store in the item model
+      QList<QVariant> channel_counts;
+      auto scc = p.supportedChannelCounts ();
+      copy (scc.cbegin (), scc.cend (), back_inserter (channel_counts));
+
+      combo_box->addItem (p.deviceName (), channel_counts);
+      if (p == *device)
+        {
+          current_index = combo_box->count () - 1;
+        }
+      else if (p == default_device)
+        {
+          default_index = combo_box->count () - 1;
+        }
+    }
+  if (current_index < 0)	// not found - use default
+    {
+      *device = default_device;
+      result = true;
+      current_index = default_index;
+    }
+  combo_box->setCurrentIndex (current_index);
+
+  return result;
+}
+
+// enable only the channels that are supported by the selected audio device
+void Configuration::impl::update_audio_channels (QComboBox const * source_combo_box, int index, QComboBox * combo_box, bool allow_both)
+{
+  // disable all items
+  for (int i (0); i < combo_box->count (); ++i)
+    {
+      combo_box->setItemData (i, combo_box_item_disabled, Qt::UserRole - 1);
+    }
+
+  Q_FOREACH (QVariant const& v, source_combo_box->itemData (index).toList ())
+    {
+      // enable valid options
+      int n {v.toInt ()};
+      if (2 == n)
+        {
+          combo_box->setItemData (AudioDevice::Left, combo_box_item_enabled, Qt::UserRole - 1);
+          combo_box->setItemData (AudioDevice::Right, combo_box_item_enabled, Qt::UserRole - 1);
+          if (allow_both)
+            {
+              combo_box->setItemData (AudioDevice::Both, combo_box_item_enabled, Qt::UserRole - 1);
+            }
+        }
+      else if (1 == n)
+        {
+          combo_box->setItemData (AudioDevice::Mono, combo_box_item_enabled, Qt::UserRole - 1);
+        }
+    }
+}
+
+void Configuration::impl::set_application_font (QFont const& font)
+{
+  qApp->setStyleSheet (qApp->styleSheet () + "* {" + font_as_stylesheet (font) + '}');
+}
+
+// load all the supported rig names into the selection combo box
+void Configuration::impl::enumerate_rigs ()
+{
+  ui_->rig_combo_box->clear ();
+
+  auto rigs = transceiver_factory_.supported_transceivers ();
+
+  for (auto r = rigs.cbegin (); r != rigs.cend (); ++r)
+    {
+      if ("None" == r.key ())
+        {
+          // put None first
+          ui_->rig_combo_box->insertItem (0, r.key (), r.value ().model_number_);
+        }
+      else
+        {
+          ui_->rig_combo_box->addItem (r.key (), r.value ().model_number_);
+        }
+    }
+
+  ui_->rig_combo_box->setCurrentText (rig_params_.rig_name);
+}
+
+void Configuration::impl::fill_port_combo_box (QComboBox * cb)
+{
+  auto current_text = cb->currentText ();
+  cb->clear ();
+  Q_FOREACH (auto const& p, QSerialPortInfo::availablePorts ())
+    {
+      if (!p.portName ().contains ( "NULL" )) // virtual serial port pairs
+        {
+          // remove possibly confusing Windows device path (OK because
+          // it gets added back by Hamlib)
+          cb->addItem (p.systemLocation ().remove (QRegularExpression {R"(^\\\\\.\\)"}));
+        }
+    }
+  cb->addItem("USB");
+  cb->setEditText (current_text);
+}
+
+
+#if !defined (QT_NO_DEBUG_STREAM)
+ENUM_QDEBUG_OPS_IMPL (Configuration, DataMode);
+ENUM_QDEBUG_OPS_IMPL (Configuration, Type2MsgGen);
+#endif
+
+ENUM_QDATASTREAM_OPS_IMPL (Configuration, DataMode);
+ENUM_QDATASTREAM_OPS_IMPL (Configuration, Type2MsgGen);
+
+ENUM_CONVERSION_OPS_IMPL (Configuration, DataMode);
+ENUM_CONVERSION_OPS_IMPL (Configuration, Type2MsgGen);
diff --git a/Configuration.hpp b/Configuration.hpp
new file mode 100644
index 0000000..e2003d1
--- /dev/null
+++ b/Configuration.hpp
@@ -0,0 +1,219 @@
+#ifndef CONFIGURATION_HPP_
+#define CONFIGURATION_HPP_
+
+#include <QObject>
+
+#include "Radio.hpp"
+#include "AudioDevice.hpp"
+#include "Transceiver.hpp"
+
+#include "pimpl_h.hpp"
+
+class QSettings;
+class QWidget;
+class QAudioDeviceInfo;
+class QString;
+class QDir;
+class QFont;
+class Bands;
+class FrequencyList;
+class StationList;
+class QStringListModel;
+class QHostAddress;
+
+//
+// Class Configuration
+//
+//  Encapsulates the control, access  and, persistence of user defined
+//  settings for the wsjtx GUI.  Setting values are accessed through a
+//  QDialog window containing concept orientated tab windows.
+//
+// Responsibilities
+//
+//  Provides management of  the CAT and PTT  rig interfaces, providing
+//  control access  via a minimal generic  set of Qt slots  and status
+//  updates via Qt signals.  Internally  the rig control capability is
+//  farmed out  to a  separate thread  since many  of the  rig control
+//  functions are blocking.
+//
+//  All user  settings required by  the wsjtx GUI are  exposed through
+//  query methods.  Settings only become  visible once they  have been
+//  accepted by the user which is  done by clicking the "OK" button on
+//  the settings dialog.
+//
+//  The QSettings instance  passed to the constructor is  used to read
+//  and write user settings.
+//
+//  Pointers to three QAbstractItemModel  objects are provided to give
+//  access to amateur band  information, user working frequencies and,
+//  user operating  band information.  These porovide  consistent data
+//  models that can  be used in GUI lists or  tables or simply queried
+//  for user defined bands, default operating frequencies and, station
+//  descriptions.
+//
+class Configuration final
+  : public QObject
+{
+  Q_OBJECT;
+  Q_ENUMS (DataMode Type2MsgGen);
+
+public:
+  using MODE = Transceiver::MODE;
+  using TransceiverState = Transceiver::TransceiverState;
+  using Frequency = Radio::Frequency;
+  using port_type = quint16;
+
+  enum DataMode {data_mode_none, data_mode_USB, data_mode_data};
+  enum Type2MsgGen {type_2_msg_1_full, type_2_msg_3_full, type_2_msg_5_only};
+
+  explicit Configuration (QSettings * settings, QWidget * parent = nullptr);
+  ~Configuration ();
+
+  int exec ();
+
+  QDir temp_dir () const;
+  QDir doc_dir () const;
+
+  QAudioDeviceInfo const& audio_input_device () const;
+  AudioDevice::Channel audio_input_channel () const;
+  QAudioDeviceInfo const& audio_output_device () const;
+  AudioDevice::Channel audio_output_channel () const;
+
+  // These query methods should be used after a call to exec() to
+  // determine if either the audio input or audio output stream
+  // parameters have changed. The respective streams should be
+  // re-opened if they return true.
+  bool restart_audio_input () const;
+  bool restart_audio_output () const;
+
+  QString my_callsign () const;
+  QString my_grid () const;
+  QFont decoded_text_font () const;
+  qint32 id_interval () const;
+  bool id_after_73 () const;
+  bool tx_QSY_allowed () const;
+  bool spot_to_psk_reporter () const;
+  bool monitor_off_at_startup () const;
+  bool monitor_last_used () const;
+  bool log_as_RTTY () const;
+  bool report_in_comments () const;
+  bool prompt_to_log () const;
+  bool insert_blank () const;
+  bool DXCC () const;
+  bool clear_DX () const;
+  bool miles () const;
+  bool quick_call () const;
+  bool disable_TX_on_73 () const;
+  bool watchdog () const;
+  bool TX_messages () const;
+  bool split_mode () const;
+  bool post_decodes () const;
+  QString udp_server_name () const;
+  port_type udp_server_port () const;
+  bool accept_udp_requests () const;
+  bool udpWindowToFront () const;
+  bool udpWindowRestore () const;
+  Bands * bands ();
+  FrequencyList * frequencies ();
+  StationList * stations ();
+  QStringListModel * macros ();
+  QDir save_directory () const;
+  QString rig_name () const;
+  unsigned jt9w_bw_mult () const;
+  float jt9w_min_dt () const;
+  float jt9w_max_dt () const;
+  Type2MsgGen type_2_msg_gen () const;
+  QColor color_CQ () const;
+  QColor color_MyCall () const;
+  QColor color_TxMsg () const;
+  QColor color_DXCC () const;
+  QColor color_NewCall () const;
+
+  // This method queries if a CAT and PTT connection is operational,
+  //
+  // It also doubles as an initialisation method when the
+  // open_if_closed parameter is passed as true.
+  bool transceiver_online (bool open_if_closed = false);
+
+  // Close down connection to rig.
+  void transceiver_offline ();
+
+  // Set transceiver frequency in Hertz.
+  Q_SLOT void transceiver_frequency (Frequency);
+
+  // Setting a non zero TX frequency means split operation
+  // rationalise_mode means ensure TX uses same mode as RX.
+  Q_SLOT void transceiver_tx_frequency (Frequency = 0u);
+
+  // Set transceiver mode.
+  //
+  // Rationalise means ensure TX uses same mode as RX.
+  Q_SLOT void transceiver_mode (MODE);
+
+  // Set/unset PTT.
+  //
+  // Note that this must be called even if VOX PTT is selected since
+  // the "Emulate Split" mode requires PTT information to coordinate
+  // frequency changes.
+  Q_SLOT void transceiver_ptt (bool = true);
+
+  // Attempt to (re-)synchronise transceiver state.
+  //
+  // Force signal guarantees either a transceiver_update or a
+  // transceiver_failure signal.
+  //
+  // The enforce_mode_and_split parameter ensures that future
+  // transceiver updates have the correct mode and split setting
+  // i.e. the transceiver is ready for use.
+  Q_SLOT void sync_transceiver (bool force_signal = false, bool enforce_mode_and_split = false);
+
+
+  //
+  // This signal indicates that a font has been selected and accepted
+  // for the decoded text.
+  //
+  Q_SIGNAL void decoded_text_font_changed (QFont);
+
+  //
+  // This signal is emitted when the UDP server changes
+  //
+  Q_SIGNAL void udp_server_changed (QString const& udp_server);
+  Q_SIGNAL void udp_server_port_changed (port_type server_port);
+
+
+  //
+  // These signals are emitted and reflect transceiver state changes
+  //
+
+  // signals a change in one of the TransceiverState members
+  Q_SIGNAL void transceiver_update (Transceiver::TransceiverState) const;
+
+  // Signals a failure of a control rig CAT or PTT connection.
+  //
+  // A failed rig CAT or PTT connection is fatal and the underlying
+  // connections are closed automatically. The connections can be
+  // re-established with a call to transceiver_online(true) assuming
+  // the fault condition has been rectified or is transient.
+  Q_SIGNAL void transceiver_failure (QString reason) const;
+
+private:
+  class impl;
+  pimpl<impl> m_;
+};
+
+
+Q_DECLARE_METATYPE (Configuration::DataMode);
+Q_DECLARE_METATYPE (Configuration::Type2MsgGen);
+
+#if !defined (QT_NO_DEBUG_STREAM)
+ENUM_QDEBUG_OPS_DECL (Configuration, DataMode);
+ENUM_QDEBUG_OPS_DECL (Configuration, Type2MsgGen);
+#endif
+
+ENUM_QDATASTREAM_OPS_DECL (Configuration, DataMode);
+ENUM_QDATASTREAM_OPS_DECL (Configuration, Type2MsgGen);
+
+ENUM_CONVERSION_OPS_DECL (Configuration, DataMode);
+ENUM_CONVERSION_OPS_DECL (Configuration, Type2MsgGen);
+
+#endif
diff --git a/Configuration.ui b/Configuration.ui
new file mode 100644
index 0000000..c449217
--- /dev/null
+++ b/Configuration.ui
@@ -0,0 +1,2248 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>configuration_dialog</class>
+ <widget class="QDialog" name="configuration_dialog">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>685</width>
+    <height>612</height>
+   </rect>
+  </property>
+  <property name="sizePolicy">
+   <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
+    <horstretch>0</horstretch>
+    <verstretch>0</verstretch>
+   </sizepolicy>
+  </property>
+  <property name="minimumSize">
+   <size>
+    <width>528</width>
+    <height>448</height>
+   </size>
+  </property>
+  <property name="windowTitle">
+   <string>Settings</string>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout_2">
+   <item>
+    <widget class="QTabWidget" name="configuration_tabs">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+       <horstretch>0</horstretch>
+       <verstretch>0</verstretch>
+      </sizepolicy>
+     </property>
+     <property name="minimumSize">
+      <size>
+       <width>80</width>
+       <height>20</height>
+      </size>
+     </property>
+     <property name="toolTip">
+      <string>Select tab to change configuration parameters.</string>
+     </property>
+     <property name="currentIndex">
+      <number>0</number>
+     </property>
+     <widget class="QWidget" name="general_tab">
+      <attribute name="title">
+       <string>Genera&l</string>
+      </attribute>
+      <attribute name="toolTip">
+       <string>General station details and settings.</string>
+      </attribute>
+      <layout class="QVBoxLayout" name="verticalLayout_4">
+       <item>
+        <widget class="QGroupBox" name="station_group_box">
+         <property name="title">
+          <string>Station Details</string>
+         </property>
+         <layout class="QGridLayout" name="gridLayout_14">
+          <item row="0" column="3">
+           <widget class="QLabel" name="grid_label">
+            <property name="text">
+             <string>M&y Grid:</string>
+            </property>
+            <property name="buddy">
+             <cstring>grid_line_edit</cstring>
+            </property>
+           </widget>
+          </item>
+          <item row="0" column="0">
+           <widget class="QLabel" name="callsign_label">
+            <property name="text">
+             <string>My C&all:</string>
+            </property>
+            <property name="buddy">
+             <cstring>callsign_line_edit</cstring>
+            </property>
+           </widget>
+          </item>
+          <item row="0" column="4">
+           <widget class="QLineEdit" name="grid_line_edit">
+            <property name="toolTip">
+             <string>Maidenhead locator (only the first four characters are required).</string>
+            </property>
+           </widget>
+          </item>
+          <item row="0" column="1">
+           <widget class="QLineEdit" name="callsign_line_edit">
+            <property name="toolTip">
+             <string>Station callsign.</string>
+            </property>
+           </widget>
+          </item>
+          <item row="0" column="2">
+           <spacer name="horizontalSpacer_4">
+            <property name="orientation">
+             <enum>Qt::Horizontal</enum>
+            </property>
+            <property name="sizeHint" stdset="0">
+             <size>
+              <width>40</width>
+              <height>20</height>
+             </size>
+            </property>
+           </spacer>
+          </item>
+          <item row="1" column="4">
+           <widget class="QComboBox" name="type_2_msg_gen_combo_box">
+            <property name="enabled">
+             <bool>true</bool>
+            </property>
+            <property name="toolTip">
+             <string><html><head/><body><p>Type 2 compound callsigns are those with prefixes or suffixes not included in the allowed shortlist (See Help-&gt;Add-on prefixes and suffixes).</p><p>This option determines which generated messages should contain your full type 2 compound call sign rather than your base callsign. It only applies if you have a type 2 compound callsign.</p><p>This option controls the way the messages that are us [...]
+            </property>
+            <property name="currentIndex">
+             <number>1</number>
+            </property>
+            <item>
+             <property name="text">
+              <string>Full call in Tx1</string>
+             </property>
+            </item>
+            <item>
+             <property name="text">
+              <string>Full call in Tx3</string>
+             </property>
+            </item>
+            <item>
+             <property name="text">
+              <string>Full call in Tx5 only</string>
+             </property>
+            </item>
+           </widget>
+          </item>
+          <item row="1" column="0" colspan="4">
+           <widget class="QLabel" name="label_5">
+            <property name="text">
+             <string>Message generation for type 2 compound callsign holders:</string>
+            </property>
+            <property name="alignment">
+             <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+            </property>
+            <property name="buddy">
+             <cstring>type_2_msg_gen_combo_box</cstring>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </widget>
+       </item>
+       <item>
+        <widget class="Line" name="line_5">
+         <property name="orientation">
+          <enum>Qt::Horizontal</enum>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <widget class="QGroupBox" name="display_group_box">
+         <property name="title">
+          <string>Display</string>
+         </property>
+         <layout class="QGridLayout" name="gridLayout_4">
+          <item row="3" column="0">
+           <widget class="QCheckBox" name="DXCC_check_box">
+            <property name="toolTip">
+             <string>Show if decoded stations are new DXCC entities or worked before.</string>
+            </property>
+            <property name="text">
+             <string>Show &DXCC entity and worked before status</string>
+            </property>
+            <property name="checked">
+             <bool>false</bool>
+            </property>
+           </widget>
+          </item>
+          <item row="0" column="0">
+           <widget class="QCheckBox" name="insert_blank_check_box">
+            <property name="toolTip">
+             <string>Include a separator line between periods in the band activity window.</string>
+            </property>
+            <property name="text">
+             <string>&Blank line between decoding periods</string>
+            </property>
+           </widget>
+          </item>
+          <item row="0" column="2" rowspan="4">
+           <layout class="QVBoxLayout" name="verticalLayout_6">
+            <item>
+             <widget class="QPushButton" name="font_push_button">
+              <property name="toolTip">
+               <string>Set the font characteristics for the application.</string>
+              </property>
+              <property name="text">
+               <string>Font...</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QPushButton" name="decoded_text_font_push_button">
+              <property name="toolTip">
+               <string>Set the font characteristics for the Band Activity and Rx Frequency areas.</string>
+              </property>
+              <property name="text">
+               <string>Decoded Text Font...</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <spacer name="verticalSpacer">
+              <property name="orientation">
+               <enum>Qt::Vertical</enum>
+              </property>
+              <property name="sizeHint" stdset="0">
+               <size>
+                <width>20</width>
+                <height>40</height>
+               </size>
+              </property>
+             </spacer>
+            </item>
+           </layout>
+          </item>
+          <item row="1" column="0">
+           <widget class="QCheckBox" name="miles_check_box">
+            <property name="toolTip">
+             <string>Show distance to DX station in miles rather than kilometers.</string>
+            </property>
+            <property name="text">
+             <string>Display dista&nce in miles</string>
+            </property>
+           </widget>
+          </item>
+          <item row="2" column="0">
+           <widget class="QCheckBox" name="TX_messages_check_box">
+            <property name="toolTip">
+             <string>Show outgoing transmitted messages in the Rx frequency window.</string>
+            </property>
+            <property name="text">
+             <string>&Tx messages to Rx frequency window</string>
+            </property>
+           </widget>
+          </item>
+          <item row="0" column="1">
+           <spacer name="horizontalSpacer_2">
+            <property name="orientation">
+             <enum>Qt::Horizontal</enum>
+            </property>
+            <property name="sizeHint" stdset="0">
+             <size>
+              <width>40</width>
+              <height>20</height>
+             </size>
+            </property>
+           </spacer>
+          </item>
+         </layout>
+        </widget>
+       </item>
+       <item>
+        <widget class="Line" name="line_7">
+         <property name="orientation">
+          <enum>Qt::Horizontal</enum>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <widget class="QGroupBox" name="behaviour_group_box">
+         <property name="title">
+          <string>Behavior</string>
+         </property>
+         <layout class="QGridLayout" name="gridLayout_8">
+          <item row="2" column="0">
+           <widget class="QCheckBox" name="disable_TX_on_73_check_box">
+            <property name="toolTip">
+             <string>Turns off automatic transmissions after sending a 73 or any other free
+text message.</string>
+            </property>
+            <property name="text">
+             <string>Di&sable Tx after sending 73</string>
+            </property>
+           </widget>
+          </item>
+          <item row="3" column="0">
+           <widget class="QCheckBox" name="watchdog_check_box">
+            <property name="toolTip">
+             <string>Stop transmitting automatically after five periods.</string>
+            </property>
+            <property name="text">
+             <string>Runaway Tx &watchdog</string>
+            </property>
+           </widget>
+          </item>
+          <item row="1" column="0">
+           <widget class="QCheckBox" name="quick_call_check_box">
+            <property name="toolTip">
+             <string>Automatic transmission mode.</string>
+            </property>
+            <property name="text">
+             <string>Doubl&e-click on call sets Tx enable</string>
+            </property>
+           </widget>
+          </item>
+          <item row="0" column="0">
+           <widget class="QCheckBox" name="monitor_off_check_box">
+            <property name="toolTip">
+             <string>Don't start decoding until the monitor button is clicked.</string>
+            </property>
+            <property name="text">
+             <string>Mon&itor off at startup</string>
+            </property>
+            <property name="checked">
+             <bool>false</bool>
+            </property>
+           </widget>
+          </item>
+          <item row="5" column="0" colspan="2">
+           <layout class="QHBoxLayout" name="horizontalLayout_9">
+            <item>
+             <widget class="QCheckBox" name="CW_id_after_73_check_box">
+              <property name="toolTip">
+               <string>Send a CW ID after every 73 or free text message.</string>
+              </property>
+              <property name="text">
+               <string>CW ID a&fter 73</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <spacer name="horizontalSpacer">
+              <property name="orientation">
+               <enum>Qt::Horizontal</enum>
+              </property>
+              <property name="sizeHint" stdset="0">
+               <size>
+                <width>40</width>
+                <height>20</height>
+               </size>
+              </property>
+             </spacer>
+            </item>
+            <item>
+             <widget class="QLabel" name="label">
+              <property name="sizePolicy">
+               <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+                <horstretch>0</horstretch>
+                <verstretch>0</verstretch>
+               </sizepolicy>
+              </property>
+              <property name="text">
+               <string>Periodic CW ID Inter&val:</string>
+              </property>
+              <property name="buddy">
+               <cstring>CW_id_interval_spin_box</cstring>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QSpinBox" name="CW_id_interval_spin_box">
+              <property name="sizePolicy">
+               <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
+                <horstretch>0</horstretch>
+                <verstretch>0</verstretch>
+               </sizepolicy>
+              </property>
+              <property name="toolTip">
+               <string>Send a CW ID periodically every few minutes.
+This might be required under your countries licence regulations.
+It will not interfere with other users as it is always sent in the
+quiet period when decoding is done.</string>
+              </property>
+             </widget>
+            </item>
+           </layout>
+          </item>
+          <item row="0" column="1">
+           <widget class="QCheckBox" name="monitor_last_used_check_box">
+            <property name="toolTip">
+             <string><html><head/><body><p>Check this if you wish to automatically return to the last monitored frequency when monitor is enabled, leave it unchecked if you wish to have the current rig frequency maintained.</p></body></html></string>
+            </property>
+            <property name="text">
+             <string>Monitor returns to last used frequency</string>
+            </property>
+           </widget>
+          </item>
+          <item row="1" column="1">
+           <widget class="QCheckBox" name="tx_QSY_check_box">
+            <property name="toolTip">
+             <string><html><head/><body><p>Some rigs are not able to process CAT commands while transmitting. This means that if you are operating in split mode you may have to uncheck this option.</p></body></html></string>
+            </property>
+            <property name="text">
+             <string>Allow Tx frequency changes while transmitting</string>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </widget>
+       </item>
+      </layout>
+     </widget>
+     <widget class="QWidget" name="radio_tab">
+      <attribute name="title">
+       <string>&Radio</string>
+      </attribute>
+      <attribute name="toolTip">
+       <string>Radio interface configuration settings.</string>
+      </attribute>
+      <layout class="QGridLayout" name="gridLayout_3">
+       <item row="1" column="0" rowspan="11">
+        <widget class="QGroupBox" name="CAT_control_group_box">
+         <property name="sizePolicy">
+          <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+           <horstretch>0</horstretch>
+           <verstretch>0</verstretch>
+          </sizepolicy>
+         </property>
+         <property name="toolTip">
+          <string>Settings that control your CAT interface.</string>
+         </property>
+         <property name="title">
+          <string>CAT Control</string>
+         </property>
+         <layout class="QVBoxLayout" name="verticalLayout_3">
+          <item>
+           <layout class="QFormLayout" name="formLayout">
+            <property name="fieldGrowthPolicy">
+             <enum>QFormLayout::ExpandingFieldsGrow</enum>
+            </property>
+            <item row="0" column="0">
+             <widget class="QLabel" name="CAT_port_label">
+              <property name="text">
+               <string>Port:</string>
+              </property>
+              <property name="buddy">
+               <cstring>CAT_port_combo_box</cstring>
+              </property>
+             </widget>
+            </item>
+            <item row="0" column="1">
+             <widget class="QComboBox" name="CAT_port_combo_box">
+              <property name="sizePolicy">
+               <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
+                <horstretch>1</horstretch>
+                <verstretch>0</verstretch>
+               </sizepolicy>
+              </property>
+              <property name="toolTip">
+               <string>Serial port used for CAT control.</string>
+              </property>
+              <property name="editable">
+               <bool>true</bool>
+              </property>
+              <property name="currentText">
+               <string/>
+              </property>
+              <property name="insertPolicy">
+               <enum>QComboBox::NoInsert</enum>
+              </property>
+             </widget>
+            </item>
+           </layout>
+          </item>
+          <item>
+           <widget class="QGroupBox" name="CAT_serial_port_parameters_group_box">
+            <property name="sizePolicy">
+             <sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
+              <horstretch>0</horstretch>
+              <verstretch>0</verstretch>
+             </sizepolicy>
+            </property>
+            <property name="title">
+             <string>Serial Port Parameters</string>
+            </property>
+            <layout class="QVBoxLayout" name="verticalLayout">
+             <item>
+              <layout class="QFormLayout" name="formLayout_5">
+               <property name="fieldGrowthPolicy">
+                <enum>QFormLayout::ExpandingFieldsGrow</enum>
+               </property>
+               <item row="0" column="0">
+                <widget class="QLabel" name="CAT_baud_label">
+                 <property name="text">
+                  <string>Baud Rate:</string>
+                 </property>
+                 <property name="buddy">
+                  <cstring>CAT_serial_baud_combo_box</cstring>
+                 </property>
+                </widget>
+               </item>
+               <item row="0" column="1">
+                <widget class="QComboBox" name="CAT_serial_baud_combo_box">
+                 <property name="sizePolicy">
+                  <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
+                   <horstretch>0</horstretch>
+                   <verstretch>0</verstretch>
+                  </sizepolicy>
+                 </property>
+                 <property name="toolTip">
+                  <string>Serial port data rate which must match the setting of your radio.</string>
+                 </property>
+                 <property name="currentIndex">
+                  <number>0</number>
+                 </property>
+                 <item>
+                  <property name="text">
+                   <string>1200</string>
+                  </property>
+                 </item>
+                 <item>
+                  <property name="text">
+                   <string>2400</string>
+                  </property>
+                 </item>
+                 <item>
+                  <property name="text">
+                   <string>4800</string>
+                  </property>
+                 </item>
+                 <item>
+                  <property name="text">
+                   <string>9600</string>
+                  </property>
+                 </item>
+                 <item>
+                  <property name="text">
+                   <string>19200</string>
+                  </property>
+                 </item>
+                 <item>
+                  <property name="text">
+                   <string>38400</string>
+                  </property>
+                 </item>
+                 <item>
+                  <property name="text">
+                   <string>57600</string>
+                  </property>
+                 </item>
+                 <item>
+                  <property name="text">
+                   <string>115200</string>
+                  </property>
+                 </item>
+                </widget>
+               </item>
+              </layout>
+             </item>
+             <item>
+              <widget class="QGroupBox" name="CAT_data_bits_group_box">
+               <property name="toolTip">
+                <string><html><head/><body><p>Number of data bits used to communicate with your radio's CAT interface (usually eight).</p></body></html></string>
+               </property>
+               <property name="title">
+                <string>Data Bits</string>
+               </property>
+               <layout class="QHBoxLayout" name="horizontalLayout_4">
+                <item>
+                 <widget class="QRadioButton" name="CAT_7_bit_radio_button">
+                  <property name="text">
+                   <string>Se&ven</string>
+                  </property>
+                  <attribute name="buttonGroup">
+                   <string notr="true">CAT_data_bits_button_group</string>
+                  </attribute>
+                 </widget>
+                </item>
+                <item>
+                 <widget class="QRadioButton" name="CAT_8_bit_radio_button">
+                  <property name="text">
+                   <string>E&ight</string>
+                  </property>
+                  <property name="checked">
+                   <bool>true</bool>
+                  </property>
+                  <attribute name="buttonGroup">
+                   <string notr="true">CAT_data_bits_button_group</string>
+                  </attribute>
+                 </widget>
+                </item>
+               </layout>
+              </widget>
+             </item>
+             <item>
+              <widget class="QGroupBox" name="CAT_stop_bits_group_box">
+               <property name="toolTip">
+                <string><html><head/><body><p>Number of stop bits used when communicating with your radio's CAT interface</p><p>(consult you radio's manual for details).</p></body></html></string>
+               </property>
+               <property name="title">
+                <string>Stop Bits</string>
+               </property>
+               <layout class="QHBoxLayout" name="horizontalLayout_2">
+                <item>
+                 <widget class="QRadioButton" name="CAT_one_stop_bit_radio_button">
+                  <property name="text">
+                   <string>On&e</string>
+                  </property>
+                  <attribute name="buttonGroup">
+                   <string notr="true">CAT_stop_bits_button_group</string>
+                  </attribute>
+                 </widget>
+                </item>
+                <item>
+                 <widget class="QRadioButton" name="CAT_two_stop_bit_radio_button">
+                  <property name="text">
+                   <string>T&wo</string>
+                  </property>
+                  <property name="checked">
+                   <bool>true</bool>
+                  </property>
+                  <attribute name="buttonGroup">
+                   <string notr="true">CAT_stop_bits_button_group</string>
+                  </attribute>
+                 </widget>
+                </item>
+               </layout>
+              </widget>
+             </item>
+             <item>
+              <widget class="QGroupBox" name="CAT_handshake_group_box">
+               <property name="toolTip">
+                <string><html><head/><body><p>Flow control protocol used between this computer and your radio's CAT interface (usually &quot;None&quot; but some require &quot;Hardware&quot;).</p></body></html></string>
+               </property>
+               <property name="title">
+                <string>Handshake</string>
+               </property>
+               <layout class="QGridLayout" name="gridLayout_11">
+                <item row="0" column="0">
+                 <widget class="QRadioButton" name="CAT_handshake_none_radio_button">
+                  <property name="text">
+                   <string>&None</string>
+                  </property>
+                  <property name="checked">
+                   <bool>true</bool>
+                  </property>
+                  <attribute name="buttonGroup">
+                   <string notr="true">CAT_handshake_button_group</string>
+                  </attribute>
+                 </widget>
+                </item>
+                <item row="0" column="1">
+                 <widget class="QRadioButton" name="CAT_handshake_xon_radio_button">
+                  <property name="toolTip">
+                   <string>Software flow control (very rare on CAT interfaces).</string>
+                  </property>
+                  <property name="text">
+                   <string>XON/XOFF</string>
+                  </property>
+                  <attribute name="buttonGroup">
+                   <string notr="true">CAT_handshake_button_group</string>
+                  </attribute>
+                 </widget>
+                </item>
+                <item row="0" column="2">
+                 <widget class="QRadioButton" name="CAT_handshake_hardware_radio_button">
+                  <property name="toolTip">
+                   <string>Flow control using the RTS and CTS RS-232 control lines
+not often used but some radios have it as an option and 
+a few, particularly some Kenwood rigs, require it).</string>
+                  </property>
+                  <property name="text">
+                   <string>&Hardware</string>
+                  </property>
+                  <attribute name="buttonGroup">
+                   <string notr="true">CAT_handshake_button_group</string>
+                  </attribute>
+                 </widget>
+                </item>
+               </layout>
+              </widget>
+             </item>
+             <item>
+              <widget class="QGroupBox" name="CAT_control_lines_group_box">
+               <property name="toolTip">
+                <string>Special control of CAT port control lines.</string>
+               </property>
+               <property name="title">
+                <string>Force Control Lines</string>
+               </property>
+               <property name="checkable">
+                <bool>true</bool>
+               </property>
+               <property name="checked">
+                <bool>false</bool>
+               </property>
+               <layout class="QHBoxLayout" name="horizontalLayout_8">
+                <item>
+                 <widget class="QCheckBox" name="CAT_DTR_check_box">
+                  <property name="toolTip">
+                   <string><html><head/><body><p>Force the DTR control linelow or high on the CAT serial port.</p><p>This is required for a few CAT interfaces that are powered</p><p>from the DTR control line.</p><p>Normally you should leave this unchecked.</p></body></html></string>
+                  </property>
+                  <property name="text">
+                   <string>DTR</string>
+                  </property>
+                 </widget>
+                </item>
+                <item>
+                 <widget class="QCheckBox" name="CAT_RTS_check_box">
+                  <property name="toolTip">
+                   <string><html><head/><body><p>Force the RTS control line low or high on the CAT serial port.</p><p>This is required for a few CAT interfaces that are powered</p><p>from the RTS control line.</p><p>Normally you should leave this unchecked.</p><p>This option is only available if Hardware handshaking is not</p><p>selected above.</p></body></html></string>
+                  </property>
+                  <property name="text">
+                   <string>RTS</string>
+                  </property>
+                 </widget>
+                </item>
+               </layout>
+              </widget>
+             </item>
+            </layout>
+           </widget>
+          </item>
+         </layout>
+        </widget>
+       </item>
+       <item row="6" column="2">
+        <widget class="Line" name="line_6">
+         <property name="orientation">
+          <enum>Qt::Horizontal</enum>
+         </property>
+        </widget>
+       </item>
+       <item row="1" column="1" rowspan="12">
+        <widget class="Line" name="line">
+         <property name="orientation">
+          <enum>Qt::Vertical</enum>
+         </property>
+        </widget>
+       </item>
+       <item row="1" column="2">
+        <widget class="QGroupBox" name="PTT_method_group_box">
+         <property name="sizePolicy">
+          <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
+           <horstretch>0</horstretch>
+           <verstretch>0</verstretch>
+          </sizepolicy>
+         </property>
+         <property name="toolTip">
+          <string>How this program activates the PTT on your radio</string>
+         </property>
+         <property name="title">
+          <string>PTT Method</string>
+         </property>
+         <layout class="QGridLayout" name="gridLayout_2">
+          <item row="0" column="0">
+           <widget class="QRadioButton" name="PTT_VOX_radio_button">
+            <property name="toolTip">
+             <string><html><head/><body><p>No PTT activation, instead the radio's automatic VOX is used to key the transmitter.</p><p>Use this if you have no radio interface hardware.</p></body></html></string>
+            </property>
+            <property name="text">
+             <string>VO&X</string>
+            </property>
+            <attribute name="buttonGroup">
+             <string notr="true">PTT_method_button_group</string>
+            </attribute>
+           </widget>
+          </item>
+          <item row="0" column="1">
+           <widget class="QRadioButton" name="PTT_DTR_radio_button">
+            <property name="toolTip">
+             <string><html><head/><body><p>Use the RS-232 DTR control line to toggle your radio's PTT,</p><p>requires hardware to inteface the line.</p><p>Some commercial interface units also use this method.</p><p>The DTR control line of the CAT serial port may be used for this or</p><p>a DTR control line on a different serial port may be used.</p></body></html></string>
+            </property>
+            <property name="text">
+             <string>&DTR</string>
+            </property>
+            <property name="checked">
+             <bool>true</bool>
+            </property>
+            <attribute name="buttonGroup">
+             <string notr="true">PTT_method_button_group</string>
+            </attribute>
+           </widget>
+          </item>
+          <item row="1" column="0">
+           <widget class="QRadioButton" name="PTT_CAT_radio_button">
+            <property name="toolTip">
+             <string>Some radios support PTT via CAT commands,
+use this option if your radio supports it and you have no
+other hardware interface for PTT.</string>
+            </property>
+            <property name="text">
+             <string>C&AT</string>
+            </property>
+            <attribute name="buttonGroup">
+             <string notr="true">PTT_method_button_group</string>
+            </attribute>
+           </widget>
+          </item>
+          <item row="1" column="1">
+           <widget class="QRadioButton" name="PTT_RTS_radio_button">
+            <property name="toolTip">
+             <string><html><head/><body><p>Use the RS-232 RTS control line to toggle your radio's PTT,</p><p>requires hardware to inteface the line.</p><p>Some commercial interface units also use this method.</p><p>The RTS control line of the CAT serial port may be used for this or</p><p>a RTS control line on a different serial port may be used.</p><p>Note that this options is not available on the CAT ser [...]
+            </property>
+            <property name="text">
+             <string>R&TS</string>
+            </property>
+            <attribute name="buttonGroup">
+             <string notr="true">PTT_method_button_group</string>
+            </attribute>
+           </widget>
+          </item>
+          <item row="2" column="0" rowspan="2" colspan="2">
+           <layout class="QFormLayout" name="formLayout_4">
+            <property name="fieldGrowthPolicy">
+             <enum>QFormLayout::ExpandingFieldsGrow</enum>
+            </property>
+            <item row="0" column="0">
+             <widget class="QLabel" name="PTT_port_label">
+              <property name="text">
+               <string>Port:</string>
+              </property>
+              <property name="buddy">
+               <cstring>PTT_port_combo_box</cstring>
+              </property>
+             </widget>
+            </item>
+            <item row="0" column="1">
+             <widget class="QComboBox" name="PTT_port_combo_box">
+              <property name="sizePolicy">
+               <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
+                <horstretch>1</horstretch>
+                <verstretch>0</verstretch>
+               </sizepolicy>
+              </property>
+              <property name="toolTip">
+               <string><html><head/><body><p>Select the RS-232 serial port utilised for PTT control,</p><p>this option is available when DTR or RTS is selected above</p><p>as a transmit method.</p><p>This port can be the same one as the one used for CAT control.</p><p>For some interface types the special value CAT may be chosen,</p><p>this is used for non-serial CAT interfaces that can control</p>&l [...]
+              </property>
+              <property name="editable">
+               <bool>true</bool>
+              </property>
+              <property name="currentText">
+               <string/>
+              </property>
+              <property name="currentIndex">
+               <number>-1</number>
+              </property>
+              <property name="insertPolicy">
+               <enum>QComboBox::NoInsert</enum>
+              </property>
+             </widget>
+            </item>
+           </layout>
+          </item>
+         </layout>
+        </widget>
+       </item>
+       <item row="5" column="2">
+        <widget class="QGroupBox" name="mode_group_box">
+         <property name="toolTip">
+          <string>Modulation mode selected on radio.</string>
+         </property>
+         <property name="title">
+          <string>Mode</string>
+         </property>
+         <layout class="QGridLayout" name="gridLayout_10">
+          <item row="0" column="1">
+           <widget class="QRadioButton" name="mode_USB_radio_button">
+            <property name="toolTip">
+             <string><html><head/><body><p>USB is usually the correct modulation mode,</p><p>unless the radio has a special data or packet mode setting</p><p>for AFSK operation.</p></body></html></string>
+            </property>
+            <property name="text">
+             <string>US&B</string>
+            </property>
+            <property name="checked">
+             <bool>true</bool>
+            </property>
+            <attribute name="buttonGroup">
+             <string notr="true">TX_mode_button_group</string>
+            </attribute>
+           </widget>
+          </item>
+          <item row="0" column="0">
+           <widget class="QRadioButton" name="mode_none_radio_button">
+            <property name="toolTip">
+             <string>Don't allow the program to set the radio mode
+(not recommended but use if the wrong mode
+or bandwidth is selected).</string>
+            </property>
+            <property name="text">
+             <string>None</string>
+            </property>
+            <attribute name="buttonGroup">
+             <string notr="true">TX_mode_button_group</string>
+            </attribute>
+           </widget>
+          </item>
+          <item row="0" column="2">
+           <widget class="QRadioButton" name="mode_data_radio_button">
+            <property name="toolTip">
+             <string>If this is availabe then it is usually the correct mode for this program.</string>
+            </property>
+            <property name="text">
+             <string>Data/P&kt</string>
+            </property>
+            <attribute name="buttonGroup">
+             <string notr="true">TX_mode_button_group</string>
+            </attribute>
+           </widget>
+          </item>
+         </layout>
+        </widget>
+       </item>
+       <item row="3" column="2">
+        <widget class="QGroupBox" name="TX_audio_source_group_box">
+         <property name="toolTip">
+          <string>Some radios can select the audio input using a CAT command,
+this setting allows you to select which audio input will be used
+(if it is available then generally the Rear/Data option is best).</string>
+         </property>
+         <property name="title">
+          <string>Transmit Audio Source</string>
+         </property>
+         <layout class="QGridLayout" name="gridLayout_7">
+          <item row="0" column="0">
+           <widget class="QRadioButton" name="TX_source_data_radio_button">
+            <property name="text">
+             <string>Rear&/Data</string>
+            </property>
+            <attribute name="buttonGroup">
+             <string notr="true">TX_audio_source_button_group</string>
+            </attribute>
+           </widget>
+          </item>
+          <item row="0" column="1">
+           <widget class="QRadioButton" name="TX_source_mic_radio_button">
+            <property name="text">
+             <string>&Front/Mic</string>
+            </property>
+            <property name="checked">
+             <bool>true</bool>
+            </property>
+            <attribute name="buttonGroup">
+             <string notr="true">TX_audio_source_button_group</string>
+            </attribute>
+           </widget>
+          </item>
+         </layout>
+        </widget>
+       </item>
+       <item row="9" column="2">
+        <spacer name="verticalSpacer_2">
+         <property name="orientation">
+          <enum>Qt::Vertical</enum>
+         </property>
+         <property name="sizeHint" stdset="0">
+          <size>
+           <width>20</width>
+           <height>40</height>
+          </size>
+         </property>
+        </spacer>
+       </item>
+       <item row="2" column="2">
+        <widget class="Line" name="line_3">
+         <property name="orientation">
+          <enum>Qt::Horizontal</enum>
+         </property>
+        </widget>
+       </item>
+       <item row="11" column="2">
+        <spacer name="verticalSpacer_7">
+         <property name="orientation">
+          <enum>Qt::Vertical</enum>
+         </property>
+         <property name="sizeHint" stdset="0">
+          <size>
+           <width>20</width>
+           <height>40</height>
+          </size>
+         </property>
+        </spacer>
+       </item>
+       <item row="0" column="0" colspan="3">
+        <layout class="QHBoxLayout" name="horizontalLayout_7">
+         <item>
+          <widget class="QLabel" name="rig_label">
+           <property name="text">
+            <string>Rig:</string>
+           </property>
+           <property name="buddy">
+            <cstring>rig_combo_box</cstring>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QComboBox" name="rig_combo_box">
+           <property name="sizePolicy">
+            <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+             <horstretch>1</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QLabel" name="CAT_poll_interval_label">
+           <property name="text">
+            <string>Poll Interval:</string>
+           </property>
+           <property name="buddy">
+            <cstring>CAT_poll_interval_spin_box</cstring>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QSpinBox" name="CAT_poll_interval_spin_box">
+           <property name="suffix">
+            <string> s</string>
+           </property>
+           <property name="minimum">
+            <number>1</number>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </item>
+       <item row="4" column="2">
+        <widget class="Line" name="line_4">
+         <property name="orientation">
+          <enum>Qt::Horizontal</enum>
+         </property>
+        </widget>
+       </item>
+       <item row="10" column="2">
+        <layout class="QHBoxLayout" name="horizontalLayout_11">
+         <item>
+          <widget class="QPushButton" name="test_CAT_push_button">
+           <property name="toolTip">
+            <string>Attempt to connect to the radio with these settings.
+Another dialog will pop up where you can verify correct operation.</string>
+           </property>
+           <property name="text">
+            <string>Test CAT</string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <spacer name="horizontalSpacer_3">
+           <property name="orientation">
+            <enum>Qt::Horizontal</enum>
+           </property>
+           <property name="sizeType">
+            <enum>QSizePolicy::Preferred</enum>
+           </property>
+           <property name="sizeHint" stdset="0">
+            <size>
+             <width>40</width>
+             <height>20</height>
+            </size>
+           </property>
+          </spacer>
+         </item>
+         <item>
+          <widget class="QPushButton" name="test_PTT_push_button">
+           <property name="toolTip">
+            <string>Attempt to activate the transmitter.
+Click again to deactivate. Normally no power should be
+output since there is no audio being generated at this time.
+Check that any Tx indication on your radio and/or your
+radio interface behave as expected.</string>
+           </property>
+           <property name="styleSheet">
+            <string notr="true">QPushButton:checked {
+	background-color: red;
+	border-style	: outset;
+	border-width: 1px;
+	border-radius: 5px;
+	border-color: black;
+	min-width: 5em;
+	padding: 3px;
+}</string>
+           </property>
+           <property name="text">
+            <string>Test PTT</string>
+           </property>
+           <property name="checkable">
+            <bool>true</bool>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </item>
+       <item row="8" column="2">
+        <widget class="QGroupBox" name="split_operation_group_box">
+         <property name="title">
+          <string>Split Operation</string>
+         </property>
+         <layout class="QGridLayout" name="gridLayout_12">
+          <item row="0" column="0">
+           <widget class="QRadioButton" name="split_none_radio_button">
+            <property name="text">
+             <string>None</string>
+            </property>
+            <property name="checked">
+             <bool>true</bool>
+            </property>
+            <attribute name="buttonGroup">
+             <string notr="true">split_mode_button_group</string>
+            </attribute>
+           </widget>
+          </item>
+          <item row="0" column="1">
+           <widget class="QRadioButton" name="split_rig_radio_button">
+            <property name="text">
+             <string>Rig</string>
+            </property>
+            <attribute name="buttonGroup">
+             <string notr="true">split_mode_button_group</string>
+            </attribute>
+           </widget>
+          </item>
+          <item row="0" column="2">
+           <widget class="QRadioButton" name="split_emulate_radio_button">
+            <property name="text">
+             <string>Fake It</string>
+            </property>
+            <attribute name="buttonGroup">
+             <string notr="true">split_mode_button_group</string>
+            </attribute>
+           </widget>
+          </item>
+         </layout>
+        </widget>
+       </item>
+       <item row="12" column="0">
+        <spacer name="verticalSpacer_5">
+         <property name="orientation">
+          <enum>Qt::Vertical</enum>
+         </property>
+         <property name="sizeHint" stdset="0">
+          <size>
+           <width>20</width>
+           <height>40</height>
+          </size>
+         </property>
+        </spacer>
+       </item>
+      </layout>
+     </widget>
+     <widget class="QWidget" name="audio_tab">
+      <attribute name="title">
+       <string>A&udio</string>
+      </attribute>
+      <attribute name="toolTip">
+       <string>Audio interface settings</string>
+      </attribute>
+      <layout class="QGridLayout" name="gridLayout_5">
+       <item row="2" column="0">
+        <widget class="QGroupBox" name="save_path_group_box">
+         <property name="title">
+          <string>Save Directory</string>
+         </property>
+         <layout class="QHBoxLayout" name="horizontalLayout_5">
+          <item>
+           <widget class="QLabel" name="save_path_label">
+            <property name="text">
+             <string>Loc&ation:</string>
+            </property>
+            <property name="buddy">
+             <cstring>save_path_select_push_button</cstring>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QLabel" name="save_path_display_label">
+            <property name="sizePolicy">
+             <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+              <horstretch>1</horstretch>
+              <verstretch>0</verstretch>
+             </sizepolicy>
+            </property>
+            <property name="toolTip">
+             <string>Path to which .WAV files are saved.</string>
+            </property>
+            <property name="autoFillBackground">
+             <bool>false</bool>
+            </property>
+            <property name="styleSheet">
+             <string notr="true">background-color: rgb(255, 255, 255);</string>
+            </property>
+            <property name="text">
+             <string>TextLabel</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QPushButton" name="save_path_select_push_button">
+            <property name="toolTip">
+             <string>Click to select a different save directory for .WAV files.</string>
+            </property>
+            <property name="text">
+             <string>S&elect</string>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </widget>
+       </item>
+       <item row="0" column="0">
+        <widget class="QGroupBox" name="soundcard_group_box">
+         <property name="title">
+          <string>Soundcard</string>
+         </property>
+         <layout class="QGridLayout" name="gridLayout_6">
+          <item row="1" column="1">
+           <widget class="QComboBox" name="sound_output_combo_box">
+            <property name="sizePolicy">
+             <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+              <horstretch>1</horstretch>
+              <verstretch>0</verstretch>
+             </sizepolicy>
+            </property>
+            <property name="toolTip">
+             <string>Select the audio CODEC to use for transmitting.
+If this is your default device for system sounds then
+ensure that all system sounds are disabled otherwise
+you will broadcast any systems sounds generated during
+transmitting periods.</string>
+            </property>
+           </widget>
+          </item>
+          <item row="0" column="1">
+           <widget class="QComboBox" name="sound_input_combo_box">
+            <property name="sizePolicy">
+             <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+              <horstretch>1</horstretch>
+              <verstretch>0</verstretch>
+             </sizepolicy>
+            </property>
+            <property name="toolTip">
+             <string>Select the audio CODEC to use for receiving.</string>
+            </property>
+           </widget>
+          </item>
+          <item row="0" column="0">
+           <widget class="QLabel" name="sound_input_label">
+            <property name="text">
+             <string>&Input:</string>
+            </property>
+            <property name="buddy">
+             <cstring>sound_input_combo_box</cstring>
+            </property>
+           </widget>
+          </item>
+          <item row="0" column="2">
+           <widget class="QComboBox" name="sound_input_channel_combo_box">
+            <property name="toolTip">
+             <string>Select the channel to use for receiving.</string>
+            </property>
+            <item>
+             <property name="text">
+              <string>Mono</string>
+             </property>
+            </item>
+            <item>
+             <property name="text">
+              <string>Left</string>
+             </property>
+            </item>
+            <item>
+             <property name="text">
+              <string>Right</string>
+             </property>
+            </item>
+            <item>
+             <property name="text">
+              <string>Both</string>
+             </property>
+            </item>
+           </widget>
+          </item>
+          <item row="1" column="2">
+           <widget class="QComboBox" name="sound_output_channel_combo_box">
+            <property name="toolTip">
+             <string>Select the audio channel used for transmission.
+Unless you have multiple radios connected on different
+channels; then you will usually want to select mono or
+both here.</string>
+            </property>
+            <item>
+             <property name="text">
+              <string>Mono</string>
+             </property>
+            </item>
+            <item>
+             <property name="text">
+              <string>Left</string>
+             </property>
+            </item>
+            <item>
+             <property name="text">
+              <string>Right</string>
+             </property>
+            </item>
+            <item>
+             <property name="text">
+              <string>Both</string>
+             </property>
+            </item>
+           </widget>
+          </item>
+          <item row="1" column="0">
+           <widget class="QLabel" name="sound_output_label">
+            <property name="text">
+             <string>Ou&tput:</string>
+            </property>
+            <property name="buddy">
+             <cstring>sound_output_combo_box</cstring>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </widget>
+       </item>
+       <item row="3" column="0">
+        <widget class="QGroupBox" name="jt9w_group_box">
+         <property name="title">
+          <string>JT9W Settings</string>
+         </property>
+         <layout class="QGridLayout" name="gridLayout_9">
+          <item row="0" column="0">
+           <layout class="QFormLayout" name="formLayout_2">
+            <property name="fieldGrowthPolicy">
+             <enum>QFormLayout::ExpandingFieldsGrow</enum>
+            </property>
+            <item row="0" column="1">
+             <widget class="QComboBox" name="jt9w_bandwidth_mult_combo_box">
+              <item>
+               <property name="text">
+                <string>1</string>
+               </property>
+              </item>
+              <item>
+               <property name="text">
+                <string>2</string>
+               </property>
+              </item>
+              <item>
+               <property name="text">
+                <string>4</string>
+               </property>
+              </item>
+              <item>
+               <property name="text">
+                <string>8</string>
+               </property>
+              </item>
+              <item>
+               <property name="text">
+                <string>16</string>
+               </property>
+              </item>
+              <item>
+               <property name="text">
+                <string>32</string>
+               </property>
+              </item>
+              <item>
+               <property name="text">
+                <string>64</string>
+               </property>
+              </item>
+              <item>
+               <property name="text">
+                <string>128</string>
+               </property>
+              </item>
+             </widget>
+            </item>
+            <item row="0" column="0">
+             <widget class="QLabel" name="label_3">
+              <property name="text">
+               <string>Bandwidth Multiplier:</string>
+              </property>
+              <property name="buddy">
+               <cstring>jt9w_bandwidth_mult_combo_box</cstring>
+              </property>
+             </widget>
+            </item>
+           </layout>
+          </item>
+          <item row="0" column="2">
+           <layout class="QFormLayout" name="formLayout_3">
+            <property name="fieldGrowthPolicy">
+             <enum>QFormLayout::ExpandingFieldsGrow</enum>
+            </property>
+            <item row="1" column="0">
+             <widget class="QLabel" name="label_4">
+              <property name="text">
+               <string>DT Max:</string>
+              </property>
+              <property name="buddy">
+               <cstring>jt9w_max_dt_double_spin_box</cstring>
+              </property>
+             </widget>
+            </item>
+            <item row="0" column="0">
+             <widget class="QLabel" name="label_2">
+              <property name="text">
+               <string>DT Min:</string>
+              </property>
+              <property name="buddy">
+               <cstring>jt9w_min_dt_double_spin_box</cstring>
+              </property>
+             </widget>
+            </item>
+            <item row="0" column="1">
+             <widget class="QDoubleSpinBox" name="jt9w_min_dt_double_spin_box">
+              <property name="suffix">
+               <string> s</string>
+              </property>
+              <property name="decimals">
+               <number>1</number>
+              </property>
+              <property name="minimum">
+               <double>-2.500000000000000</double>
+              </property>
+              <property name="maximum">
+               <double>5.000000000000000</double>
+              </property>
+              <property name="singleStep">
+               <double>0.100000000000000</double>
+              </property>
+              <property name="value">
+               <double>-2.500000000000000</double>
+              </property>
+             </widget>
+            </item>
+            <item row="1" column="1">
+             <widget class="QDoubleSpinBox" name="jt9w_max_dt_double_spin_box">
+              <property name="suffix">
+               <string> s</string>
+              </property>
+              <property name="decimals">
+               <number>1</number>
+              </property>
+              <property name="minimum">
+               <double>-2.500000000000000</double>
+              </property>
+              <property name="maximum">
+               <double>5.000000000000000</double>
+              </property>
+              <property name="singleStep">
+               <double>0.100000000000000</double>
+              </property>
+              <property name="value">
+               <double>5.000000000000000</double>
+              </property>
+             </widget>
+            </item>
+           </layout>
+          </item>
+          <item row="0" column="1">
+           <spacer name="horizontalSpacer_5">
+            <property name="orientation">
+             <enum>Qt::Horizontal</enum>
+            </property>
+            <property name="sizeHint" stdset="0">
+             <size>
+              <width>40</width>
+              <height>20</height>
+             </size>
+            </property>
+           </spacer>
+          </item>
+         </layout>
+        </widget>
+       </item>
+       <item row="5" column="0">
+        <spacer name="verticalSpacer_3">
+         <property name="orientation">
+          <enum>Qt::Vertical</enum>
+         </property>
+         <property name="sizeHint" stdset="0">
+          <size>
+           <width>20</width>
+           <height>40</height>
+          </size>
+         </property>
+        </spacer>
+       </item>
+       <item row="1" column="0">
+        <widget class="Line" name="line_2">
+         <property name="orientation">
+          <enum>Qt::Horizontal</enum>
+         </property>
+        </widget>
+       </item>
+      </layout>
+     </widget>
+     <widget class="QWidget" name="tx_macros_tab">
+      <attribute name="title">
+       <string>Tx &Macros</string>
+      </attribute>
+      <attribute name="toolTip">
+       <string>Canned free text messages setup</string>
+      </attribute>
+      <layout class="QGridLayout" name="gridLayout">
+       <item row="0" column="1">
+        <widget class="QPushButton" name="add_macro_push_button">
+         <property name="text">
+          <string>&Add</string>
+         </property>
+        </widget>
+       </item>
+       <item row="0" column="0">
+        <widget class="QLineEdit" name="add_macro_line_edit">
+         <property name="maxLength">
+          <number>13</number>
+         </property>
+        </widget>
+       </item>
+       <item row="0" column="2">
+        <widget class="QPushButton" name="delete_macro_push_button">
+         <property name="text">
+          <string>&Delete</string>
+         </property>
+        </widget>
+       </item>
+       <item row="1" column="0" colspan="3">
+        <widget class="QListView" name="macros_list_view">
+         <property name="contextMenuPolicy">
+          <enum>Qt::ActionsContextMenu</enum>
+         </property>
+         <property name="toolTip">
+          <string>Drag and drop items to rearrange order
+Right click for item specific actions
+Click, SHIFT+Click and, CRTL+Click to select items</string>
+         </property>
+         <property name="styleSheet">
+          <string notr="true">QListView {
+    show-decoration-selected: 1; /* make the selection span the entire width of the view */
+}
+
+QListView::item:alternate {
+    background: #EEEEEE;
+}
+
+QListView::item:selected {
+    border: 1px solid #6a6ea9;
+}
+
+QListView::item:selected:!active {
+    background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
+                                stop: 0 #ABAFE5, stop: 1 #8588B2);
+}
+
+QListView::item:selected:active {
+    background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
+                                stop: 0 #6a6ea9, stop: 1 #888dd9);
+}
+
+QListView::item:hover {
+    background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
+                                stop: 0 #FAFBFE, stop: 1 #DCDEF1);
+}</string>
+         </property>
+         <property name="dragDropMode">
+          <enum>QAbstractItemView::InternalMove</enum>
+         </property>
+         <property name="defaultDropAction">
+          <enum>Qt::MoveAction</enum>
+         </property>
+         <property name="alternatingRowColors">
+          <bool>true</bool>
+         </property>
+         <property name="selectionMode">
+          <enum>QAbstractItemView::ExtendedSelection</enum>
+         </property>
+         <property name="uniformItemSizes">
+          <bool>true</bool>
+         </property>
+        </widget>
+       </item>
+      </layout>
+     </widget>
+     <widget class="QWidget" name="reporting_tab">
+      <attribute name="title">
+       <string>Reportin&g</string>
+      </attribute>
+      <attribute name="toolTip">
+       <string>Reporting and logging settings</string>
+      </attribute>
+      <layout class="QVBoxLayout" name="verticalLayout_5">
+       <item>
+        <widget class="QGroupBox" name="logging_group_box">
+         <property name="title">
+          <string>Logging</string>
+         </property>
+         <layout class="QVBoxLayout" name="verticalLayout_8">
+          <item>
+           <widget class="QCheckBox" name="prompt_to_log_check_box">
+            <property name="toolTip">
+             <string>The program will pop up a partially completed Log QSO dialog when you send a 73 or free text message.</string>
+            </property>
+            <property name="text">
+             <string>Promp&t me to log QSO</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QCheckBox" name="log_as_RTTY_check_box">
+            <property name="toolTip">
+             <string>Some logging programs will not accept JT-65 or JT9 as a recognized mode.</string>
+            </property>
+            <property name="text">
+             <string>Con&vert mode to RTTY</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QCheckBox" name="report_in_comments_check_box">
+            <property name="toolTip">
+             <string>Some logging programs will not accept the type of reports
+saved by this program.
+Check this option to save the sent and received reports in the
+comments field.</string>
+            </property>
+            <property name="text">
+             <string>d&B reports to comments</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QCheckBox" name="clear_DX_check_box">
+            <property name="toolTip">
+             <string>Check this option to force the clearing of the DX Call
+and DX Grid fields when a 73 or free text message is sent.</string>
+            </property>
+            <property name="text">
+             <string>Clear &DX call and grid after logging</string>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </widget>
+       </item>
+       <item>
+        <widget class="Line" name="line_8">
+         <property name="orientation">
+          <enum>Qt::Horizontal</enum>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <widget class="QGroupBox" name="network_group_box">
+         <property name="title">
+          <string>Network Services</string>
+         </property>
+         <layout class="QGridLayout" name="gridLayout_17">
+          <item row="0" column="0">
+           <widget class="QCheckBox" name="psk_reporter_check_box">
+            <property name="toolTip">
+             <string>The program can send your station details and all
+decoded signals as spots to the http://pskreporter.info web site.
+This is used for reverse beacon analysis which is very useful
+for assessing propagation and system performance.</string>
+            </property>
+            <property name="text">
+             <string>Enable &PSK Reporter Spotting</string>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </widget>
+       </item>
+       <item>
+        <widget class="QGroupBox" name="groupBox_4">
+         <property name="title">
+          <string>UDP Server</string>
+         </property>
+         <layout class="QGridLayout" name="gridLayout_16">
+          <item row="0" column="0">
+           <layout class="QFormLayout" name="formLayout_6">
+            <property name="fieldGrowthPolicy">
+             <enum>QFormLayout::AllNonFixedFieldsGrow</enum>
+            </property>
+            <item row="0" column="0">
+             <widget class="QLabel" name="udp_server_label">
+              <property name="text">
+               <string>UDP Server:</string>
+              </property>
+              <property name="buddy">
+               <cstring>udp_server_line_edit</cstring>
+              </property>
+             </widget>
+            </item>
+            <item row="0" column="1">
+             <widget class="QLineEdit" name="udp_server_line_edit">
+              <property name="sizePolicy">
+               <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+                <horstretch>0</horstretch>
+                <verstretch>0</verstretch>
+               </sizepolicy>
+              </property>
+              <property name="toolTip">
+               <string><html><head/><body><p>Optional hostname of network service to receive decodes.</p><p>Formats:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">hostname</li><li style=" margin-top:0px; margin-bottom:0p [...]
+              </property>
+              <property name="inputMethodHints">
+               <set>Qt::ImhDigitsOnly</set>
+              </property>
+             </widget>
+            </item>
+            <item row="1" column="0">
+             <widget class="QLabel" name="label_6">
+              <property name="text">
+               <string>UDP Server port number:</string>
+              </property>
+              <property name="buddy">
+               <cstring>udp_server_port_spin_box</cstring>
+              </property>
+             </widget>
+            </item>
+            <item row="1" column="1">
+             <widget class="QSpinBox" name="udp_server_port_spin_box">
+              <property name="toolTip">
+               <string><html><head/><body><p>Enter the service port number of the UDP server that WSJT-X should send updates to. If this is zero no updates will be broadcast.</p></body></html></string>
+              </property>
+              <property name="minimum">
+               <number>0</number>
+              </property>
+              <property name="maximum">
+               <number>65534</number>
+              </property>
+             </widget>
+            </item>
+           </layout>
+          </item>
+          <item row="0" column="1">
+           <layout class="QVBoxLayout" name="verticalLayout_11">
+            <item>
+             <widget class="QCheckBox" name="accept_udp_requests_check_box">
+              <property name="toolTip">
+               <string><html><head/><body><p>With this enabled WSJT-X will accept certain requests back from a UDP server that receives decode messages.</p></body></html></string>
+              </property>
+              <property name="text">
+               <string>Accept UDP requests</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QCheckBox" name="udpWindowToFront">
+              <property name="toolTip">
+               <string><html><head/><body><p>Indicate acceptance of an incoming UDP request. The effect of this option varies depending on the operating system and window manager, its intent is to notify the acceptance of an incoming UDP request even if this application is minimized or hidden.</p></body></html></string>
+              </property>
+              <property name="text">
+               <string>Notify on accepted UDP request</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QCheckBox" name="udpWindowRestore">
+              <property name="toolTip">
+               <string><html><head/><body><p>Restore the window from minimized if an UDP request is accepted.</p></body></html></string>
+              </property>
+              <property name="text">
+               <string>Accepted UDP request restores window</string>
+              </property>
+             </widget>
+            </item>
+           </layout>
+          </item>
+         </layout>
+        </widget>
+       </item>
+       <item>
+        <spacer name="verticalSpacer_4">
+         <property name="orientation">
+          <enum>Qt::Vertical</enum>
+         </property>
+         <property name="sizeHint" stdset="0">
+          <size>
+           <width>20</width>
+           <height>40</height>
+          </size>
+         </property>
+        </spacer>
+       </item>
+      </layout>
+     </widget>
+     <widget class="QWidget" name="frequencies_tab">
+      <attribute name="title">
+       <string>Frequencies</string>
+      </attribute>
+      <attribute name="toolTip">
+       <string>Default frequencies and band specific station details setup</string>
+      </attribute>
+      <layout class="QVBoxLayout" name="verticalLayout_10">
+       <item>
+        <widget class="QGroupBox" name="groupBox">
+         <property name="title">
+          <string>Working Frequencies</string>
+         </property>
+         <layout class="QHBoxLayout" name="horizontalLayout">
+          <item>
+           <widget class="QTableView" name="frequencies_table_view">
+            <property name="contextMenuPolicy">
+             <enum>Qt::ActionsContextMenu</enum>
+            </property>
+            <property name="toolTip">
+             <string>Right click to add or delete frequencies.</string>
+            </property>
+            <property name="dragDropMode">
+             <enum>QAbstractItemView::DragOnly</enum>
+            </property>
+            <property name="alternatingRowColors">
+             <bool>true</bool>
+            </property>
+            <property name="selectionBehavior">
+             <enum>QAbstractItemView::SelectRows</enum>
+            </property>
+            <property name="sortingEnabled">
+             <bool>true</bool>
+            </property>
+            <attribute name="horizontalHeaderStretchLastSection">
+             <bool>true</bool>
+            </attribute>
+            <attribute name="verticalHeaderVisible">
+             <bool>false</bool>
+            </attribute>
+           </widget>
+          </item>
+          <item>
+           <spacer name="horizontalSpacer_6">
+            <property name="orientation">
+             <enum>Qt::Horizontal</enum>
+            </property>
+            <property name="sizeHint" stdset="0">
+             <size>
+              <width>40</width>
+              <height>20</height>
+             </size>
+            </property>
+           </spacer>
+          </item>
+         </layout>
+        </widget>
+       </item>
+       <item>
+        <widget class="QGroupBox" name="groupBox_2">
+         <property name="title">
+          <string>Station Information</string>
+         </property>
+         <layout class="QHBoxLayout" name="horizontalLayout_3">
+          <item>
+           <widget class="QTableView" name="stations_table_view">
+            <property name="contextMenuPolicy">
+             <enum>Qt::ActionsContextMenu</enum>
+            </property>
+            <property name="acceptDrops">
+             <bool>true</bool>
+            </property>
+            <property name="toolTip">
+             <string>Items may be edited.
+Right click for insert and delete options.</string>
+            </property>
+            <property name="dragEnabled">
+             <bool>true</bool>
+            </property>
+            <property name="dragDropOverwriteMode">
+             <bool>true</bool>
+            </property>
+            <property name="dragDropMode">
+             <enum>QAbstractItemView::DragDrop</enum>
+            </property>
+            <property name="defaultDropAction">
+             <enum>Qt::MoveAction</enum>
+            </property>
+            <property name="alternatingRowColors">
+             <bool>true</bool>
+            </property>
+            <property name="selectionMode">
+             <enum>QAbstractItemView::ExtendedSelection</enum>
+            </property>
+            <property name="selectionBehavior">
+             <enum>QAbstractItemView::SelectRows</enum>
+            </property>
+            <property name="sortingEnabled">
+             <bool>true</bool>
+            </property>
+            <property name="wordWrap">
+             <bool>true</bool>
+            </property>
+            <attribute name="horizontalHeaderStretchLastSection">
+             <bool>true</bool>
+            </attribute>
+            <attribute name="verticalHeaderVisible">
+             <bool>false</bool>
+            </attribute>
+           </widget>
+          </item>
+         </layout>
+        </widget>
+       </item>
+      </layout>
+     </widget>
+     <widget class="QWidget" name="tab">
+      <attribute name="title">
+       <string>Colors</string>
+      </attribute>
+      <widget class="QWidget" name="layoutWidget">
+       <property name="geometry">
+        <rect>
+         <x>44</x>
+         <y>60</y>
+         <width>229</width>
+         <height>168</height>
+        </rect>
+       </property>
+       <layout class="QGridLayout" name="gridLayout_13">
+        <item row="0" column="0">
+         <widget class="QPushButton" name="pbCQmsg">
+          <property name="minimumSize">
+           <size>
+            <width>140</width>
+            <height>0</height>
+           </size>
+          </property>
+          <property name="text">
+           <string>CQ in message</string>
+          </property>
+         </widget>
+        </item>
+        <item row="0" column="1">
+         <widget class="QLabel" name="labCQ">
+          <property name="minimumSize">
+           <size>
+            <width>80</width>
+            <height>20</height>
+           </size>
+          </property>
+          <property name="styleSheet">
+           <string notr="true">QLabel{background-color: #66ff66}</string>
+          </property>
+          <property name="text">
+           <string>K1ABC</string>
+          </property>
+          <property name="alignment">
+           <set>Qt::AlignCenter</set>
+          </property>
+         </widget>
+        </item>
+        <item row="1" column="0">
+         <widget class="QPushButton" name="pbMyCall">
+          <property name="minimumSize">
+           <size>
+            <width>140</width>
+            <height>0</height>
+           </size>
+          </property>
+          <property name="text">
+           <string>My Call in message</string>
+          </property>
+         </widget>
+        </item>
+        <item row="1" column="1">
+         <widget class="QLabel" name="labMyCall">
+          <property name="minimumSize">
+           <size>
+            <width>80</width>
+            <height>20</height>
+           </size>
+          </property>
+          <property name="styleSheet">
+           <string notr="true">QLabel{background-color: #ff6666}</string>
+          </property>
+          <property name="text">
+           <string>K1ABC</string>
+          </property>
+          <property name="alignment">
+           <set>Qt::AlignCenter</set>
+          </property>
+         </widget>
+        </item>
+        <item row="2" column="0">
+         <widget class="QPushButton" name="pbTxMsg">
+          <property name="minimumSize">
+           <size>
+            <width>140</width>
+            <height>0</height>
+           </size>
+          </property>
+          <property name="text">
+           <string>Transmitted message</string>
+          </property>
+         </widget>
+        </item>
+        <item row="2" column="1">
+         <widget class="QLabel" name="labTx">
+          <property name="minimumSize">
+           <size>
+            <width>80</width>
+            <height>20</height>
+           </size>
+          </property>
+          <property name="styleSheet">
+           <string notr="true">QLabel{background-color: yellow}</string>
+          </property>
+          <property name="text">
+           <string>K1ABC</string>
+          </property>
+          <property name="alignment">
+           <set>Qt::AlignCenter</set>
+          </property>
+         </widget>
+        </item>
+        <item row="3" column="0">
+         <widget class="QPushButton" name="pbNewDXCC">
+          <property name="minimumSize">
+           <size>
+            <width>140</width>
+            <height>0</height>
+           </size>
+          </property>
+          <property name="text">
+           <string>New DXCC</string>
+          </property>
+         </widget>
+        </item>
+        <item row="3" column="1">
+         <widget class="QLabel" name="labDXCC">
+          <property name="minimumSize">
+           <size>
+            <width>80</width>
+            <height>20</height>
+           </size>
+          </property>
+          <property name="styleSheet">
+           <string notr="true">QLabel{background-color: #ff66ff}</string>
+          </property>
+          <property name="text">
+           <string>K1ABC</string>
+          </property>
+          <property name="alignment">
+           <set>Qt::AlignCenter</set>
+          </property>
+         </widget>
+        </item>
+        <item row="4" column="0">
+         <widget class="QPushButton" name="pbNewCall">
+          <property name="minimumSize">
+           <size>
+            <width>140</width>
+            <height>0</height>
+           </size>
+          </property>
+          <property name="text">
+           <string>New Call</string>
+          </property>
+         </widget>
+        </item>
+        <item row="4" column="1">
+         <widget class="QLabel" name="labNewCall">
+          <property name="minimumSize">
+           <size>
+            <width>80</width>
+            <height>20</height>
+           </size>
+          </property>
+          <property name="styleSheet">
+           <string notr="true">QLabel{background-color: #66ffff}</string>
+          </property>
+          <property name="text">
+           <string>K1ABC</string>
+          </property>
+          <property name="alignment">
+           <set>Qt::AlignCenter</set>
+          </property>
+         </widget>
+        </item>
+       </layout>
+      </widget>
+     </widget>
+    </widget>
+   </item>
+   <item>
+    <widget class="QDialogButtonBox" name="configuration_dialog_button_box">
+     <property name="toolTip">
+      <string>Discard or apply configuration changes including
+resetting the radio interface and applying any
+soundcard changes</string>
+     </property>
+     <property name="orientation">
+      <enum>Qt::Horizontal</enum>
+     </property>
+     <property name="standardButtons">
+      <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <tabstops>
+  <tabstop>configuration_tabs</tabstop>
+  <tabstop>callsign_line_edit</tabstop>
+  <tabstop>grid_line_edit</tabstop>
+  <tabstop>type_2_msg_gen_combo_box</tabstop>
+  <tabstop>insert_blank_check_box</tabstop>
+  <tabstop>miles_check_box</tabstop>
+  <tabstop>TX_messages_check_box</tabstop>
+  <tabstop>DXCC_check_box</tabstop>
+  <tabstop>font_push_button</tabstop>
+  <tabstop>decoded_text_font_push_button</tabstop>
+  <tabstop>monitor_off_check_box</tabstop>
+  <tabstop>monitor_last_used_check_box</tabstop>
+  <tabstop>quick_call_check_box</tabstop>
+  <tabstop>tx_QSY_check_box</tabstop>
+  <tabstop>disable_TX_on_73_check_box</tabstop>
+  <tabstop>watchdog_check_box</tabstop>
+  <tabstop>CW_id_after_73_check_box</tabstop>
+  <tabstop>CW_id_interval_spin_box</tabstop>
+  <tabstop>rig_combo_box</tabstop>
+  <tabstop>CAT_poll_interval_spin_box</tabstop>
+  <tabstop>CAT_port_combo_box</tabstop>
+  <tabstop>CAT_serial_baud_combo_box</tabstop>
+  <tabstop>CAT_7_bit_radio_button</tabstop>
+  <tabstop>CAT_8_bit_radio_button</tabstop>
+  <tabstop>CAT_one_stop_bit_radio_button</tabstop>
+  <tabstop>CAT_two_stop_bit_radio_button</tabstop>
+  <tabstop>CAT_handshake_none_radio_button</tabstop>
+  <tabstop>CAT_handshake_xon_radio_button</tabstop>
+  <tabstop>CAT_handshake_hardware_radio_button</tabstop>
+  <tabstop>CAT_DTR_check_box</tabstop>
+  <tabstop>CAT_RTS_check_box</tabstop>
+  <tabstop>PTT_VOX_radio_button</tabstop>
+  <tabstop>PTT_DTR_radio_button</tabstop>
+  <tabstop>PTT_CAT_radio_button</tabstop>
+  <tabstop>PTT_RTS_radio_button</tabstop>
+  <tabstop>PTT_port_combo_box</tabstop>
+  <tabstop>TX_source_data_radio_button</tabstop>
+  <tabstop>TX_source_mic_radio_button</tabstop>
+  <tabstop>mode_none_radio_button</tabstop>
+  <tabstop>mode_USB_radio_button</tabstop>
+  <tabstop>mode_data_radio_button</tabstop>
+  <tabstop>split_none_radio_button</tabstop>
+  <tabstop>split_rig_radio_button</tabstop>
+  <tabstop>split_emulate_radio_button</tabstop>
+  <tabstop>test_CAT_push_button</tabstop>
+  <tabstop>test_PTT_push_button</tabstop>
+  <tabstop>sound_input_combo_box</tabstop>
+  <tabstop>sound_input_channel_combo_box</tabstop>
+  <tabstop>sound_output_combo_box</tabstop>
+  <tabstop>sound_output_channel_combo_box</tabstop>
+  <tabstop>save_path_select_push_button</tabstop>
+  <tabstop>jt9w_bandwidth_mult_combo_box</tabstop>
+  <tabstop>jt9w_min_dt_double_spin_box</tabstop>
+  <tabstop>jt9w_max_dt_double_spin_box</tabstop>
+  <tabstop>add_macro_line_edit</tabstop>
+  <tabstop>add_macro_push_button</tabstop>
+  <tabstop>delete_macro_push_button</tabstop>
+  <tabstop>macros_list_view</tabstop>
+  <tabstop>prompt_to_log_check_box</tabstop>
+  <tabstop>log_as_RTTY_check_box</tabstop>
+  <tabstop>report_in_comments_check_box</tabstop>
+  <tabstop>clear_DX_check_box</tabstop>
+  <tabstop>psk_reporter_check_box</tabstop>
+  <tabstop>udp_server_line_edit</tabstop>
+  <tabstop>udp_server_port_spin_box</tabstop>
+  <tabstop>accept_udp_requests_check_box</tabstop>
+  <tabstop>udpWindowToFront</tabstop>
+  <tabstop>udpWindowRestore</tabstop>
+  <tabstop>frequencies_table_view</tabstop>
+  <tabstop>stations_table_view</tabstop>
+  <tabstop>pbCQmsg</tabstop>
+  <tabstop>pbMyCall</tabstop>
+  <tabstop>pbTxMsg</tabstop>
+  <tabstop>pbNewDXCC</tabstop>
+  <tabstop>pbNewCall</tabstop>
+ </tabstops>
+ <resources/>
+ <connections>
+  <connection>
+   <sender>configuration_dialog_button_box</sender>
+   <signal>accepted()</signal>
+   <receiver>configuration_dialog</receiver>
+   <slot>accept()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>245</x>
+     <y>605</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>157</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>configuration_dialog_button_box</sender>
+   <signal>rejected()</signal>
+   <receiver>configuration_dialog</receiver>
+   <slot>reject()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>313</x>
+     <y>605</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>286</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>add_macro_push_button</sender>
+   <signal>clicked()</signal>
+   <receiver>add_macro_line_edit</receiver>
+   <slot>setFocus()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>576</x>
+     <y>62</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>199</x>
+     <y>60</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>add_macro_line_edit</sender>
+   <signal>returnPressed()</signal>
+   <receiver>add_macro_push_button</receiver>
+   <slot>setFocus()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>199</x>
+     <y>60</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>576</x>
+     <y>62</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+ <buttongroups>
+  <buttongroup name="PTT_method_button_group"/>
+  <buttongroup name="TX_audio_source_button_group"/>
+  <buttongroup name="CAT_data_bits_button_group"/>
+  <buttongroup name="CAT_handshake_button_group"/>
+  <buttongroup name="CAT_stop_bits_button_group"/>
+  <buttongroup name="split_mode_button_group"/>
+  <buttongroup name="TX_mode_button_group"/>
+ </buttongroups>
+</ui>
diff --git a/DXLabSuiteCommanderTransceiver.cpp b/DXLabSuiteCommanderTransceiver.cpp
new file mode 100644
index 0000000..7ef7bb4
--- /dev/null
+++ b/DXLabSuiteCommanderTransceiver.cpp
@@ -0,0 +1,398 @@
+#include "DXLabSuiteCommanderTransceiver.hpp"
+
+#include <QTcpSocket>
+#include <QRegularExpression>
+#include <QLocale>
+
+#include "NetworkServerLookup.hpp"
+
+#include "moc_DXLabSuiteCommanderTransceiver.cpp"
+
+namespace
+{
+  char const * const commander_transceiver_name {"DX Lab Suite Commander"};
+
+  QString map_mode (Transceiver::MODE mode)
+  {
+    switch (mode)
+      {
+      case Transceiver::AM: return "AM";
+      case Transceiver::CW: return "CW";
+      case Transceiver::CW_R: return "CW-R";
+      case Transceiver::USB: return "USB";
+      case Transceiver::LSB: return "LSB";
+      case Transceiver::FSK: return "RTTY";
+      case Transceiver::FSK_R: return "RTTY-R";
+      case Transceiver::DIG_L: return "DATA-L";
+      case Transceiver::DIG_U: return "DATA-U";
+      case Transceiver::FM:
+      case Transceiver::DIG_FM:
+        return "FM";
+      default: break;
+      }
+    return "USB";
+  }
+}
+
+void DXLabSuiteCommanderTransceiver::register_transceivers (TransceiverFactory::Transceivers * registry, int id)
+{
+  (*registry)[commander_transceiver_name] = TransceiverFactory::Capabilities {id, TransceiverFactory::Capabilities::network, true};
+}
+
+DXLabSuiteCommanderTransceiver::DXLabSuiteCommanderTransceiver (std::unique_ptr<TransceiverBase> wrapped, QString const& address, bool use_for_ptt, int poll_interval)
+  : PollingTransceiver {poll_interval}
+  , wrapped_ {std::move (wrapped)}
+  , use_for_ptt_ {use_for_ptt}
+  , server_ {address}
+  , commander_ {nullptr}
+{
+}
+
+DXLabSuiteCommanderTransceiver::~DXLabSuiteCommanderTransceiver ()
+{
+}
+
+void DXLabSuiteCommanderTransceiver::do_start ()
+{
+  TRACE_CAT ("starting");
+  wrapped_->start ();
+
+  auto server_details = network_server_lookup (server_, 52002u, QHostAddress::LocalHost, QAbstractSocket::IPv4Protocol);
+
+  if (!commander_)
+    {
+      commander_ = new QTcpSocket {this}; // QObject takes ownership
+    }
+
+  commander_->connectToHost (std::get<0> (server_details), std::get<1> (server_details));
+  if (!commander_->waitForConnected ())
+    {
+      TRACE_CAT ("failed to connect" << commander_->errorString ());
+      throw error {tr ("Failed to connect to DX Lab Suite Commander\n") + commander_->errorString ()};
+    }
+      
+  poll ();
+}
+
+void DXLabSuiteCommanderTransceiver::do_stop ()
+{
+  if (commander_)
+    {
+      commander_->close ();
+      delete commander_, commander_ = nullptr;
+    }
+
+  wrapped_->stop ();
+  TRACE_CAT ("stopped");
+}
+
+void DXLabSuiteCommanderTransceiver::do_ptt (bool on)
+{
+  TRACE_CAT (on << state ());
+  if (use_for_ptt_)
+    {
+      simple_command (on  ? "<command:5>CmdTX<parameters:0>" : "<command:5>CmdRX<parameters:0>");
+    }
+  else
+    {
+      wrapped_->ptt (on);
+    }
+  update_PTT (on);
+}
+
+void DXLabSuiteCommanderTransceiver::do_frequency (Frequency f, MODE m)
+{
+  TRACE_CAT (f << state ());
+  auto f_string = frequency_to_string (f);
+  if (UNK != m)
+    {
+      auto m_string = map_mode (m);
+      auto params =  ("<xcvrfreq:%1>" + f_string + "<xcvrmode:%2>" + m_string + "<preservesplitanddual:1>Y").arg (f_string.size ()).arg (m_string.size ());
+      simple_command (("<command:14>CmdSetFreqMode<parameters:%1>" + params).arg (params.size ()));
+      update_mode (m);
+    }
+  else
+    {
+      auto params =  ("<xcvrfreq:%1>" + f_string).arg (f_string.size ());
+      simple_command (("<command:10>CmdSetFreq<parameters:%1>" + params).arg (params.size ()));
+    }
+  update_rx_frequency (f);
+}
+
+void DXLabSuiteCommanderTransceiver::do_tx_frequency (Frequency tx, bool /* rationalise_mode */)
+{
+  TRACE_CAT (tx << state ());
+  if (tx)
+    {
+      auto f_string = frequency_to_string (tx);
+      auto params = ("<xcvrfreq:%1>" + f_string + "<SuppressDual:1>Y").arg (f_string.size ());
+      simple_command (("<command:11>CmdQSXSplit<parameters:%1>" + params).arg (params.size ()));
+    }
+  else
+    {
+      simple_command ("<command:8>CmdSplit<parameters:8><1:3>off");
+    }
+  update_split (tx);
+  update_other_frequency (tx);
+}
+
+void DXLabSuiteCommanderTransceiver::do_mode (MODE m, bool /* rationalise */)
+{
+  TRACE_CAT (m << state ());
+  auto m_string = map_mode (m);
+  auto params =  ("<1:%1>" + m_string).arg (m_string.size ());
+  simple_command (("<command:10>CmdSetMode<parameters:%1>" + params).arg (params.size ()));
+  update_mode (m);
+}
+
+void DXLabSuiteCommanderTransceiver::poll ()
+{
+#if WSJT_TRACE_CAT && WSJT_TRACE_CAT_POLLS
+  bool quiet {false};
+#else
+  bool quiet {true};
+#endif
+
+  auto reply = command_with_reply ("<command:10>CmdGetFreq<parameters:0>", quiet);
+  if (0 == reply.indexOf ("<CmdFreq:"))
+    {
+      auto f = string_to_frequency (reply.mid (reply.indexOf ('>') + 1));
+      if (f)
+        {
+          if (!state ().ptt ()) // Commander is not reliable on frequency
+                                // polls while transmitting
+            {
+              update_rx_frequency (f);
+            }
+        }
+    }
+  else
+    {
+      TRACE_CAT_POLL ("get frequency unexpected response");
+      throw error {tr ("DX Lab Suite Commander didn't respond correctly polling frequency")};
+    }
+
+  if (state ().split ())
+    {
+      reply = command_with_reply ("<command:12>CmdGetTXFreq<parameters:0>", quiet);
+      if (0 == reply.indexOf ("<CmdTXFreq:"))
+        {
+          auto f = string_to_frequency (reply.mid (reply.indexOf ('>') + 1));
+          if (f)
+            {
+              if (!state ().ptt ()) // Commander is not reliable on frequency
+                                // polls while transmitting
+                {
+                  update_other_frequency (f);
+                }
+            }
+        }
+      else
+        {
+          TRACE_CAT_POLL ("get tx frequency unexpected response");
+          throw error {tr ("DX Lab Suite Commander didn't respond correctly polling TX frequency")};
+        }
+    }
+
+  reply = command_with_reply ("<command:12>CmdSendSplit<parameters:0>", quiet);
+  if (0 == reply.indexOf ("<CmdSplit:"))
+    {
+      auto split = reply.mid (reply.indexOf ('>') + 1);
+      if ("ON" == split)
+        {
+          update_split (true);
+        }
+      else if ("OFF" == split)
+        {
+          update_split (false);
+        }
+      else
+        {
+          TRACE_CAT_POLL ("unexpected split state" << split);
+          throw error {tr ("DX Lab Suite Commander sent an unrecognised split state: ") + split};
+        }
+    }
+  else
+    {
+      TRACE_CAT_POLL ("get split mode unexpected response");
+      throw error {tr ("DX Lab Suite Commander didn't respond correctly polling split status")};
+    }
+
+  reply = command_with_reply ("<command:11>CmdSendMode<parameters:0>", quiet);
+  if (0 == reply.indexOf ("<CmdMode:"))
+    {
+      auto mode = reply.mid (reply.indexOf ('>') + 1);
+      MODE m {UNK};
+      if ("AM" == mode)
+        {
+          m = AM;
+        }
+      else if ("CW" == mode)
+        {
+          m = CW;
+        }
+      else if ("CW-R" == mode)
+        {
+          m = CW_R;
+        }
+      else if ("FM" == mode || "WBFM" == mode)
+        {
+          m = FM;
+        }
+      else if ("LSB" == mode)
+        {
+          m = LSB;
+        }
+      else if ("USB" == mode)
+        {
+          m = USB;
+        }
+      else if ("RTTY" == mode)
+        {
+          m = FSK;
+        }
+      else if ("RTTY-R" == mode)
+        {
+          m = FSK_R;
+        }
+      else if ("PKT" == mode || "DATA-L" == mode || "Data-L" == mode || "DIGL" == mode)
+        {
+          m = DIG_L;
+        }
+      else if ("PKT-R" == mode || "DATA-U" == mode || "Data-U" == mode || "DIGU" == mode)
+        {
+          m = DIG_U;
+        }
+      else
+        {
+          TRACE_CAT_POLL ("unexpected mode name" << mode);
+          throw error {tr ("DX Lab Suite Commander sent an unrecognised mode: \"") + mode + '"'};
+        }
+      update_mode (m);
+    }
+  else
+    {
+      TRACE_CAT_POLL ("unexpected response");
+      throw error {tr ("DX Lab Suite Commander didn't respond correctly polling mode")};
+    }
+}
+
+void DXLabSuiteCommanderTransceiver::simple_command (QString const& cmd, bool no_debug)
+{
+  Q_ASSERT (commander_);
+
+  if (!no_debug)
+    {
+      TRACE_CAT (cmd);
+    }
+
+  if (!write_to_port (cmd))
+    {
+      TRACE_CAT ("failed:" << commander_->errorString ());
+      throw error {tr ("DX Lab Suite Commander send command failed\n") + commander_->errorString ()};
+    }
+}
+
+QString DXLabSuiteCommanderTransceiver::command_with_reply (QString const& cmd, bool no_debug)
+{
+  Q_ASSERT (commander_);
+
+  if (!write_to_port (cmd))
+    {
+      TRACE_CAT ("failed to send command:" << commander_->errorString ());
+      throw error {
+        tr ("DX Lab Suite Commander failed to send command \"%1\": %2\n")
+          .arg (cmd)
+          .arg (commander_->errorString ())
+          };
+    }
+
+  // waitForReadReady appears to be unreliable on Windows timing out
+  // when data is waiting so retry a few times
+  unsigned retries {5};
+  bool replied {false};
+  while (!replied && --retries)
+    {
+      replied = commander_->waitForReadyRead ();
+      if (!replied && commander_->error () != commander_->SocketTimeoutError)
+        {
+          TRACE_CAT (cmd << "failed to read reply:" << commander_->errorString ());
+          throw error {
+            tr ("DX Lab Suite Commander send command \"%1\" read reply failed: %2\n")
+              .arg (cmd)
+              .arg (commander_->errorString ())
+              };
+        }
+    }
+
+  if (!replied)
+    {
+      TRACE_CAT (cmd << "retries exhausted");
+      throw error {
+        tr ("DX Lab Suite Commander retries exhausted sending command \"%1\"")
+          .arg (cmd)
+          };
+    }
+
+  auto result = commander_->readAll ();
+  // qDebug () << "result: " << result;
+  // for (int i = 0; i < result.size (); ++i)
+  //   {
+  //     qDebug () << i << ":" << hex << int (result[i]);
+  //   }
+
+  if (!no_debug)
+    {
+      TRACE_CAT (cmd << "->" << result);
+    }
+
+  return result;                // converting raw UTF-8 bytes to QString
+}
+
+bool DXLabSuiteCommanderTransceiver::write_to_port (QString const& s)
+{
+  auto data = s.toLocal8Bit ();
+  auto to_send = data.constData ();
+  auto length = data.size ();
+
+  qint64 total_bytes_sent {0};
+  while (total_bytes_sent < length)
+    {
+      auto bytes_sent = commander_->write (to_send + total_bytes_sent, length - total_bytes_sent);
+      if (bytes_sent < 0 || !commander_->waitForBytesWritten ())
+        {
+          return false;
+        }
+
+      total_bytes_sent += bytes_sent;
+    }
+  return true;
+}
+
+QString DXLabSuiteCommanderTransceiver::frequency_to_string (Frequency f) const
+{
+  // number is localized and in kHz, avoid floating point translation
+  // errors by adding a small number (0.1Hz)
+  return QString {"%L1"}.arg (f / 1e3 + 1e-4, 10, 'f', 3);
+}
+
+auto DXLabSuiteCommanderTransceiver::string_to_frequency (QString s) const -> Frequency
+{
+  // temporary hack because Commander is returning invalid UTF-8 bytes
+  s.replace (QChar {QChar::ReplacementCharacter}, locale_.groupSeparator ());
+
+  // remove DP - relies on n.nnn kHz format so we can do ulonglong
+  // conversion to Hz
+  bool ok;
+
+  //  auto f = locale_.toDouble (s, &ok); // use when CmdSendFreq and
+                                      // CmdSendTxFreq reinstated
+
+  auto f = QLocale::c ().toDouble (s, &ok); // temporary fix
+
+  if (!ok)
+    {
+      throw error {tr ("DX Lab Suite Commander sent an unrecognized frequency")};
+    }
+  return (f + 1e-4) * 1e3;
+}
diff --git a/DXLabSuiteCommanderTransceiver.hpp b/DXLabSuiteCommanderTransceiver.hpp
new file mode 100644
index 0000000..c039857
--- /dev/null
+++ b/DXLabSuiteCommanderTransceiver.hpp
@@ -0,0 +1,57 @@
+#ifndef DX_LAB_SUITE_COMMANDER_TRANSCEIVER_HPP__
+#define DX_LAB_SUITE_COMMANDER_TRANSCEIVER_HPP__
+
+#include <memory>
+
+#include "TransceiverFactory.hpp"
+#include "PollingTransceiver.hpp"
+
+class QTcpSocket;
+class QByteArray;
+class QString;
+
+//
+// DX Lab Suite Commander Interface
+//
+// Implemented as a Transceiver decorator  because we may want the PTT
+// services of another Transceiver  type such as the HamlibTransceiver
+// which can  be enabled by wrapping  a HamlibTransceiver instantiated
+// as a "Hamlib Dummy" transceiver in the Transceiver factory method.
+//
+class DXLabSuiteCommanderTransceiver final
+  : public PollingTransceiver
+{
+  Q_OBJECT;                     // for translation context
+
+public:
+  static void register_transceivers (TransceiverFactory::Transceivers *, int id);
+
+  // takes ownership of wrapped Transceiver
+  explicit DXLabSuiteCommanderTransceiver (std::unique_ptr<TransceiverBase> wrapped, QString const& address, bool use_for_ptt, int poll_interval);
+  ~DXLabSuiteCommanderTransceiver ();
+
+protected:
+  void do_start () override;
+  void do_stop () override;
+  void do_frequency (Frequency, MODE) override;
+  void do_tx_frequency (Frequency, bool rationalise_mode) override;
+  void do_mode (MODE, bool rationalise) override;
+  void do_ptt (bool on) override;
+
+  void poll () override;
+
+private:
+  void simple_command (QString const&, bool no_debug = false);
+  QString command_with_reply (QString const&, bool no_debug = false);
+  bool write_to_port (QString const&);
+  QString frequency_to_string (Frequency) const;
+  Frequency string_to_frequency (QString) const;
+
+  std::unique_ptr<TransceiverBase> wrapped_;
+  bool use_for_ptt_;
+  QString server_;
+  QTcpSocket * commander_;
+  QLocale locale_;
+};
+
+#endif
diff --git a/Darwin/Info.plist.in b/Darwin/Info.plist.in
new file mode 100644
index 0000000..2ad1e0d
--- /dev/null
+++ b/Darwin/Info.plist.in
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleExecutable</key>
+	<string>@WSJTX_BUNDLE_NAME@</string>
+	<key>CFBundleDisplayName</key>
+	<string>@WSJTX_BUNDLE_NAME@</string>
+</dict>
+</plist>
diff --git a/Darwin/KVASD-installer/KVASD-installer.xcodeproj/project.pbxproj b/Darwin/KVASD-installer/KVASD-installer.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..a23b5ef
--- /dev/null
+++ b/Darwin/KVASD-installer/KVASD-installer.xcodeproj/project.pbxproj
@@ -0,0 +1,306 @@
+// !$*UTF8*$!
+{
+	archiveVersion = 1;
+	classes = {
+	};
+	objectVersion = 46;
+	objects = {
+
+/* Begin PBXBuildFile section */
+		A924153F1A2143F400B34EFA /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A924153E1A2143F400B34EFA /* Cocoa.framework */; };
+		A92415411A2143F400B34EFA /* AppleScriptObjC.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A92415401A2143F400B34EFA /* AppleScriptObjC.framework */; };
+		A924154D1A2143F400B34EFA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = A924154C1A2143F400B34EFA /* main.m */; };
+		A92415531A2143F400B34EFA /* WSJTAppDelegate.applescript in Sources */ = {isa = PBXBuildFile; fileRef = A92415521A2143F400B34EFA /* WSJTAppDelegate.applescript */; };
+		A92415581A2143F400B34EFA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A92415571A2143F400B34EFA /* Images.xcassets */; };
+		A99DD3EC1A267FF900951324 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = A99DD3EB1A267FF900951324 /* InfoPlist.strings */; };
+		A99DD3EE1A26801100951324 /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = A99DD3ED1A26801100951324 /* Credits.rtf */; };
+		A99DD3F01A26801D00951324 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = A99DD3EF1A26801D00951324 /* MainMenu.xib */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+		A924153B1A2143F400B34EFA /* KVASD-installer.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "KVASD-installer.app"; sourceTree = BUILT_PRODUCTS_DIR; };
+		A924153E1A2143F400B34EFA /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
+		A92415401A2143F400B34EFA /* AppleScriptObjC.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppleScriptObjC.framework; path = System/Library/Frameworks/AppleScriptObjC.framework; sourceTree = SDKROOT; };
+		A92415431A2143F400B34EFA /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; };
+		A92415441A2143F400B34EFA /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; };
+		A92415451A2143F400B34EFA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
+		A92415481A2143F400B34EFA /* KVASD-installer-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "KVASD-installer-Info.plist"; sourceTree = "<group>"; };
+		A924154C1A2143F400B34EFA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
+		A924154E1A2143F400B34EFA /* KVASD-installer-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "KVASD-installer-Prefix.pch"; sourceTree = "<group>"; };
+		A92415521A2143F400B34EFA /* WSJTAppDelegate.applescript */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.applescript; path = WSJTAppDelegate.applescript; sourceTree = "<group>"; };
+		A92415571A2143F400B34EFA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
+		A99DD3EB1A267FF900951324 /* InfoPlist.strings */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; path = InfoPlist.strings; sourceTree = "<group>"; };
+		A99DD3ED1A26801100951324 /* Credits.rtf */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.rtf; path = Credits.rtf; sourceTree = "<group>"; };
+		A99DD3EF1A26801D00951324 /* MainMenu.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MainMenu.xib; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+		A92415381A2143F400B34EFA /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				A92415411A2143F400B34EFA /* AppleScriptObjC.framework in Frameworks */,
+				A924153F1A2143F400B34EFA /* Cocoa.framework in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+		A92415321A2143F400B34EFA = {
+			isa = PBXGroup;
+			children = (
+				A92415461A2143F400B34EFA /* KVASD-installer */,
+				A924153D1A2143F400B34EFA /* Frameworks */,
+				A924153C1A2143F400B34EFA /* Products */,
+			);
+			sourceTree = "<group>";
+		};
+		A924153C1A2143F400B34EFA /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				A924153B1A2143F400B34EFA /* KVASD-installer.app */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
+		A924153D1A2143F400B34EFA /* Frameworks */ = {
+			isa = PBXGroup;
+			children = (
+				A924153E1A2143F400B34EFA /* Cocoa.framework */,
+				A92415401A2143F400B34EFA /* AppleScriptObjC.framework */,
+				A92415421A2143F400B34EFA /* Other Frameworks */,
+			);
+			name = Frameworks;
+			sourceTree = "<group>";
+		};
+		A92415421A2143F400B34EFA /* Other Frameworks */ = {
+			isa = PBXGroup;
+			children = (
+				A92415431A2143F400B34EFA /* AppKit.framework */,
+				A92415441A2143F400B34EFA /* CoreData.framework */,
+				A92415451A2143F400B34EFA /* Foundation.framework */,
+			);
+			name = "Other Frameworks";
+			sourceTree = "<group>";
+		};
+		A92415461A2143F400B34EFA /* KVASD-installer */ = {
+			isa = PBXGroup;
+			children = (
+				A92415521A2143F400B34EFA /* WSJTAppDelegate.applescript */,
+				A99DD3EF1A26801D00951324 /* MainMenu.xib */,
+				A92415571A2143F400B34EFA /* Images.xcassets */,
+				A92415471A2143F400B34EFA /* Supporting Files */,
+			);
+			path = "KVASD-installer";
+			sourceTree = "<group>";
+		};
+		A92415471A2143F400B34EFA /* Supporting Files */ = {
+			isa = PBXGroup;
+			children = (
+				A92415481A2143F400B34EFA /* KVASD-installer-Info.plist */,
+				A99DD3ED1A26801100951324 /* Credits.rtf */,
+				A99DD3EB1A267FF900951324 /* InfoPlist.strings */,
+				A924154C1A2143F400B34EFA /* main.m */,
+				A924154E1A2143F400B34EFA /* KVASD-installer-Prefix.pch */,
+			);
+			name = "Supporting Files";
+			sourceTree = "<group>";
+		};
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+		A924153A1A2143F400B34EFA /* KVASD-installer */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = A924155B1A2143F400B34EFA /* Build configuration list for PBXNativeTarget "KVASD-installer" */;
+			buildPhases = (
+				A92415371A2143F400B34EFA /* Sources */,
+				A92415381A2143F400B34EFA /* Frameworks */,
+				A92415391A2143F400B34EFA /* Resources */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = "KVASD-installer";
+			productName = "KVASD-installer";
+			productReference = A924153B1A2143F400B34EFA /* KVASD-installer.app */;
+			productType = "com.apple.product-type.application";
+		};
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+		A92415331A2143F400B34EFA /* Project object */ = {
+			isa = PBXProject;
+			attributes = {
+				CLASSPREFIX = WSJT;
+				LastUpgradeCheck = 0500;
+				ORGANIZATIONNAME = WSJT;
+			};
+			buildConfigurationList = A92415361A2143F400B34EFA /* Build configuration list for PBXProject "KVASD-installer" */;
+			compatibilityVersion = "Xcode 3.2";
+			developmentRegion = English;
+			hasScannedForEncodings = 0;
+			knownRegions = (
+				en,
+				Base,
+			);
+			mainGroup = A92415321A2143F400B34EFA;
+			productRefGroup = A924153C1A2143F400B34EFA /* Products */;
+			projectDirPath = "";
+			projectRoot = "";
+			targets = (
+				A924153A1A2143F400B34EFA /* KVASD-installer */,
+			);
+		};
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+		A92415391A2143F400B34EFA /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				A99DD3EC1A267FF900951324 /* InfoPlist.strings in Resources */,
+				A99DD3EE1A26801100951324 /* Credits.rtf in Resources */,
+				A92415581A2143F400B34EFA /* Images.xcassets in Resources */,
+				A99DD3F01A26801D00951324 /* MainMenu.xib in Resources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+		A92415371A2143F400B34EFA /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				A92415531A2143F400B34EFA /* WSJTAppDelegate.applescript in Sources */,
+				A924154D1A2143F400B34EFA /* main.m in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+		A92415591A2143F400B34EFA /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+				CLANG_CXX_LIBRARY = "libc++";
+				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				COPY_PHASE_STRIP = NO;
+				GCC_C_LANGUAGE_STANDARD = gnu99;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_ENABLE_OBJC_EXCEPTIONS = YES;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				GCC_PREPROCESSOR_DEFINITIONS = (
+					"DEBUG=1",
+					"$(inherited)",
+				);
+				GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				MACOSX_DEPLOYMENT_TARGET = 10.7;
+				ONLY_ACTIVE_ARCH = YES;
+				SDKROOT = macosx;
+			};
+			name = Debug;
+		};
+		A924155A1A2143F400B34EFA /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+				CLANG_CXX_LIBRARY = "libc++";
+				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				COPY_PHASE_STRIP = YES;
+				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+				ENABLE_NS_ASSERTIONS = NO;
+				GCC_C_LANGUAGE_STANDARD = gnu99;
+				GCC_ENABLE_OBJC_EXCEPTIONS = YES;
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				MACOSX_DEPLOYMENT_TARGET = 10.7;
+				ONLY_ACTIVE_ARCH = NO;
+				SDKROOT = macosx;
+			};
+			name = Release;
+		};
+		A924155C1A2143F400B34EFA /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+				COMBINE_HIDPI_IMAGES = YES;
+				GCC_PRECOMPILE_PREFIX_HEADER = YES;
+				GCC_PREFIX_HEADER = "KVASD-installer/KVASD-installer-Prefix.pch";
+				INFOPLIST_FILE = "KVASD-installer/KVASD-installer-Info.plist";
+				MACOSX_DEPLOYMENT_TARGET = 10.7;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				WRAPPER_EXTENSION = app;
+			};
+			name = Debug;
+		};
+		A924155D1A2143F400B34EFA /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+				COMBINE_HIDPI_IMAGES = YES;
+				GCC_PRECOMPILE_PREFIX_HEADER = YES;
+				GCC_PREFIX_HEADER = "KVASD-installer/KVASD-installer-Prefix.pch";
+				INFOPLIST_FILE = "KVASD-installer/KVASD-installer-Info.plist";
+				MACOSX_DEPLOYMENT_TARGET = 10.7;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				WRAPPER_EXTENSION = app;
+			};
+			name = Release;
+		};
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+		A92415361A2143F400B34EFA /* Build configuration list for PBXProject "KVASD-installer" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				A92415591A2143F400B34EFA /* Debug */,
+				A924155A1A2143F400B34EFA /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		A924155B1A2143F400B34EFA /* Build configuration list for PBXNativeTarget "KVASD-installer" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				A924155C1A2143F400B34EFA /* Debug */,
+				A924155D1A2143F400B34EFA /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+/* End XCConfigurationList section */
+	};
+	rootObject = A92415331A2143F400B34EFA /* Project object */;
+}
diff --git a/Darwin/KVASD-installer/KVASD-installer.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Darwin/KVASD-installer/KVASD-installer.xcodeproj/project.xcworkspace/contents.xcworkspacedata
new file mode 100644
index 0000000..90f9ef2
--- /dev/null
+++ b/Darwin/KVASD-installer/KVASD-installer.xcodeproj/project.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Workspace
+   version = "1.0">
+   <FileRef
+      location = "self:KVASD-installer.xcodeproj">
+   </FileRef>
+</Workspace>
diff --git a/Darwin/KVASD-installer/KVASD-installer/Credits.rtf b/Darwin/KVASD-installer/KVASD-installer/Credits.rtf
new file mode 100644
index 0000000..fb63b08
--- /dev/null
+++ b/Darwin/KVASD-installer/KVASD-installer/Credits.rtf
@@ -0,0 +1,30 @@
+{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf400
+{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\paperw11900\paperh16840\vieww9600\viewh8400\viewkind0
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720
+
+\f0\b\fs24 \cf0 Engineering:
+\b0 \
+	G4WJS - Bill Somerville\
+\
+
+\b Human Interface Design:
+\b0 \
+	G4WJS - Bill Somerville\
+\
+
+\b Testing:
+\b0 \
+	G4WJS - Bill Somerville\
+\
+
+\b Documentation:
+\b0 \
+	G4WJS - Bill Somerville\
+\
+
+\b With special thanks to:
+\b0 \
+	No one in particular.\
+}
\ No newline at end of file
diff --git a/Darwin/KVASD-installer/KVASD-installer/Images.xcassets/AppIcon.appiconset/Contents.json b/Darwin/KVASD-installer/KVASD-installer/Images.xcassets/AppIcon.appiconset/Contents.json
new file mode 100644
index 0000000..7cd4f8e
--- /dev/null
+++ b/Darwin/KVASD-installer/KVASD-installer/Images.xcassets/AppIcon.appiconset/Contents.json
@@ -0,0 +1,68 @@
+{
+  "images" : [
+    {
+      "size" : "16x16",
+      "idiom" : "mac",
+      "filename" : "icon_16x16.png",
+      "scale" : "1x"
+    },
+    {
+      "size" : "16x16",
+      "idiom" : "mac",
+      "filename" : "icon_16x16 at 2x.png",
+      "scale" : "2x"
+    },
+    {
+      "size" : "32x32",
+      "idiom" : "mac",
+      "filename" : "icon_32x32.png",
+      "scale" : "1x"
+    },
+    {
+      "size" : "32x32",
+      "idiom" : "mac",
+      "filename" : "icon_32x32 at 2x.png",
+      "scale" : "2x"
+    },
+    {
+      "size" : "128x128",
+      "idiom" : "mac",
+      "filename" : "icon_128x128.png",
+      "scale" : "1x"
+    },
+    {
+      "size" : "128x128",
+      "idiom" : "mac",
+      "filename" : "icon_128x128 at 2x.png",
+      "scale" : "2x"
+    },
+    {
+      "size" : "256x256",
+      "idiom" : "mac",
+      "filename" : "icon_256x256.png",
+      "scale" : "1x"
+    },
+    {
+      "size" : "256x256",
+      "idiom" : "mac",
+      "filename" : "icon_256x256 at 2x.png",
+      "scale" : "2x"
+    },
+    {
+      "size" : "512x512",
+      "idiom" : "mac",
+      "filename" : "icon_512x512.png",
+      "scale" : "1x"
+    },
+    {
+      "size" : "512x512",
+      "idiom" : "mac",
+      "filename" : "icon_512x512 at 2x.png",
+      "scale" : "2x"
+    }
+  ],
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}
\ No newline at end of file
diff --git a/Darwin/KVASD-installer/KVASD-installer/Images.xcassets/AppIcon.appiconset/icon_128x128.png b/Darwin/KVASD-installer/KVASD-installer/Images.xcassets/AppIcon.appiconset/icon_128x128.png
new file mode 100644
index 0000000..f27139e
Binary files /dev/null and b/Darwin/KVASD-installer/KVASD-installer/Images.xcassets/AppIcon.appiconset/icon_128x128.png differ
diff --git a/Darwin/KVASD-installer/KVASD-installer/Images.xcassets/AppIcon.appiconset/icon_128x128 at 2x.png b/Darwin/KVASD-installer/KVASD-installer/Images.xcassets/AppIcon.appiconset/icon_128x128 at 2x.png
new file mode 100644
index 0000000..eebc17e
Binary files /dev/null and b/Darwin/KVASD-installer/KVASD-installer/Images.xcassets/AppIcon.appiconset/icon_128x128 at 2x.png differ
diff --git a/Darwin/KVASD-installer/KVASD-installer/Images.xcassets/AppIcon.appiconset/icon_16x16.png b/Darwin/KVASD-installer/KVASD-installer/Images.xcassets/AppIcon.appiconset/icon_16x16.png
new file mode 100644
index 0000000..ecc5868
Binary files /dev/null and b/Darwin/KVASD-installer/KVASD-installer/Images.xcassets/AppIcon.appiconset/icon_16x16.png differ
diff --git a/Darwin/KVASD-installer/KVASD-installer/Images.xcassets/AppIcon.appiconset/icon_16x16 at 2x.png b/Darwin/KVASD-installer/KVASD-installer/Images.xcassets/AppIcon.appiconset/icon_16x16 at 2x.png
new file mode 100644
index 0000000..9a8ee28
Binary files /dev/null and b/Darwin/KVASD-installer/KVASD-installer/Images.xcassets/AppIcon.appiconset/icon_16x16 at 2x.png differ
diff --git a/Darwin/KVASD-installer/KVASD-installer/Images.xcassets/AppIcon.appiconset/icon_256x256.png b/Darwin/KVASD-installer/KVASD-installer/Images.xcassets/AppIcon.appiconset/icon_256x256.png
new file mode 100644
index 0000000..eebc17e
Binary files /dev/null and b/Darwin/KVASD-installer/KVASD-installer/Images.xcassets/AppIcon.appiconset/icon_256x256.png differ
diff --git a/Darwin/KVASD-installer/KVASD-installer/Images.xcassets/AppIcon.appiconset/icon_256x256 at 2x.png b/Darwin/KVASD-installer/KVASD-installer/Images.xcassets/AppIcon.appiconset/icon_256x256 at 2x.png
new file mode 100644
index 0000000..b4701fb
Binary files /dev/null and b/Darwin/KVASD-installer/KVASD-installer/Images.xcassets/AppIcon.appiconset/icon_256x256 at 2x.png differ
diff --git a/Darwin/KVASD-installer/KVASD-installer/Images.xcassets/AppIcon.appiconset/icon_32x32.png b/Darwin/KVASD-installer/KVASD-installer/Images.xcassets/AppIcon.appiconset/icon_32x32.png
new file mode 100644
index 0000000..9a8ee28
Binary files /dev/null and b/Darwin/KVASD-installer/KVASD-installer/Images.xcassets/AppIcon.appiconset/icon_32x32.png differ
diff --git a/Darwin/KVASD-installer/KVASD-installer/Images.xcassets/AppIcon.appiconset/icon_32x32 at 2x.png b/Darwin/KVASD-installer/KVASD-installer/Images.xcassets/AppIcon.appiconset/icon_32x32 at 2x.png
new file mode 100644
index 0000000..88b285e
Binary files /dev/null and b/Darwin/KVASD-installer/KVASD-installer/Images.xcassets/AppIcon.appiconset/icon_32x32 at 2x.png differ
diff --git a/Darwin/KVASD-installer/KVASD-installer/Images.xcassets/AppIcon.appiconset/icon_512x512.png b/Darwin/KVASD-installer/KVASD-installer/Images.xcassets/AppIcon.appiconset/icon_512x512.png
new file mode 100644
index 0000000..b4701fb
Binary files /dev/null and b/Darwin/KVASD-installer/KVASD-installer/Images.xcassets/AppIcon.appiconset/icon_512x512.png differ
diff --git a/Darwin/KVASD-installer/KVASD-installer/Images.xcassets/AppIcon.appiconset/icon_512x512 at 2x.png b/Darwin/KVASD-installer/KVASD-installer/Images.xcassets/AppIcon.appiconset/icon_512x512 at 2x.png
new file mode 100644
index 0000000..9dd961d
Binary files /dev/null and b/Darwin/KVASD-installer/KVASD-installer/Images.xcassets/AppIcon.appiconset/icon_512x512 at 2x.png differ
diff --git a/Darwin/KVASD-installer/KVASD-installer/InfoPlist.strings b/Darwin/KVASD-installer/KVASD-installer/InfoPlist.strings
new file mode 100644
index 0000000..477b28f
--- /dev/null
+++ b/Darwin/KVASD-installer/KVASD-installer/InfoPlist.strings
@@ -0,0 +1,2 @@
+/* Localized versions of Info.plist keys */
+
diff --git a/Darwin/KVASD-installer/KVASD-installer/KVASD-installer-Info.plist b/Darwin/KVASD-installer/KVASD-installer/KVASD-installer-Info.plist
new file mode 100644
index 0000000..fd76b1a
--- /dev/null
+++ b/Darwin/KVASD-installer/KVASD-installer/KVASD-installer-Info.plist
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>en</string>
+	<key>CFBundleDocumentTypes</key>
+	<array>
+		<dict>
+			<key>CFBundleTypeRole</key>
+			<string>Viewer</string>
+			<key>LSItemContentTypes</key>
+			<array>
+				<string>com.apple.application-bundle</string>
+			</array>
+		</dict>
+	</array>
+	<key>CFBundleExecutable</key>
+	<string>${EXECUTABLE_NAME}</string>
+	<key>CFBundleIconFile</key>
+	<string></string>
+	<key>CFBundleIdentifier</key>
+	<string>org.k1jt.${PRODUCT_NAME:rfc1034identifier}</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundleName</key>
+	<string>${PRODUCT_NAME}</string>
+	<key>CFBundlePackageType</key>
+	<string>APPL</string>
+	<key>CFBundleShortVersionString</key>
+	<string>1.0</string>
+	<key>CFBundleSignature</key>
+	<string>????</string>
+	<key>CFBundleVersion</key>
+	<string>1</string>
+	<key>LSApplicationCategoryType</key>
+	<string>public.app-category.utilities</string>
+	<key>LSMinimumSystemVersion</key>
+	<string>${MACOSX_DEPLOYMENT_TARGET}</string>
+	<key>NSHumanReadableCopyright</key>
+	<string>Created by Bill Somerville (G4WJS) on 12/11/2014.
+
+ The author of this work hereby waives all claim of copyright (economic and moral)
+in this work and immediately places it in the public domain; it may be used, distorted
+or destroyed in any manner whatsoever without further attribution or notice to the creator.</string>
+	<key>NSMainNibFile</key>
+	<string>MainMenu</string>
+	<key>NSPrincipalClass</key>
+	<string>NSApplication</string>
+</dict>
+</plist>
diff --git a/Darwin/KVASD-installer/KVASD-installer/KVASD-installer-Prefix.pch b/Darwin/KVASD-installer/KVASD-installer/KVASD-installer-Prefix.pch
new file mode 100644
index 0000000..35d7640
--- /dev/null
+++ b/Darwin/KVASD-installer/KVASD-installer/KVASD-installer-Prefix.pch
@@ -0,0 +1,9 @@
+//
+//  Prefix header
+//
+//  The contents of this file are implicitly included at the beginning of every source file.
+//
+
+#ifdef __OBJC__
+    #import <Cocoa/Cocoa.h>
+#endif
diff --git a/Darwin/KVASD-installer/KVASD-installer/MainMenu.xib b/Darwin/KVASD-installer/KVASD-installer/MainMenu.xib
new file mode 100644
index 0000000..7b643ac
--- /dev/null
+++ b/Darwin/KVASD-installer/KVASD-installer/MainMenu.xib
@@ -0,0 +1,290 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="4514" systemVersion="12F45" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
+    <dependencies>
+        <deployment version="1070" defaultVersion="1070" identifier="macosx"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="4514"/>
+    </dependencies>
+    <objects>
+        <customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
+            <connections>
+                <outlet property="delegate" destination="494" id="495"/>
+            </connections>
+        </customObject>
+        <customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
+        <customObject id="-3" userLabel="Application">
+            <connections>
+                <outlet property="delegate" destination="494" id="B9w-iE-h6m"/>
+            </connections>
+        </customObject>
+        <menu title="AMainMenu" systemMenu="main" id="29" userLabel="MainMenu">
+            <items>
+                <menuItem title="KVASD-installer" id="56">
+                    <menu key="submenu" title="KVASD-installer" systemMenu="apple" id="57">
+                        <items>
+                            <menuItem title="About KVASD-installer" id="58">
+                                <modifierMask key="keyEquivalentModifierMask"/>
+                                <connections>
+                                    <action selector="doAbout:" target="494" id="u46-Dy-iCH"/>
+                                </connections>
+                            </menuItem>
+                            <menuItem isSeparatorItem="YES" id="236">
+                                <modifierMask key="keyEquivalentModifierMask" command="YES"/>
+                            </menuItem>
+                            <menuItem title="Preferences…" keyEquivalent="," id="129" userLabel="121"/>
+                            <menuItem isSeparatorItem="YES" id="143">
+                                <modifierMask key="keyEquivalentModifierMask" command="YES"/>
+                            </menuItem>
+                            <menuItem title="Services" id="131">
+                                <menu key="submenu" title="Services" systemMenu="services" id="130"/>
+                            </menuItem>
+                            <menuItem isSeparatorItem="YES" id="144">
+                                <modifierMask key="keyEquivalentModifierMask" command="YES"/>
+                            </menuItem>
+                            <menuItem title="Hide KVASD-installer" keyEquivalent="h" id="134">
+                                <connections>
+                                    <action selector="hide:" target="-1" id="367"/>
+                                </connections>
+                            </menuItem>
+                            <menuItem title="Hide Others" keyEquivalent="h" id="145">
+                                <modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
+                                <connections>
+                                    <action selector="hideOtherApplications:" target="-1" id="368"/>
+                                </connections>
+                            </menuItem>
+                            <menuItem title="Show All" id="150">
+                                <connections>
+                                    <action selector="unhideAllApplications:" target="-1" id="370"/>
+                                </connections>
+                            </menuItem>
+                            <menuItem isSeparatorItem="YES" id="149">
+                                <modifierMask key="keyEquivalentModifierMask" command="YES"/>
+                            </menuItem>
+                            <menuItem title="Quit KVASD-installer" keyEquivalent="q" id="136" userLabel="1111">
+                                <connections>
+                                    <action selector="performClose:" target="371" id="cEn-Uc-6XC"/>
+                                </connections>
+                            </menuItem>
+                        </items>
+                    </menu>
+                </menuItem>
+                <menuItem title="Window" id="19">
+                    <menu key="submenu" title="Window" systemMenu="window" id="24">
+                        <items>
+                            <menuItem title="Minimize" keyEquivalent="m" id="23">
+                                <connections>
+                                    <action selector="performMiniaturize:" target="-1" id="37"/>
+                                </connections>
+                            </menuItem>
+                            <menuItem title="Zoom" id="239">
+                                <connections>
+                                    <action selector="performZoom:" target="-1" id="240"/>
+                                </connections>
+                            </menuItem>
+                            <menuItem isSeparatorItem="YES" id="92">
+                                <modifierMask key="keyEquivalentModifierMask" command="YES"/>
+                            </menuItem>
+                            <menuItem title="Bring All to Front" id="5">
+                                <connections>
+                                    <action selector="arrangeInFront:" target="-1" id="39"/>
+                                </connections>
+                            </menuItem>
+                        </items>
+                    </menu>
+                </menuItem>
+                <menuItem title="Help" id="490">
+                    <modifierMask key="keyEquivalentModifierMask"/>
+                    <menu key="submenu" title="Help" systemMenu="help" id="491">
+                        <items>
+                            <menuItem title="KVASD-installer Help" keyEquivalent="?" id="492">
+                                <connections>
+                                    <action selector="showHelp:" target="-1" id="493"/>
+                                </connections>
+                            </menuItem>
+                        </items>
+                    </menu>
+                </menuItem>
+            </items>
+        </menu>
+        <window title="KVASD-installer" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" animationBehavior="default" id="371">
+            <windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
+            <windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
+            <rect key="contentRect" x="80" y="390" width="496" height="492"/>
+            <rect key="screenRect" x="0.0" y="0.0" width="1920" height="1058"/>
+            <value key="minSize" type="size" width="524" height="564"/>
+            <view key="contentView" id="372">
+                <rect key="frame" x="0.0" y="0.0" width="496" height="492"/>
+                <autoresizingMask key="autoresizingMask"/>
+                <subviews>
+                    <button toolTip="Invoke a file chooser dialog to pick a WSJT-X application bundle to install KVASD into." verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="zDT-OA-GKH">
+                        <rect key="frame" x="20" y="63" width="113" height="25"/>
+                        <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
+                        <buttonCell key="cell" type="squareTextured" title="Choose target ..." bezelStyle="texturedSquare" imagePosition="overlaps" alignment="center" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="wka-Od-w4K">
+                            <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
+                            <font key="font" metaFont="system"/>
+                        </buttonCell>
+                        <connections>
+                            <action selector="doChooseTarget:" target="494" id="T3v-Fi-ceL"/>
+                        </connections>
+                    </button>
+                    <button toolTip="Click to process all the WSJT-X application bundles you have selected." verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="WgE-a2-qYH">
+                        <rect key="frame" x="430" y="63" width="46" height="25"/>
+                        <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
+                        <buttonCell key="cell" type="squareTextured" title="Install" bezelStyle="texturedSquare" imagePosition="overlaps" alignment="center" enabled="NO" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="Wul-Wc-vif">
+                            <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
+                            <font key="font" metaFont="system"/>
+                        </buttonCell>
+                        <connections>
+                            <action selector="doInstall:" target="494" id="tMW-3E-gQh"/>
+                        </connections>
+                    </button>
+                    <progressIndicator maxValue="100" displayedWhenStopped="NO" indeterminate="YES" style="bar" translatesAutoresizingMaskIntoConstraints="NO" id="C3t-a8-lOf">
+                        <rect key="frame" x="20" y="157" width="456" height="20"/>
+                        <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
+                    </progressIndicator>
+                    <scrollView horizontalLineScroll="10" horizontalPageScroll="10" verticalLineScroll="10" verticalPageScroll="10" hasHorizontalScroller="NO" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="FDk-OM-v7f">
+                        <rect key="frame" x="20" y="184" width="456" height="288"/>
+                        <autoresizingMask key="autoresizingMask"/>
+                        <string key="toolTip">Please read the agreement and tick the "Agree" checkbox below if you accept the terms and wish to continue with the installation.</string>
+                        <clipView key="contentView" id="hfA-a7-tlo">
+                            <rect key="frame" x="1" y="1" width="439" height="286"/>
+                            <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                            <subviews>
+                                <textView importsGraphics="NO" findStyle="panel" continuousSpellChecking="YES" allowsUndo="YES" usesRuler="YES" usesFontPanel="YES" verticallyResizable="YES" allowsNonContiguousLayout="YES" quoteSubstitution="YES" dashSubstitution="YES" spellingCorrection="YES" smartInsertDelete="YES" id="7ov-Rl-J8r">
+                                    <rect key="frame" x="0.0" y="0.0" width="439" height="286"/>
+                                    <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                                    <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
+                                    <size key="minSize" width="439" height="286"/>
+                                    <size key="maxSize" width="648" height="10000000"/>
+                                    <color key="insertionPointColor" white="0.0" alpha="1" colorSpace="calibratedWhite"/>
+                                    <size key="minSize" width="439" height="286"/>
+                                    <size key="maxSize" width="648" height="10000000"/>
+                                </textView>
+                            </subviews>
+                            <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
+                        </clipView>
+                        <scroller key="horizontalScroller" hidden="YES" verticalHuggingPriority="750" doubleValue="1" horizontal="YES" id="U59-MZ-pYE">
+                            <rect key="frame" x="-100" y="-100" width="87" height="18"/>
+                            <autoresizingMask key="autoresizingMask"/>
+                        </scroller>
+                        <scroller key="verticalScroller" verticalHuggingPriority="750" horizontal="NO" id="yPp-8r-Jdr">
+                            <rect key="frame" x="440" y="1" width="15" height="286"/>
+                            <autoresizingMask key="autoresizingMask"/>
+                        </scroller>
+                    </scrollView>
+                    <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" translatesAutoresizingMaskIntoConstraints="NO" id="Ykk-0Z-lxG">
+                        <rect key="frame" x="17" y="20" width="462" height="37"/>
+                        <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
+                        <constraints>
+                            <constraint firstAttribute="height" constant="37" id="hQV-aJ-MXM"/>
+                        </constraints>
+                        <textFieldCell key="cell" sendsActionOnEndEditing="YES" alignment="center" title="Use "Choose target ..." to pick WSJT-X application bundles to install KVASD into" id="3OK-wt-WuN">
+                            <font key="font" metaFont="system"/>
+                            <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
+                            <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
+                        </textFieldCell>
+                    </textField>
+                    <box autoresizesSubviews="NO" title="License" borderType="line" translatesAutoresizingMaskIntoConstraints="NO" id="wa1-Gy-wEE">
+                        <rect key="frame" x="17" y="91" width="462" height="59"/>
+                        <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
+                        <view key="contentView">
+                            <rect key="frame" x="1" y="1" width="460" height="43"/>
+                            <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                            <subviews>
+                                <button verticalHuggingPriority="750" tag="-1" translatesAutoresizingMaskIntoConstraints="NO" id="zHE-FK-uha">
+                                    <rect key="frame" x="12" y="5" width="102" height="32"/>
+                                    <autoresizingMask key="autoresizingMask"/>
+                                    <constraints>
+                                        <constraint firstAttribute="width" constant="90" id="93n-sN-xbH"/>
+                                    </constraints>
+                                    <buttonCell key="cell" type="push" title="Save ..." bezelStyle="rounded" alignment="center" enabled="NO" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="qaP-zQ-Ead">
+                                        <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
+                                        <font key="font" metaFont="system"/>
+                                        <connections>
+                                            <action selector="doSave:" target="494" id="KPT-pj-YyW"/>
+                                        </connections>
+                                    </buttonCell>
+                                </button>
+                                <button verticalHuggingPriority="750" tag="-1" translatesAutoresizingMaskIntoConstraints="NO" id="ylZ-OO-wid">
+                                    <rect key="frame" x="179" y="5" width="102" height="32"/>
+                                    <autoresizingMask key="autoresizingMask"/>
+                                    <constraints>
+                                        <constraint firstAttribute="width" constant="90" id="x77-Gu-2d1"/>
+                                    </constraints>
+                                    <buttonCell key="cell" type="push" title="Print ..." bezelStyle="rounded" alignment="center" enabled="NO" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="2cB-RL-2Da">
+                                        <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
+                                        <font key="font" metaFont="system"/>
+                                    </buttonCell>
+                                    <connections>
+                                        <action selector="doPrint:" target="494" id="879-hA-tbm"/>
+                                    </connections>
+                                </button>
+                                <button tag="-1" translatesAutoresizingMaskIntoConstraints="NO" id="art-4p-gjI">
+                                    <rect key="frame" x="347" y="-1" width="102" height="47"/>
+                                    <autoresizingMask key="autoresizingMask"/>
+                                    <constraints>
+                                        <constraint firstAttribute="width" constant="98" id="tcI-KQ-cBc"/>
+                                    </constraints>
+                                    <buttonCell key="cell" type="check" title="Agree" bezelStyle="regularSquare" imagePosition="left" enabled="NO" inset="2" id="NP4-SZ-zup">
+                                        <behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
+                                        <font key="font" metaFont="system"/>
+                                        <connections>
+                                            <action selector="doAgree:" target="494" id="AEf-cK-aSu"/>
+                                        </connections>
+                                    </buttonCell>
+                                </button>
+                            </subviews>
+                        </view>
+                        <constraints>
+                            <constraint firstItem="art-4p-gjI" firstAttribute="top" secondItem="wa1-Gy-wEE" secondAttribute="top" constant="14" id="0zn-cU-8Qd"/>
+                            <constraint firstItem="ylZ-OO-wid" firstAttribute="centerY" secondItem="art-4p-gjI" secondAttribute="centerY" id="P4Z-tf-K7i"/>
+                            <constraint firstAttribute="trailing" secondItem="art-4p-gjI" secondAttribute="trailing" constant="11" id="PaV-Cy-yPe"/>
+                            <constraint firstItem="zHE-FK-uha" firstAttribute="top" secondItem="wa1-Gy-wEE" secondAttribute="top" constant="25" id="Vbl-9p-bwR"/>
+                            <constraint firstItem="zHE-FK-uha" firstAttribute="leading" secondItem="wa1-Gy-wEE" secondAttribute="leading" constant="16" id="gSc-ts-7Qh"/>
+                            <constraint firstItem="ylZ-OO-wid" firstAttribute="centerX" secondItem="wa1-Gy-wEE" secondAttribute="centerX" id="hzs-Tk-cqg"/>
+                            <constraint firstItem="ylZ-OO-wid" firstAttribute="baseline" secondItem="zHE-FK-uha" secondAttribute="baseline" id="jka-sT-Thn"/>
+                            <constraint firstAttribute="bottom" secondItem="art-4p-gjI" secondAttribute="bottom" constant="-2" id="oKe-JP-bfb"/>
+                        </constraints>
+                        <color key="borderColor" white="0.0" alpha="0.41999999999999998" colorSpace="calibratedWhite"/>
+                        <color key="fillColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
+                    </box>
+                </subviews>
+                <constraints>
+                    <constraint firstItem="C3t-a8-lOf" firstAttribute="trailing" secondItem="FDk-OM-v7f" secondAttribute="trailing" id="4DP-Kp-1q2"/>
+                    <constraint firstItem="zDT-OA-GKH" firstAttribute="top" secondItem="wa1-Gy-wEE" secondAttribute="bottom" constant="8" symbolic="YES" id="ML8-yC-89i"/>
+                    <constraint firstItem="FDk-OM-v7f" firstAttribute="leading" secondItem="372" secondAttribute="leading" constant="20" symbolic="YES" id="NMg-Ck-obh"/>
+                    <constraint firstItem="zDT-OA-GKH" firstAttribute="leading" secondItem="wa1-Gy-wEE" secondAttribute="leading" id="T51-Uf-1WE"/>
+                    <constraint firstItem="wa1-Gy-wEE" firstAttribute="leading" secondItem="C3t-a8-lOf" secondAttribute="leading" id="TGy-7g-zAJ"/>
+                    <constraint firstItem="Ykk-0Z-lxG" firstAttribute="leading" secondItem="zDT-OA-GKH" secondAttribute="leading" id="bbq-7t-f68"/>
+                    <constraint firstItem="C3t-a8-lOf" firstAttribute="trailing" secondItem="wa1-Gy-wEE" secondAttribute="trailing" id="d1F-PM-eaa"/>
+                    <constraint firstItem="FDk-OM-v7f" firstAttribute="top" secondItem="372" secondAttribute="top" constant="20" symbolic="YES" id="kJJ-dt-NRz"/>
+                    <constraint firstItem="C3t-a8-lOf" firstAttribute="leading" secondItem="FDk-OM-v7f" secondAttribute="leading" id="kgo-AY-mzZ"/>
+                    <constraint firstItem="Ykk-0Z-lxG" firstAttribute="top" secondItem="zDT-OA-GKH" secondAttribute="bottom" constant="8" symbolic="YES" id="lnw-0d-qNt"/>
+                    <constraint firstItem="zDT-OA-GKH" firstAttribute="baseline" secondItem="WgE-a2-qYH" secondAttribute="baseline" id="ohE-qi-Dfp"/>
+                    <constraint firstItem="Ykk-0Z-lxG" firstAttribute="trailing" secondItem="WgE-a2-qYH" secondAttribute="trailing" id="p2f-9z-tE5"/>
+                    <constraint firstItem="C3t-a8-lOf" firstAttribute="top" secondItem="FDk-OM-v7f" secondAttribute="bottom" constant="8" symbolic="YES" id="qZp-QK-6Gr"/>
+                    <constraint firstAttribute="trailing" secondItem="FDk-OM-v7f" secondAttribute="trailing" constant="20" symbolic="YES" id="rjX-vJ-uNw"/>
+                    <constraint firstItem="wa1-Gy-wEE" firstAttribute="top" secondItem="C3t-a8-lOf" secondAttribute="bottom" constant="8" symbolic="YES" id="rjt-GZ-jeN"/>
+                    <constraint firstAttribute="bottom" secondItem="Ykk-0Z-lxG" secondAttribute="bottom" constant="20" symbolic="YES" id="vBM-jI-CPn"/>
+                    <constraint firstItem="wa1-Gy-wEE" firstAttribute="trailing" secondItem="WgE-a2-qYH" secondAttribute="trailing" id="wYS-jM-6G3"/>
+                </constraints>
+            </view>
+            <connections>
+                <outlet property="delegate" destination="494" id="E9E-qr-Qke"/>
+            </connections>
+        </window>
+        <customObject id="494" customClass="WSJTAppDelegate">
+            <connections>
+                <outlet property="agreeCheckBox" destination="NP4-SZ-zup" id="BvB-Ac-MFu"/>
+                <outlet property="chooseTargetButton" destination="zDT-OA-GKH" id="q8b-d7-xok"/>
+                <outlet property="eulaTextView" destination="7ov-Rl-J8r" id="986-TU-OO8"/>
+                <outlet property="installButton" destination="WgE-a2-qYH" id="0yv-Eu-yHW"/>
+                <outlet property="licenceBox" destination="wa1-Gy-wEE" id="eR5-0y-iYi"/>
+                <outlet property="mainWindow" destination="371" id="JZA-eM-kJw"/>
+                <outlet property="printButton" destination="ylZ-OO-wid" id="Nf6-fU-NSK"/>
+                <outlet property="progressBar" destination="C3t-a8-lOf" id="ioI-hZ-ytR"/>
+                <outlet property="saveButton" destination="zHE-FK-uha" id="FMI-0f-Pat"/>
+            </connections>
+        </customObject>
+        <customObject id="420" customClass="NSFontManager"/>
+    </objects>
+</document>
\ No newline at end of file
diff --git a/Darwin/KVASD-installer/KVASD-installer/WSJTAppDelegate.applescript b/Darwin/KVASD-installer/KVASD-installer/WSJTAppDelegate.applescript
new file mode 100644
index 0000000..3b87e9a
--- /dev/null
+++ b/Darwin/KVASD-installer/KVASD-installer/WSJTAppDelegate.applescript
@@ -0,0 +1,357 @@
+--
+--  WSJTAppDelegate.applescript
+--  KVASD-installer
+--
+--    This script is a drag and drop target that expects a WSJT-X app bundle path.
+--    It can also be opened with a file list or by dropping a suitable WSJT-X app
+--    bundle onto it. Alternatively a target WSJT-X application bundle may be
+--    selected by clicking the "Choose target ..." button.
+--
+--    It fetches the KVASD EULA text and displays it in a dialog which the reader
+--    must at least scroll to the end before clicking the Agree button which then
+--    downloads the appropriate KVASD executable. The MD5 hash checksum is checked
+--    on the KVASD executable.
+--
+--    Once the EULA has been accepted the "Install" button is enabled to install
+--    the KVASD executable into the target WSJT-X application bundle(s) and the
+--    RPATHs are modified to reference the libgcc support libraries inside the
+--    WSJT-X application bundle.
+--
+--  Created by Bill Somerville (G4WJS) on 12/11/2014.
+--
+--  The author of this work hereby waives all claim of copyright (economic and moral)
+--  in this work and immediately places it in the public domain; it may be used, distorted
+--  or destroyed in any manner whatsoever without further attribution or notice to the creator.
+--
+
+-- curl wraps cURL to download files
+script curl
+    on download(|url|, fileName, destination)
+        set |file| to destination & fileName
+        try
+            do shell script "curl --fail --retry 5 --silent --show-error --output " & |file| & " " & |url| & fileName
+        on error errorString
+            error "An error occurred downloading:" & return & |url| & fileName & return & return & errorString
+        end try
+        return |file| as POSIX file
+    end download
+    
+    on downloadMD5(|url|, fileName)
+        set md5Ext to ".md5"
+        try
+            return do shell script "curl --fail --retry 5 --silent " & |url| & fileName & md5Ext ¬
+                & " | awk '{match($0,\"[[:xdigit:]]{32}\"); print substr($0,RSTART,RLENGTH)}'"
+        on error errorString
+            error "An error occurred downloading" & return & return & fileName & md5Ext & return & return & errorString
+        end try
+    end downloadMD5
+end script
+
+-- kvasd looks after fetching kvasd files from the web source
+script kvasd
+    property serverPath : "https://svn.code.sf.net/p/wsjt/wsjt/trunk/kvasd-binary/"
+    property targetName : "kvasd"
+    
+    on destination()
+        return system attribute "TMPDIR"
+    end destination
+    
+    on fetchEULA()
+        return curl's download(serverPath,targetName  & "_eula.txt",my destination())
+    end fetchEULA
+    
+    on fetchBinary()
+        set |url| to serverPath & do shell script "echo `uname -s`-`uname -m`" & "/"
+        set md5Sum to curl's downloadMD5(|url|,targetName)
+        set |file| to curl's download(|url|,targetName,my destination())
+        set md5Calc to do shell script "md5 " & (POSIX path of |file|) & " | cut -d' ' -f4"
+        if md5Calc ≠ md5Sum then
+            error "KVASD download corrupt MD5 hash check" & return & return ¬
+                    & " expected [" & md5Sum & "]" & return ¬
+                    & "   actual [" & md5Calc & "]" ¬
+                number 500
+        end if
+    end fetchBinary
+    
+    on saveLicense()
+        set dest to choose folder ¬
+            with prompt "Specify folder to save license to" ¬
+            default location (path to documents folder)
+        tell application "Finder" to ¬
+            duplicate (my destination() & targetName & "_eula.txt") as POSIX file to dest
+    end saveLicense
+    
+    on printLicense()
+        tell application "Finder" to ¬
+            print (my destination() & targetName & "_eula.txt") as POSIX file
+    end printLicense
+    
+    on cleanUp()
+        tell application "Finder"
+            if exists (my destination() & targetName & "_eula.txt") as POSIX file then
+                delete (my destination() & targetName & "_eula.txt") as POSIX file
+            end if
+            if exists (my destination() & targetName) as POSIX file then
+                delete (my destination() & targetName) as POSIX file
+            end if
+        end tell
+    end cleanUp
+end script
+
+script WSJTAppDelegate
+	property parent : class "NSObject"
+    
+    property mainWindow : missing value
+    property eulaTextView : missing value
+    property progressBar : missing value
+    property saveButton : missing value
+    property printButton : missing value
+    property agreeCheckBox : missing value
+    property chooseTargetButton : missing value
+    property installButton : missing value
+    
+    property bundlesToProcess : {}
+    
+    global defaultNotificationCentre
+    global licenceAgreed
+    
+    on split(theText,theDelimiters)
+        set oldDelimiters to AppleScript's text item delimiters
+        set AppleScript's text item delimiters to theDelimiters
+        set theResult to the text items of theText
+        set AppleScript's text item delimiters to oldDelimiters
+        return theResult
+    end split
+    
+    -- do the install
+    on process()
+        repeat with bundlePath in bundlesToProcess
+            try
+                set wsjtxBundle to current application's NSBundle's bundleWithPath_(bundlePath)
+                if wsjtxBundle = missing value or wsjtxBundle's bundleIdentifier() as text ≠ "org.k1jt.wsjtx" then
+                    error "Not an appropriate WSJT-X application bundle: " & return & return ¬
+                    & bundlePath as text number 501
+                end if
+                set installRoot to wsjtxBundle's bundlePath() as text
+                display dialog "Install KVASD into Aplication Bundle" & return & return ¬
+                    & installRoot ¬
+                    buttons {"Ok", "Skip"} default button {"Ok"}
+                if button returned of result = "Ok" then
+                    try
+                        set target to installRoot & "/Contents/MacOS/" & kvasd's targetName
+                        do shell script "cp " & kvasd's destination() & kvasd's targetName & space & target
+                        do shell script "chmod +x " & target
+                        display alert "KVASD installed into application bundle:" & return & return & installRoot ¬
+                            buttons {"Ok"} default button "Ok" ¬
+                            giving up after 5
+                    on error errorString
+                        error "Failed to move KVASD into application bundle:" & return & return & installRoot ¬
+                            & return & return & "Error: " & errorString
+                    end try
+                end if
+            on error errorString
+                display alert errorString as warning buttons {"Ok"} default button "Ok"
+            end try
+        end repeat
+    end process
+
+    --
+    -- NSApplicationDelegate Protocol
+    --
+    on applicationWillFinishLaunching_(aNotification)
+        try
+--            mainWindow's registerForDraggedTypes_({"public.file-url"})
+            
+            set defaultNotificationCentre to current application's NSNotificationCenter's defaultCenter()
+            set licenceAgreed to false
+            eulaTextView's setEditable_(false)
+            
+            script downloadEula
+                eulaTextView's setString_(read kvasd's fetchEULA())
+            end script
+            my doWithRetry(downloadEula)
+            saveButton's setEnabled_(true)
+            printButton's setEnabled_(true)
+        
+            -- add observers for view port changes on EULA text view
+            set boundsChangeNotice to current application's NSViewBoundsDidChangeNotification
+            set frameChangeNotice to current application's NSViewFrameDidChangeNotification
+            defaultNotificationCentre's addObserver_selector_name_object_(me,"viewChanged:",boundsChangeNotice,missing value)
+            defaultNotificationCentre's addObserver_selector_name_object_(me,"viewChanged:",frameChangeNotice,missing value)
+        on error errorString
+            abort(errorString)
+        end try
+    end applicationWillFinishLaunching_
+    
+    on applicationShouldTerminateAfterLastWindowClosed_(sender)
+        return true
+    end applicationShouldTerminateAfterLastWindowClosed_
+	
+	on applicationWillTerminate_(sender)
+        defaultNotificationCentre's removeObserver_(me)
+        kvasd's cleanUp()
+	end applicationWillTerminate_
+    
+    --
+    -- NSDraggingDestination (NSWindow Delgate) Protocol (Not working on 10.7)
+    --
+    
+    -- Accept Generic drag&drop sources
+--    on draggingEntered_(sender)
+--        return current application's NSDragOperationGeneric
+--    end draggingEntered_
+    
+    -- Process a drop on our window
+--    on performDragOperation_(sender)
+--        try
+--            set pb to sender's draggingPasteboard()
+--            if pb's types() as list contains current application's NSURLPboardType then
+--                set options to {NSPasteboardURLReadingContentsConformToTypesKey:{"com.apple.application-bundle"}}
+--                repeat with u in pb's readObjectsForClasses_options_({current application's |NSURL|},options)
+--                    copy u's |path| to end of bundlesToProcess
+--                end repeat
+--                if bundlesToProcess ≠ {} and licenceAgreed then
+--                    installButton's setEnabled_(true)
+--                end if
+--                return true
+--            end if
+--        on error errorString
+--            abort(errorString)
+--        end try
+--        return false
+--    end performDragOperation_
+    
+    --
+    -- UI handlers
+    --
+    
+    -- Save EULA
+    on doSave_(sender)
+        try
+            kvasd's saveLicense()
+        on error errorString number errorNumber
+            if errorNumber is equal to -128 then
+                -- just ignore Cancel
+            else
+                abort(errorString)
+            end if
+        end try
+    end doSave_
+    
+    -- Save EULA
+    on doPrint_(sender)
+        try
+            kvasd's printLicense()
+        on error errorString number errorNumber
+            if errorNumber is equal to -128 then
+                -- just ignore Cancel
+            else
+                abort(errorString)
+            end if
+        end try
+    end doPrint_
+    
+    -- Agree Button handler
+    on doAgree_(sender)
+        if agreeCheckBox's state() as boolean then
+            try
+                script downloadKvasd
+                    kvasd's fetchBinary()
+                end script
+                my doWithRetry(downloadKvasd)
+            on error errorString
+                abort(errorString)
+            end try
+            agreeCheckBox's setEnabled_(false)
+            set licenceAgreed to true
+            if bundlesToProcess ≠ {} then
+                installButton's setEnabled_(true)
+            end if
+        end if
+    end doAgree_
+
+    -- Choose target button handler
+    on doChooseTarget_(sender)
+        try
+            repeat with target in choose file ¬
+                    with prompt "Choose the WSJT-X application bundle you wish to install KVASD into" ¬
+                    of type "com.apple.application-bundle" ¬
+                    default location "/Applications" as POSIX file as alias ¬
+                    invisibles false ¬
+                    multiple selections allowed true
+                copy POSIX path of target to end of bundlesToProcess
+            end repeat
+            if bundlesToProcess ≠ {} and licenceAgreed then
+                installButton's setEnabled_(true)
+            end if
+        on error number -128
+            -- just ignore Cancel
+        end try
+    end doChooseTarget_
+
+    -- Install button handler
+    on doInstall_(sender)
+        try
+            process()
+            set bundlesToProcess to {}
+            installButton's setEnabled_(false)
+        on error errorString
+            abort(errorString)
+        end try
+    end doInstall_
+
+    -- handler called on eulaTextView scroll or view changes
+    -- enables agree/install button once the bottom is reached
+    on viewChanged_(aNotification)
+        try
+            set dr to eulaTextView's |bounds| as record
+            set vdr to eulaTextView's visibleRect as record
+            if height of |size| of dr - (y of origin of vdr + height of |size| of vdr) is less than or equal to 0 ¬
+                    and not licenceAgreed then
+                agreeCheckBox's setEnabled_(true)
+            end if
+        on error errorString
+            abort(errorString)
+        end try
+    end viewChanged
+
+    -- Do something with retries
+    on doWithRetry(action)
+        set done to false
+        repeat until done
+            try
+                my progressAction(action)
+                set done to true
+            on error errorString
+                set userCanceled to false
+                try
+                    set dialogResult to display alert errorString as warning ¬
+                        buttons {"Cancel", "Retry"} default button "Retry" cancel button "Cancel"
+                on error number -128
+                    set userCanceled to true
+                end try
+                if userCanceled then
+                    error "User canceled operation"
+                end if
+            end try
+        end repeat
+    end doWithRetry
+
+    -- execute around handler to display a progress bar during an action
+    on progressAction(action)
+        progressBar's startAnimation_(me)
+        tell action to run
+        progressBar's stopAnimation_(me)
+    end progressAction
+
+    -- Abort handler
+    on abort(errorString)
+        display alert errorString as critical buttons {"Ok"} default button "Ok"
+        quit
+    end abort
+
+    -- About menu item
+    on doAbout_(sender)
+        display alert "KVASD-installer v1.0"
+    end onAbout_
+end script
diff --git a/Darwin/KVASD-installer/KVASD-installer/main.m b/Darwin/KVASD-installer/KVASD-installer/main.m
new file mode 100644
index 0000000..ac15490
--- /dev/null
+++ b/Darwin/KVASD-installer/KVASD-installer/main.m
@@ -0,0 +1,17 @@
+//
+//  main.m
+//  KVASD-installer
+//
+//  Created by Bill Somerville (G4WJS) on 22/11/2014.
+//  Copyright (c) 2014 WSJT. All rights reserved.
+//
+
+#import <Cocoa/Cocoa.h>
+
+#import <AppleScriptObjC/AppleScriptObjC.h>
+
+int main(int argc, const char * argv[])
+{
+    [[NSBundle mainBundle] loadAppleScriptObjectiveCScripts];
+    return NSApplicationMain(argc, argv);
+}
diff --git a/Darwin/Mac-wsjtx-startup.sh b/Darwin/Mac-wsjtx-startup.sh
new file mode 100644
index 0000000..b393910
--- /dev/null
+++ b/Darwin/Mac-wsjtx-startup.sh
@@ -0,0 +1,16 @@
+#!/bin/sh
+WSJTX_BUNDLE="`echo "$0" | sed -e 's/\/Contents\/MacOS\/.*//'`"
+WSJTX_RESOURCES="$WSJTX_BUNDLE/Contents/Resources"
+WSJTX_TEMP="/tmp/wsjtx/$UID"
+
+echo "running $0"
+echo "WSJTX_BUNDLE: $WSJTX_BUNDLE"
+
+# Setup temporary runtime files
+rm -rf "$WSJTX_TEMP"
+
+export "DYLD_LIBRARY_PATH=$WSJTX_RESOURCES/lib"
+export "PATH=$WSJTX_RESOURCES/bin:$PATH"
+
+#export
+exec "$WSJTX_RESOURCES/bin/wsjtx"
\ No newline at end of file
diff --git a/Darwin/ReadMe.txt b/Darwin/ReadMe.txt
new file mode 100644
index 0000000..c389180
--- /dev/null
+++ b/Darwin/ReadMe.txt
@@ -0,0 +1,106 @@
+                    Notes on WSJT-X Installation for Mac OS X
+                    -----------------------------------------
+
+If you have already downloaded a previous version of WSJT-X then I suggest 
+you change the name in the Applications folder from WSJT-X to WSJT-X_previous 
+before proceeding.  
+
+If you have installed a previous version of WSJT-X before then there is no 
+need to change anything on your system so proceed to NEXT.  
+
+BEGIN:
+
+There are some system matters you must deal with first.  Open a Terminal window
+by going to Applications->Utilities and clicking on Terminal.
+
+Along with this ReadMe file there is a file:   sysctl.conf.   Drag this file to your Desktop.
+
+WSJT-X makes use of a block of memory which is shared between different parts of
+the code.  The normal allocation of shared memory on a Mac is insufficient and this 
+has to be increased.   You can check the current allocation on your Mac by typing:
+
+  sysctl -a | grep sysv.shm
+
+If your shmmax is already at least 33554432 (32 MB) then you can close the Terminal
+window and skip the next steps and go to (NEXT).
+  
+Now move this file into place for the system to use by typing: (Note this assumes that
+you really did drag this file to your Desktop as required earlier.)
+
+  sudo cp $HOME/Desktop/sysctl.conf /etc/
+  sudo chmod 664 /etc/sysctl.conf
+  sudo chown  root:wheel  /etc/sysctl.conf
+
+and then reboot your Mac.  This is necessary to install the changes.  After the
+reboot you should re-open the Terminal window as before and you can check that the
+change has been made by typing:
+
+  sysctl -a | grep sysv.shm
+
+If shmmax is not shown as 33554432 then contact me since WSJT-X will fail to load with
+an error message: "Unable to create shared memory segment".
+
+You are now finished with system changes.  You should make certain that NO error messages
+have been produced during these steps.   You can now close the Terminal window.  It will
+not be necessary to repeat this procedure again, even when you download an updated
+version of WSJT-X.
+
+NEXT:
+
+Drag the WSJT-X app to your preferred location, such as Applications.
+
+WSJT-X can utilise a closed source proprietary tool called KVASD to get the best 
+possible sensitivity with JT65A signals.  When used it increases the maximum sensitivity 
+by approximately 2dB.  Because WSJT-X is an Open Source application released under the
+GPL v3 license, the KVASD tool must be installed manually after WSJT-X installation.
+The install DMG includes an installer tool KVASD-installer that allows you to install 
+KVASD into your WSJT-X application.  When you run KVASD-installer you must have a 
+functioning Internet connection since it downloads KVASD during the installation.
+
+Run KVASD-installer and review the license terms then use the "Choose target ..." button
+to select the WSJT-X application you have just installed then; click "Install" to inject
+KVASD into the WSJT-X application.
+
+You need to configure your sound card.   Visit Applications > Utilities > Audio MIDI 
+Setup and select your sound card and then set Format to be "48000Hz 2ch-16bit" for 
+input and output.
+
+Now double-click on the WSJT-X app and two windows will appear.  Select Preferences 
+under the WSJT-X Menu and fill in various station details on the General panel.   
+I recommend checking the 4 boxes under the Display heading and the first 4 boxes under 
+the Behaviour heading.
+
+Next visit the Audio panel and select the Audio Codec you use to communicate between 
+WSJT-X and your rig.   There are so many audio interfaces available that it is not 
+possible to give detailed advice on selection.  If you have difficulties contact me.   
+Note the location of the Save Directory.  Decoded wave forms are located here.
+
+Look at the Reporting panel.  If you check the "Prompt me" box, a logging panel will appear 
+at the end of the QSO.  Two log files are provided in Library/Application Support/WSJT-X.
+These are a simple wsjtx.log file and wsjtx_log.adi which is formatted for use with 
+logging databases.    The "File" menu bar items include a button "Open log directory" 
+to open the log directory in Finder for you, ready for processing by any logging 
+application you use.
+
+Finally, visit the Radio panel.  WSJT-X is most effective when operated with CAT 
+control.  You will need to install the relevant Mac driver for your rig.   This must 
+be located in the device driver directory  /dev. You should install your driver 
+and then re-launch WSJT-X. Return to the the Radio panel in Preferences and in 
+the "Serial port" panel select your driver from the list that is presented.   If 
+for some reason your driver is not shown, then insert the full name 
+of your driver in the Serial Port panel.   Such as:  /dev/tty.PL2303-00002226 or 
+whatever driver you have.  The /dev/ prefix is mandatory.  Set the relevant 
+communication parameters as required by your transceiver and click "Test CAT" to
+check.
+
+WSJT-X needs the Mac clock to be accurate.  Visit System Preferences > Date & Time 
+and make sure that date and time are set automatically.  The drop-down menu will 
+normally offer you several time servers to choose from.
+
+On the Help menu, have a look at the new Online User's Guide for operational hints 
+and tips.
+
+Please email me if you have problems.
+
+--- John G4KLA     (g4kla at rmnjmn.demon.co.uk)
+
diff --git a/Darwin/developer read me.txt b/Darwin/developer read me.txt
new file mode 100644
index 0000000..2b54312
--- /dev/null
+++ b/Darwin/developer read me.txt	
@@ -0,0 +1,91 @@
+KVASD-installer
+===============
+This is a small AppleScriptObjbC Xcode project that is an application bundle GUI tool
+to install the KVASD tool into a WSJT-X application bundle. It fetches the KVASD EULA
+from the SourceForge web svn server and presents it to the user, the user may store
+license or print it. They must agree the license terms before the KVASD tool is also
+downloaded from the SourceForge web svn server. The user then can select the target
+WSJT-X application bundle for installation either via a file chooser dialog or simply
+by dragging the target WSJT-X application bundle onto the KVASD-installer window.
+Once selected the "Install" button starts the installation process. The installation
+copies the kvasd binary into the WSJT-X bundle and adjusts the dylib paths in it to
+point to the libgcc dylibs that are shipped inside the WSJT_X bundle.
+
+KVASD-installer is not built as part of the WSJT-X project build, instead it must be
+built within Xcode and deployed into the source tree at the location 'contrib/Darwin'
+as a bare application bundle which is then checked into source control. The WSJT-X 
+CMake build, when building a DragNDrop installer package for WSJT-X inserts the 
+KVASD-installer application bundle into the root of the package DMG ready to be used
+after installing the main WSJT-X application bundle.
+
+
+Changing the content of the DragNDrop DMG root folder.
+======================================================
+
+The files and links in this folder are populated by the WSJT-X CMake build script. There are install commands which are only run on Apple hosts, this is important because they will get installed at the install root on other platforms, which would be very bad on Linux for example since that is /usr normally!
+
+The symlink to /Applications, the background image (derived from "~/src/wsjtx/artwork/DragNDrop Background.svg") and, the custom .DS_Store file ("~/src/wsjtx_DMG.DS_Store") are all handled specifically by the CPack DragNDrop packager so you don't need to install those.
+
+
+
+Modifying the .DS_Store folder options for the DragNDrop DMG root folder.
+=========================================================================
+
+The DragNDrop installer is a generated a DMG file that has a custom .DS_Store file that defines the layout, background image and, folder view options of the DMG root folder.
+
+To modify this file, first you need to make a DragNDrop package then mount the DMG file, then modify the root .DS_Store file using Finder. Once you are happy with the results, you check into source control the modified .DS_Store file and then future package builds will use that file.
+
+The installer DMG is read only and shrunk to exactly the size of the contents, also the .DS_Store file is read only and the background image PNG file is hidden. You need to undo all of these things before changing the .DS_Store file. Don't forget to redo these things before checking in a new version of the custom .DS_Store file.
+
+The following recipe shows how to amend the content and layout of the DMG root folder:
+
+# convert the DMG to a R/W copy (substitute the DMG you have built)
+hdiutil convert wsjtx-1.4.0-rc1-Darwin.dmg -format UDRW -o rw.dmg
+
+# expand the R/W copy to make room for changes
+# first find the current number of sectors
+hdiutil resize -limits rw.dmg
+# the output looks like:
+#
+#  min 	 cur 	 max
+#109696	109696	33037872
+#
+# you need to increase the sector count to something a bit bigger than current
+#  e.g. in this case use 110000
+hdiutil resize -sectors 110000 rw.dmg
+
+# now you can mount the R/W DMG
+hdiutil attach rw.dmg
+
+# change the hidden attribute on the background PNG
+chflags nohidden /Volumes/wsjtx-1.4.0-rc1-Darwin/background.png
+
+# make the .DS_Store file writeable
+chmod 644 /Volumes/wsjtx-1.4.0-rc1-Darwin/.DS_Store
+
+# now you can change Finder view options, rearrange icons etc. Remember that you are
+# only changing the folder options, not the folder content as that is controlled by
+# the install steps in the project CMakeLists.txt if you are adding or removing a file
+# to the DMG root folder, you need to have changed the install steps before doing this
+# procedure so the content changes are reflected in the installer DMG you start with.
+
+# when you are happy with the layout etc. close the Finder window to ensure all
+# changes are saved.
+
+# set the background PNG as a hidden file
+chflags hidden /Volumes/wsjtx-1.4.0-rc1-Darwin/background.png
+
+# make the .DS_Store file read only
+chmod 444 /Volumes/wsjtx-1.4.0-rc1-Darwin/.DS_Store
+
+# update the custom .DS_Store file in the source repository (NOTE the file name)
+cp /Volumes/wsjtx-1.4.0-rc1-Darwin/.DS_Store ~/src/wsjtx/wsjtx_DMG.DS_Store
+
+# build a new package and try out the new installer to test your changes
+# if all is well commit the changes
+
+# dismount and eject the R/W DMG and discard it
+hdiutil detach /Volumes/wsjtx-1.4.0-rc1-Darwin
+rm rw.dmg
+
+# That's all Folks!
\ No newline at end of file
diff --git a/Darwin/postflight.sh.in b/Darwin/postflight.sh.in
new file mode 100644
index 0000000..f5fc297
--- /dev/null
+++ b/Darwin/postflight.sh.in
@@ -0,0 +1,3 @@
+#!/bin/bash
+"$2 at CMAKE_INSTALL_SUBDIR@/@WSJTX_BUNDLE_NAME at .app/Contents/MacOS/@WSJTX_BUNDLE_NAME@" --mac-install
+exit 0
diff --git a/Darwin/postupgrade.sh.in b/Darwin/postupgrade.sh.in
new file mode 100644
index 0000000..06bd986
--- /dev/null
+++ b/Darwin/postupgrade.sh.in
@@ -0,0 +1,2 @@
+#!/bin/bash
+exit 0
diff --git a/Darwin/sysctl.conf b/Darwin/sysctl.conf
new file mode 100644
index 0000000..50ce64c
--- /dev/null
+++ b/Darwin/sysctl.conf
@@ -0,0 +1,5 @@
+kern.sysv.shmmax=33554432
+kern.sysv.shmmin=1
+kern.sysv.shmmni=128
+kern.sysv.shmseg=32
+kern.sysv.shmall=8192
diff --git a/Darwin/wsjtx_DMG.DS_Store b/Darwin/wsjtx_DMG.DS_Store
new file mode 100644
index 0000000..55e7458
Binary files /dev/null and b/Darwin/wsjtx_DMG.DS_Store differ
diff --git a/Detector.cpp b/Detector.cpp
new file mode 100644
index 0000000..ef7a8ff
--- /dev/null
+++ b/Detector.cpp
@@ -0,0 +1,134 @@
+#include "Detector.hpp"
+#include <QDateTime>
+#include <QtAlgorithms>
+#include <QDebug>
+#include "commons.h"
+
+#include "moc_Detector.cpp"
+
+extern "C" {
+  void   fil4_(qint16*, qint32*, qint16*, qint32*);
+}
+
+Detector::Detector (unsigned frameRate, unsigned periodLengthInSeconds,
+                    unsigned framesPerSignal, unsigned downSampleFactor,
+                    QObject * parent)
+  : AudioDevice (parent)
+  , m_frameRate (frameRate)
+  , m_period (periodLengthInSeconds)
+  , m_downSampleFactor (downSampleFactor)
+  , m_framesPerSignal (framesPerSignal)
+  , m_starting (false)
+  , m_buffer ((downSampleFactor > 1) ?
+              new short [framesPerSignal * downSampleFactor] : 0)
+  , m_bufferPos (0)
+{
+  (void)m_frameRate;            // quell compiler warning
+  clear ();
+}
+
+bool Detector::reset ()
+{
+  clear ();
+  // don't call base call reset because it calls seek(0) which causes
+  // a warning
+  return isOpen ();
+}
+
+void Detector::clear ()
+{
+  // set index to roughly where we are in time (1ms resolution)
+  // qint64 now (QDateTime::currentMSecsSinceEpoch ());
+  // unsigned msInPeriod ((now % 86400000LL) % (m_period * 1000));
+  // jt9com_.kin = qMin ((msInPeriod * m_frameRate) / 1000, static_cast<unsigned> (sizeof (jt9com_.d2) / sizeof (jt9com_.d2[0])));
+  jt9com_.kin = 0;
+  m_bufferPos = 0;
+
+  // fill buffer with zeros (G4WJS commented out because it might cause decoder hangs)
+  // qFill (jt9com_.d2, jt9com_.d2 + sizeof (jt9com_.d2) / sizeof (jt9com_.d2[0]), 0);
+}
+
+qint64 Detector::writeData (char const * data, qint64 maxSize)
+{
+    // no torn frames
+    Q_ASSERT (!(maxSize % static_cast<qint64> (bytesPerFrame ())));
+    // these are in terms of input frames (not down sampled)
+    size_t framesAcceptable ((sizeof (jt9com_.d2) /
+                              sizeof (jt9com_.d2[0]) - jt9com_.kin) * m_downSampleFactor);
+    size_t framesAccepted (qMin (static_cast<size_t> (maxSize /
+                                                      bytesPerFrame ()), framesAcceptable));
+
+    if (framesAccepted < static_cast<size_t> (maxSize / bytesPerFrame ())) {
+      qDebug () << "dropped " << maxSize / bytesPerFrame () - framesAccepted
+                << " frames of data on the floor!";
+    }
+
+    for (unsigned remaining = framesAccepted; remaining; ) {
+      size_t numFramesProcessed (qMin (m_framesPerSignal *
+                                       m_downSampleFactor - m_bufferPos, remaining));
+
+      if(m_downSampleFactor > 1) {
+        store (&data[(framesAccepted - remaining) * bytesPerFrame ()],
+               numFramesProcessed, &m_buffer[m_bufferPos]);
+        m_bufferPos += numFramesProcessed;
+        if(m_bufferPos==m_framesPerSignal*m_downSampleFactor) {
+          qint32 framesToProcess (m_framesPerSignal * m_downSampleFactor);
+          qint32 framesAfterDownSample;
+          if(framesToProcess==13824 and jt9com_.kin>=0 and jt9com_.kin<1440000) {
+            fil4_(&m_buffer[0], &framesToProcess, &jt9com_.d2[jt9com_.kin],
+                  &framesAfterDownSample);
+            jt9com_.kin += framesAfterDownSample;
+          } else {
+            qDebug() << "framesToProcess = " << framesToProcess;
+            qDebug() << "jt9com_.kin     = " << jt9com_.kin;
+            qDebug() << "secondInPeriod  = " << secondInPeriod();
+          }
+          Q_EMIT framesWritten (jt9com_.kin);
+          m_bufferPos = 0;
+        }
+
+      } else {
+        store (&data[(framesAccepted - remaining) * bytesPerFrame ()],
+               numFramesProcessed, &jt9com_.d2[jt9com_.kin]);
+        m_bufferPos += numFramesProcessed;
+        jt9com_.kin += numFramesProcessed;
+        if (m_bufferPos == static_cast<unsigned> (m_framesPerSignal)) {
+          Q_EMIT framesWritten (jt9com_.kin);
+          m_bufferPos = 0;
+        }
+      }
+
+      if (!secondInPeriod ()) {
+        if (!m_starting) {
+          // next samples will be in new period so wrap around to
+          // start of buffer
+          //
+          // we don't bother calling reset () since we expect to fill
+          // the whole buffer and don't need to waste cycles zeroing
+          jt9com_.kin = 0;
+          m_bufferPos = 0;
+          m_starting = true;
+        }
+      } else if(m_starting) {
+        m_starting = false;
+      }
+      remaining -= numFramesProcessed;
+    }
+  // } else {
+  //   jt9com_.kin = 0;
+  //   m_bufferPos = 0;
+  // }
+
+  return maxSize;    // we drop any data past the end of the buffer on
+  // the floor until the next period starts
+}
+
+unsigned Detector::secondInPeriod () const
+{
+  // we take the time of the data as the following assuming no latency
+  // delivering it to us (not true but close enough for us)
+  qint64 now (QDateTime::currentMSecsSinceEpoch ());
+
+  unsigned secondInToday ((now % 86400000LL) / 1000);
+  return secondInToday % m_period;
+}
diff --git a/Detector.hpp b/Detector.hpp
new file mode 100644
index 0000000..355dff1
--- /dev/null
+++ b/Detector.hpp
@@ -0,0 +1,58 @@
+#ifndef DETECTOR_HPP__
+#define DETECTOR_HPP__
+
+#include "AudioDevice.hpp"
+
+#include <QScopedArrayPointer>
+
+//
+// output device that distributes data in predefined chunks via a signal
+//
+// the underlying device for this abstraction is just the buffer that
+// stores samples throughout a receiving period
+//
+class Detector : public AudioDevice
+{
+  Q_OBJECT;
+
+public:
+  //
+  // if the data buffer were not global storage and fixed size then we
+  // might want maximum size passed as constructor arguments
+  //
+  // we down sample by a factor of 4
+  //
+  // the framesPerSignal argument is the number after down sampling
+  //
+  Detector (unsigned frameRate, unsigned periodLengthInSeconds, unsigned framesPerSignal, unsigned downSampleFactor = 4u, QObject * parent = 0);
+
+  Q_SIGNAL void framesWritten (qint64) const;
+
+  bool reset () override;
+
+protected:
+  qint64 readData (char * /* data */, qint64 /* maxSize */)
+  {
+    return -1;			// we don't produce data
+  }
+
+  qint64 writeData (char const * data, qint64 maxSize);
+
+private:
+  void clear ();		// discard buffer contents
+  unsigned secondInPeriod () const;
+
+  unsigned m_frameRate;
+  unsigned m_period;
+  unsigned m_downSampleFactor;
+  qint32 m_framesPerSignal;	// after any down sampling
+  bool m_starting;
+  QScopedArrayPointer<short> m_buffer; // de-interleaved sample buffer
+  // big enough for all the
+  // samples for one increment of
+  // data (a signals worth) at
+  // the input sample rate
+  unsigned m_bufferPos;
+};
+
+#endif
diff --git a/EmulateSplitTransceiver.cpp b/EmulateSplitTransceiver.cpp
new file mode 100644
index 0000000..8b2b9ee
--- /dev/null
+++ b/EmulateSplitTransceiver.cpp
@@ -0,0 +1,116 @@
+#include "EmulateSplitTransceiver.hpp"
+
+EmulateSplitTransceiver::EmulateSplitTransceiver (std::unique_ptr<Transceiver> wrapped)
+  : wrapped_ {std::move (wrapped)}
+  , frequency_ {0, 0}
+  , pre_tx_frequency_ {0}
+  , tx_ {false}
+{
+  // Connect update signal of wrapped Transceiver object instance to ours.
+  connect (wrapped_.get (), &Transceiver::update, this, &EmulateSplitTransceiver::handle_update);
+
+  // Connect failure signal of wrapped Transceiver object to our
+  // parent failure signal.
+  connect (wrapped_.get (), &Transceiver::failure, this, &Transceiver::failure);
+}
+
+void EmulateSplitTransceiver::start () noexcept
+{
+  wrapped_->start ();
+  wrapped_->tx_frequency (0, false);
+}
+
+void EmulateSplitTransceiver::frequency (Frequency rx, MODE m) noexcept
+{
+#if WSJT_TRACE_CAT
+  qDebug () << "EmulateSplitTransceiver::frequency:" << rx << "mode:" << m;
+#endif
+
+  // Save frequency parameters.
+  frequency_[0] = rx;
+
+  // Set active frequency.
+  wrapped_->frequency (rx, m);
+}
+
+void EmulateSplitTransceiver::tx_frequency (Frequency tx, bool /* rationalise_mode */) noexcept
+{
+#if WSJT_TRACE_CAT
+  qDebug () << "EmulateSplitTransceiver::tx_frequency:" << tx;
+#endif
+
+  // Save frequency parameter.
+  frequency_[1] = tx;
+
+  // Set active frequency.
+  wrapped_->frequency (frequency_[(tx_ && frequency_[1]) ? 1 : 0]);
+}
+
+void EmulateSplitTransceiver::ptt (bool on) noexcept
+{
+#if WSJT_TRACE_CAT
+  qDebug () << "EmulateSplitTransceiver::ptt:" << on;
+#endif
+
+  // Save TX state for future frequency change requests.
+  if (on)
+    {
+      // save the Rx frequency
+      pre_tx_frequency_ = frequency_[0];
+
+      // Switch to other frequency if we have one i.e. client wants
+      // split operation).
+      wrapped_->frequency (frequency_[frequency_[1] ? 1 : 0]);
+
+      // Change TX state.
+      wrapped_->ptt (true);
+    }
+  else
+    {
+      // Change TX state.
+      wrapped_->ptt (false);
+
+      // Switch to RX frequency.
+      wrapped_->frequency (pre_tx_frequency_);
+      pre_tx_frequency_ = 0;
+    }
+  tx_ = on;
+}
+
+void EmulateSplitTransceiver::handle_update (TransceiverState state)
+{
+#if WSJT_TRACE_CAT
+  qDebug () << "EmulateSplitTransceiver::handle_update: from wrapped:" << state;
+#endif
+
+  // Change to reflect emulated state, we don't want to report the
+  // shifted frequency when transmitting.
+  if (pre_tx_frequency_)
+    {
+      state.frequency (pre_tx_frequency_);
+    }
+  else
+    {
+      // Follow the rig if in RX mode.
+      frequency_[0] = state.frequency ();
+    }
+
+  // Always report the other frequency as the Tx frequency we will use.
+  state.tx_frequency (frequency_[1]);
+
+  if (state.split ())
+    {
+      Q_EMIT failure (tr ("Emulated split mode requires rig to be in simplex mode"));
+    }
+  else
+    {
+      state.split (true);       // override rig state
+  
+#if WSJT_TRACE_CAT
+      qDebug () << "EmulateSplitTransceiver::handle_update: signalling:" << state;
+#endif
+
+      // signal emulated state
+      Q_EMIT update (state);
+    }
+}
diff --git a/EmulateSplitTransceiver.hpp b/EmulateSplitTransceiver.hpp
new file mode 100644
index 0000000..d088871
--- /dev/null
+++ b/EmulateSplitTransceiver.hpp
@@ -0,0 +1,53 @@
+#ifndef EMULATE_SPLIT_TRANSCEIVER_HPP__
+#define EMULATE_SPLIT_TRANSCEIVER_HPP__
+
+#include <memory>
+
+#include "Transceiver.hpp"
+
+//
+// Emulate Split Transceiver
+//
+// Helper decorator class that encapsulates  the emulation of split TX
+// operation.
+//
+// Responsibilities
+//
+//  Delegates  all  but setting  of  other  (split) frequency  to  the
+//  wrapped Transceiver instance. Also routes failure signals from the
+//  wrapped Transceiver instance to this instances failure signal.
+//
+//  Intercepts status  updates from  the wrapped  Transceiver instance
+//  and re-signals it with the emulated status.
+//
+//  Generates a status update signal if the other (split) frequency is
+//  changed, this is necessary  since the wrapped transceiver instance
+//  never receives other frequency changes.
+//
+class EmulateSplitTransceiver final
+  : public Transceiver
+{
+public:
+  // takes ownership of wrapped Transceiver
+  explicit EmulateSplitTransceiver (std::unique_ptr<Transceiver> wrapped);
+
+  void start () noexcept override;
+  void frequency (Frequency, MODE) noexcept override;
+  void tx_frequency (Frequency, bool rationalise_mode) noexcept override;
+  void ptt (bool on) noexcept override;
+
+  // forward everything else to wrapped Transceiver
+  void stop () noexcept override {wrapped_->stop (); Q_EMIT finished ();}
+  void mode (MODE m, bool /* rationalise */) noexcept override {wrapped_->mode (m, false);}
+  void sync (bool force_signal) noexcept override {wrapped_->sync (force_signal);}
+
+private:
+  void handle_update (TransceiverState);
+
+  std::unique_ptr<Transceiver> wrapped_;
+  Frequency frequency_[2];  // [0] <- RX, [1] <- other
+  Frequency pre_tx_frequency_;  // return to this on switching to Rx
+  bool tx_;
+};
+
+#endif
diff --git a/ForeignKeyDelegate.cpp b/ForeignKeyDelegate.cpp
new file mode 100644
index 0000000..18817e7
--- /dev/null
+++ b/ForeignKeyDelegate.cpp
@@ -0,0 +1,32 @@
+#include "ForeignKeyDelegate.hpp"
+
+#include <QComboBox>
+
+#include "CandidateKeyFilter.hpp"
+
+ForeignKeyDelegate::ForeignKeyDelegate (QAbstractItemModel const * referencing_model
+                                        , QAbstractItemModel * referenced_model
+                                        , int referencing_key_column
+                                        , int referenced_key_column
+                                        , QObject * parent
+                                        , int referencing_key_role
+                                        , int referenced_key_role)
+  : QStyledItemDelegate {parent}
+  , candidate_key_filter_ {new CandidateKeyFilter {referencing_model, referenced_model, referencing_key_column, referenced_key_column, referencing_key_role, referenced_key_role}}
+{
+}
+
+ForeignKeyDelegate::~ForeignKeyDelegate ()
+{
+}
+
+QWidget * ForeignKeyDelegate::createEditor (QWidget * parent
+                                            , QStyleOptionViewItem const& /* option */
+                                            , QModelIndex const& index) const
+{
+  auto editor = new QComboBox {parent};
+  editor->setFrame (false);
+  candidate_key_filter_->set_active_key (index);
+  editor->setModel (candidate_key_filter_.data ());
+  return editor;
+}
diff --git a/ForeignKeyDelegate.hpp b/ForeignKeyDelegate.hpp
new file mode 100644
index 0000000..9e0dc06
--- /dev/null
+++ b/ForeignKeyDelegate.hpp
@@ -0,0 +1,35 @@
+#ifndef FOREIGN_KEY_DELEGATE_HPP_
+#define FOREIGN_KEY_DELEGATE_HPP_
+
+#include <QStyledItemDelegate>
+#include <QScopedPointer>
+
+class CandidateKeyFilter;
+
+//
+// Class ForeignKeyDelegate
+//
+//	Item delegate for editing a foreign key item in a one or many
+//	to one relationship. A QComboBox is used as an item delegate
+//	for the edit role.
+//
+class ForeignKeyDelegate final
+  : public QStyledItemDelegate
+{
+public:
+  explicit ForeignKeyDelegate (QAbstractItemModel const * referencing_model
+                               , QAbstractItemModel * referenced_model
+                               , int referencing_key_column = 0
+                               , int referenced_key_column = 0
+                               , QObject * parent = nullptr
+                               , int referencing_key_role = Qt::EditRole
+                               , int referenced_key_role = Qt::EditRole);
+  ~ForeignKeyDelegate ();
+
+  QWidget * createEditor (QWidget * parent, QStyleOptionViewItem const&, QModelIndex const&) const override;
+
+private:
+  QScopedPointer<CandidateKeyFilter> candidate_key_filter_;
+};
+
+#endif
diff --git a/FrequencyItemDelegate.cpp b/FrequencyItemDelegate.cpp
new file mode 100644
index 0000000..8e9ebd5
--- /dev/null
+++ b/FrequencyItemDelegate.cpp
@@ -0,0 +1,36 @@
+#include "FrequencyItemDelegate.hpp"
+
+#include "Radio.hpp"
+#include "FrequencyLineEdit.hpp"
+#include "Bands.hpp"
+
+QString FrequencyItemDelegate::displayText (QVariant const& value, QLocale const& locale) const
+{
+  auto frequency = value.value<Radio::Frequency> ();
+  auto band_name = bands_->data (bands_->find (frequency));
+  return Radio::pretty_frequency_MHz_string (frequency, locale) + " MHz (" + band_name.toString () + ')';
+}
+
+QWidget * FrequencyItemDelegate::createEditor (QWidget * parent
+					       , QStyleOptionViewItem const& /* option */
+					       , QModelIndex const& /* index */) const
+{
+  auto editor = new FrequencyLineEdit {parent};
+  editor->setFrame (false);
+  return editor;
+}
+
+
+QString FrequencyDeltaItemDelegate::displayText (QVariant const& value, QLocale const& locale) const
+{
+  return Radio::pretty_frequency_MHz_string (value.value<Radio::FrequencyDelta> (), locale) + " MHz";
+}
+
+QWidget * FrequencyDeltaItemDelegate::createEditor (QWidget * parent
+					       , QStyleOptionViewItem const& /* option */
+					       , QModelIndex const& /* index */) const
+{
+  auto editor = new FrequencyDeltaLineEdit {parent};
+  editor->setFrame (false);
+  return editor;
+}
diff --git a/FrequencyItemDelegate.hpp b/FrequencyItemDelegate.hpp
new file mode 100644
index 0000000..55ec3b0
--- /dev/null
+++ b/FrequencyItemDelegate.hpp
@@ -0,0 +1,53 @@
+#ifndef FREQUENCY_ITEM_DELEGATE_HPP_
+#define FREQUENCY_ITEM_DELEGATE_HPP_
+
+#include <QStyledItemDelegate>
+
+class Bands;
+
+//
+// Class FrequencyItemDelegate
+//
+//	Item delegate for displaying and editing a Frequency item in a
+//	view that uses a FrequencyLineEdit as an item delegate for the
+//	edit role.
+//
+class FrequencyItemDelegate final
+  : public QStyledItemDelegate
+{
+public:
+  explicit FrequencyItemDelegate (Bands const * bands, QObject * parent = nullptr)
+    : QStyledItemDelegate {parent}
+    , bands_ {bands}
+  {
+  }
+
+  QString displayText (QVariant const& value, QLocale const&) const override;
+  QWidget * createEditor (QWidget * parent, QStyleOptionViewItem const&, QModelIndex const&) const override;
+
+private:
+  Bands const * bands_;
+};
+
+
+//
+// Class FrequencyDeltaItemDelegate
+//
+//	Item delegate for displaying and editing a FrequencyDelta item
+//	in a view that uses a FrequencyDeltaLineEdit as an item
+//	delegate for the edit role.
+//
+class FrequencyDeltaItemDelegate final
+  : public QStyledItemDelegate
+{
+public:
+  explicit FrequencyDeltaItemDelegate (QObject * parent = nullptr)
+    : QStyledItemDelegate {parent}
+  {
+  }
+
+  QString displayText (QVariant const& value, QLocale const&) const override;
+  QWidget * createEditor (QWidget * parent, QStyleOptionViewItem const&, QModelIndex const&) const override;
+};
+
+#endif
diff --git a/FrequencyLineEdit.cpp b/FrequencyLineEdit.cpp
new file mode 100644
index 0000000..e37800f
--- /dev/null
+++ b/FrequencyLineEdit.cpp
@@ -0,0 +1,40 @@
+#include "FrequencyLineEdit.hpp"
+
+#include <QRegExpValidator>
+#include <QRegExp>
+#include <QString>
+
+#include "moc_FrequencyLineEdit.cpp"
+
+FrequencyLineEdit::FrequencyLineEdit (QWidget * parent)
+  : QLineEdit (parent)
+{
+  setValidator (new QRegExpValidator {QRegExp {R"(\d{0,6}(\.\d{0,6})?)"}, this});
+}
+
+auto FrequencyLineEdit::frequency () const -> Frequency
+{
+  return Radio::frequency (text (), 6);
+}
+
+void FrequencyLineEdit::frequency (Frequency f)
+{
+  setText (Radio::frequency_MHz_string (f));
+}
+
+
+FrequencyDeltaLineEdit::FrequencyDeltaLineEdit (QWidget * parent)
+  : QLineEdit (parent)
+{
+  setValidator (new QRegExpValidator {QRegExp {R"(-?\d{0,6}(\.\d{0,6})?)"}, this});
+}
+
+auto FrequencyDeltaLineEdit::frequency_delta () const -> FrequencyDelta
+{
+  return Radio::frequency_delta (text (), 6);
+}
+
+void FrequencyDeltaLineEdit::frequency_delta (FrequencyDelta d)
+{
+  setText (Radio::frequency_MHz_string (d));
+}
diff --git a/FrequencyLineEdit.hpp b/FrequencyLineEdit.hpp
new file mode 100644
index 0000000..f59a37b
--- /dev/null
+++ b/FrequencyLineEdit.hpp
@@ -0,0 +1,45 @@
+#ifndef FREQUENCY_LINE_EDIT_HPP_
+#define FREQUENCY_LINE_EDIT_HPP_
+
+#include <QLineEdit>
+
+#include "Radio.hpp"
+
+class QWidget;
+
+//
+// MHz frequency line edits with validation
+//
+class FrequencyLineEdit final
+  : public QLineEdit
+{
+  Q_OBJECT;
+  Q_PROPERTY (Frequency frequency READ frequency WRITE frequency USER true);
+
+public:
+  using Frequency = Radio::Frequency;
+
+  explicit FrequencyLineEdit (QWidget * parent = nullptr);
+
+  // Property frequency implementation
+  Frequency frequency () const;
+  void frequency (Frequency);
+};
+
+class FrequencyDeltaLineEdit final
+  : public QLineEdit
+{
+  Q_OBJECT;
+  Q_PROPERTY (FrequencyDelta frequency_delta READ frequency_delta WRITE frequency_delta USER true);
+
+public:
+  using FrequencyDelta = Radio::FrequencyDelta;
+
+  explicit FrequencyDeltaLineEdit (QWidget * parent = nullptr);
+
+  // Property frequency_delta implementation
+  FrequencyDelta frequency_delta () const;
+  void frequency_delta (FrequencyDelta);
+};
+
+#endif
diff --git a/FrequencyList.cpp b/FrequencyList.cpp
new file mode 100644
index 0000000..76cac1f
--- /dev/null
+++ b/FrequencyList.cpp
@@ -0,0 +1,357 @@
+#include "FrequencyList.hpp"
+
+#include <utility>
+
+#include <QAbstractTableModel>
+#include <QString>
+#include <QList>
+#include <QListIterator>
+#include <QVector>
+#include <QStringList>
+#include <QMimeData>
+#include <QDataStream>
+#include <QByteArray>
+#include <QDebug>
+
+#include "pimpl_impl.hpp"
+
+class FrequencyList::impl final
+  : public QAbstractTableModel
+{
+public:
+  impl (Frequencies frequencies, QObject * parent)
+    : QAbstractTableModel {parent}
+    , frequencies_ {frequencies}
+  {
+  }
+
+  Frequencies const& frequencies () const {return frequencies_;}
+  void assign (Frequencies);
+  QModelIndex add (Frequency);
+
+protected:
+  // Implement the QAbstractTableModel interface
+  int rowCount (QModelIndex const& parent = QModelIndex {}) const override;
+  int columnCount (QModelIndex const& parent = QModelIndex {}) const override;
+  Qt::ItemFlags flags (QModelIndex const& = QModelIndex {}) const override;
+  QVariant data (QModelIndex const&, int role = Qt::DisplayRole) const override;
+  bool setData (QModelIndex const&, QVariant const& value, int role = Qt::EditRole) override;
+  QVariant headerData (int section, Qt::Orientation, int = Qt::DisplayRole) const override;
+  bool removeRows (int row, int count, QModelIndex const& parent = QModelIndex {}) override;
+  bool insertRows (int row, int count, QModelIndex const& parent = QModelIndex {}) override;
+  QStringList mimeTypes () const override;
+  QMimeData * mimeData (QModelIndexList const&) const override;
+
+private:
+  static int constexpr num_cols {2};
+  static auto constexpr mime_type ="application/wsjt.Frequencies";
+
+  Frequencies frequencies_;
+};
+
+FrequencyList::FrequencyList (QObject * parent)
+  : FrequencyList {{}, parent}
+{
+}
+
+FrequencyList::FrequencyList (Frequencies frequencies, QObject * parent)
+  : QSortFilterProxyModel {parent}
+  , m_ {frequencies, parent}
+{
+  setSourceModel (&*m_);
+  setSortRole (SortRole);
+}
+
+FrequencyList::~FrequencyList ()
+{
+}
+
+FrequencyList& FrequencyList::operator = (Frequencies frequencies)
+{
+  m_->assign (frequencies);
+  return *this;
+}
+
+auto FrequencyList::frequencies () const -> Frequencies
+{
+  return m_->frequencies ();
+}
+
+QModelIndex FrequencyList::add (Frequency f)
+{
+  return mapFromSource (m_->add (f));
+}
+
+bool FrequencyList::remove (Frequency f)
+{
+  auto row = m_->frequencies ().indexOf (f);
+
+  if (0 > row)
+    {
+      return false;
+    }
+
+  return m_->removeRow (row);
+}
+
+namespace
+{
+  bool row_is_higher (QModelIndex const& lhs, QModelIndex const& rhs)
+  {
+    return lhs.row () > rhs.row ();
+  }
+}
+
+bool FrequencyList::removeDisjointRows (QModelIndexList rows)
+{
+  bool result {true};
+
+  // We must work with source model indexes because we don't want row
+  // removes to invalidate model indexes we haven't yet processed. We
+  // achieve that by processing them in decending row order.
+  for (int r = 0; r < rows.size (); ++r)
+    {
+      rows[r] = mapToSource (rows[r]);
+    }
+
+  // reverse sort by row
+  qSort (rows.begin (), rows.end (), row_is_higher);
+  Q_FOREACH (auto index, rows)
+    {
+      if (result && !m_->removeRow (index.row ()))
+        {
+          result = false;
+        }
+    }
+
+  return result;
+}
+
+
+void FrequencyList::impl::assign (Frequencies frequencies)
+{
+  beginResetModel ();
+  std::swap (frequencies_, frequencies);
+  endResetModel ();
+}
+
+QModelIndex FrequencyList::impl::add (Frequency f)
+{
+  // Any Frequency that isn't in the list may be added
+  if (!frequencies_.contains (f))
+    {
+      auto row = frequencies_.size ();
+
+      beginInsertRows (QModelIndex {}, row, row);
+      frequencies_.append (f);
+      endInsertRows ();
+
+      return index (row, 0);
+    }
+
+  return QModelIndex {};
+}
+
+int FrequencyList::impl::rowCount (QModelIndex const& parent) const
+{
+  return parent.isValid () ? 0 : frequencies_.size ();
+}
+
+int FrequencyList::impl::columnCount (QModelIndex const& parent) const
+{
+  return parent.isValid () ? 0 : num_cols;
+}
+
+Qt::ItemFlags FrequencyList::impl::flags (QModelIndex const& index) const
+{
+  auto result = QAbstractTableModel::flags (index) | Qt::ItemIsDropEnabled;
+
+  auto row = index.row ();
+  auto column = index.column ();
+
+  if (index.isValid ()
+      && row < frequencies_.size ()
+      && column < num_cols)
+    {
+      switch (column)
+        {
+        case 0:
+          result |= Qt::ItemIsEditable | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled;
+          break;
+
+        case 1:
+          result |= Qt::ItemIsDragEnabled;
+          break;
+        }
+    }
+
+  return result;
+}
+
+QVariant FrequencyList::impl::data (QModelIndex const& index, int role) const
+{
+  QVariant item;
+
+  auto row = index.row ();
+  auto column = index.column ();
+
+  if (index.isValid ()
+      && row < frequencies_.size ()
+      && column < num_cols)
+    {
+      auto frequency = frequencies_.at (row);
+
+      switch (column)
+        {
+        case 0:
+          switch (role)
+            {
+            case SortRole:
+            case Qt::DisplayRole:
+            case Qt::EditRole:
+            case Qt::AccessibleTextRole:
+              item = frequency;
+              break;
+
+            case Qt::ToolTipRole:
+            case Qt::AccessibleDescriptionRole:
+              item = tr ("Frequency");
+              break;
+
+            case Qt::TextAlignmentRole:
+              item = Qt::AlignRight + Qt::AlignVCenter;
+              break;
+            }
+          break;
+
+        case 1:
+          switch (role)
+            {
+            case Qt::DisplayRole:
+            case Qt::EditRole:
+            case Qt::AccessibleTextRole:
+              item = static_cast<double> (frequency / 1.e6);
+              break;
+
+            case SortRole:	// use the underlying Frequency value
+              item = frequency;
+              break;
+
+            case Qt::ToolTipRole:
+            case Qt::AccessibleDescriptionRole:
+              item = tr ("Frequency MHz");
+              break;
+
+            case Qt::TextAlignmentRole:
+              item = Qt::AlignRight + Qt::AlignVCenter;
+              break;
+            }
+          break;
+        }
+    }
+
+  return item;
+}
+
+bool FrequencyList::impl::setData (QModelIndex const& model_index, QVariant const& value, int role)
+{
+  bool changed {false};
+
+  auto row = model_index.row ();
+  if (model_index.isValid ()
+      && Qt::EditRole == role
+      && row < frequencies_.size ()
+      && 0 == model_index.column ()
+      && value.canConvert<Frequency> ())
+    {
+      auto frequency = value.value<Frequency> ();
+      auto original_frequency = frequencies_.at (row);
+      if (frequency != original_frequency)
+        {
+          frequencies_.replace (row, frequency);
+          Q_EMIT dataChanged (model_index, index (model_index.row (), 1), QVector<int> {} << role);
+        }
+      changed = true;
+    }
+
+  return changed;
+}
+
+QVariant FrequencyList::impl::headerData (int section, Qt::Orientation orientation, int role) const
+{
+  QVariant header;
+
+  if (Qt::DisplayRole == role
+      && Qt::Horizontal == orientation
+      && section < num_cols)
+    {
+      switch (section)
+        {
+        case 0: header = tr ("Frequency"); break;
+        case 1: header = tr ("Frequency (MHz)"); break;
+        }
+    }
+  else
+    {
+      header = QAbstractTableModel::headerData (section, orientation, role);
+    }
+
+  return header;
+}
+
+bool FrequencyList::impl::removeRows (int row, int count, QModelIndex const& parent)
+{
+  if (0 < count && (row + count) <= rowCount (parent))
+    {
+      beginRemoveRows (parent, row, row + count - 1);
+      for (auto r = 0; r < count; ++r)
+        {
+          frequencies_.removeAt (row);
+        }
+      endRemoveRows ();
+      return true;
+    }
+
+  return false;
+}
+
+bool FrequencyList::impl::insertRows (int row, int count, QModelIndex const& parent)
+{
+  if (0 < count)
+    {
+      beginInsertRows (parent, row, row + count - 1);
+      for (auto r = 0; r < count; ++r)
+        {
+          frequencies_.insert (row, Frequency {});
+        }
+      endInsertRows ();
+      return true;
+    }
+
+  return false;
+}
+
+QStringList FrequencyList::impl::mimeTypes () const
+{
+  QStringList types;
+  types << mime_type;
+  return types;
+}
+
+QMimeData * FrequencyList::impl::mimeData (QModelIndexList const& items) const
+{
+  QMimeData * mime_data = new QMimeData {};
+  QByteArray encoded_data;
+  QDataStream stream {&encoded_data, QIODevice::WriteOnly};
+
+  Q_FOREACH (auto const& item, items)
+    {
+      if (item.isValid ())
+        {
+          stream << QString {data (item, Qt::DisplayRole).toString ()};
+        }
+    }
+
+  mime_data->setData (mime_type, encoded_data);
+  return mime_data;
+}
diff --git a/FrequencyList.hpp b/FrequencyList.hpp
new file mode 100644
index 0000000..c226592
--- /dev/null
+++ b/FrequencyList.hpp
@@ -0,0 +1,59 @@
+#ifndef FREQUENCY_LIST_HPP__
+#define FREQUENCY_LIST_HPP__
+
+#include "pimpl_h.hpp"
+
+#include <QSortFilterProxyModel>
+
+#include "Radio.hpp"
+
+//
+// Class FrequencyList
+//
+//  Encapsulates a collection of frequencies.  The implementation is a
+//  table  containing the  list of  Frequency type  elements which  is
+//  editable  and  a  second  column  which  is  an  immutable  double
+//  representation  of  the  corresponding Frequency  item  scaled  to
+//  mega-Hertz.
+//
+//  The list is ordered.
+//
+// Responsibilities
+//
+//  Stores internally a list  of unique frequencies.  Provides methods
+//  to add and delete list elements.
+//
+// Collaborations
+//
+//  Implements the QSortFilterProxyModel interface  for a list of spot
+//  frequencies.
+//
+class FrequencyList final
+  : public QSortFilterProxyModel
+{
+public:
+  using Frequency = Radio::Frequency;
+  using Frequencies = Radio::Frequencies;
+
+  explicit FrequencyList (QObject * parent = nullptr);
+  explicit FrequencyList (Frequencies, QObject * parent = nullptr);
+  ~FrequencyList ();
+
+  // Load and store contents
+  FrequencyList& operator = (Frequencies);
+  Frequencies frequencies () const;
+
+  // Model API
+  QModelIndex add (Frequency);
+  bool remove (Frequency);
+  bool removeDisjointRows (QModelIndexList);
+
+  // Custom roles.
+  static int constexpr SortRole = Qt::UserRole;
+
+private:
+  class impl;
+  pimpl<impl> m_;
+};
+
+#endif
diff --git a/GetUserId.cpp b/GetUserId.cpp
new file mode 100644
index 0000000..238c3b5
--- /dev/null
+++ b/GetUserId.cpp
@@ -0,0 +1,75 @@
+#include "GetUserId.hpp"
+
+#include <stdexcept>
+
+#include <QApplication>
+#include <QString>
+#include <QDialog>
+#include <QLineEdit>
+#include <QRegExpValidator>
+#include <QDialogButtonBox>
+#include <QFormLayout>
+#include <QVBoxLayout>
+
+//
+// Dialog to get callsign
+//
+class CallsignDialog final
+  : public QDialog
+{
+  Q_OBJECT;
+
+private:
+  Q_DISABLE_COPY (CallsignDialog);
+
+public:
+  explicit CallsignDialog (QWidget * parent = nullptr)
+    : QDialog {parent}
+  {
+    setWindowTitle (QApplication::applicationName () + " - " + tr ("Callsign"));
+    
+    callsign_.setValidator (new QRegExpValidator {QRegExp {"[A-Za-z0-9]+"}, this});
+    
+    auto form_layout = new QFormLayout ();
+    form_layout->addRow ("&Callsign:", &callsign_);
+    
+    auto main_layout = new QVBoxLayout (this);
+    main_layout->addLayout (form_layout);
+    
+    auto button_box = new QDialogButtonBox {QDialogButtonBox::Ok | QDialogButtonBox::Cancel};
+    main_layout->addWidget (button_box);
+
+    connect (button_box, &QDialogButtonBox::accepted, this, &CallsignDialog::accept);
+    connect (button_box, &QDialogButtonBox::rejected, this, &CallsignDialog::reject);
+  }
+  
+  QString callsign () const {return callsign_.text ();}
+  
+private:
+  QLineEdit callsign_;
+};
+
+#include "GetUserId.moc"
+
+QString get_user_id ()
+{
+  // get the users callsign so we can use it to persist the
+  // settings and log file against a unique tag
+  QString id;
+  {
+    CallsignDialog dialog;
+    while (id.isEmpty ())
+      {
+        if (QDialog::Accepted == dialog.exec ())
+          {
+            id = dialog.callsign ().toUpper ();
+          }
+        else
+          {
+            throw std::runtime_error ("Callsign required");
+          }
+      }
+  }
+
+  return id;
+}
diff --git a/GetUserId.hpp b/GetUserId.hpp
new file mode 100644
index 0000000..205042f
--- /dev/null
+++ b/GetUserId.hpp
@@ -0,0 +1,8 @@
+#ifndef GETUSERID_HPP_
+#define GETUSERID_HPP_
+
+#include <QString>
+
+QString get_user_id ();
+
+#endif
diff --git a/HRDTransceiver.cpp b/HRDTransceiver.cpp
new file mode 100644
index 0000000..bf94541
--- /dev/null
+++ b/HRDTransceiver.cpp
@@ -0,0 +1,1002 @@
+#include "HRDTransceiver.hpp"
+
+#include <QHostAddress>
+#include <QByteArray>
+#include <QRegExp>
+#include <QTcpSocket>
+#include <QThread>
+#include <QStandardPaths>
+#include <QDir>
+
+#include "NetworkServerLookup.hpp"
+
+namespace
+{
+  char const * const HRD_transceiver_name = "Ham Radio Deluxe";
+
+  // some commands require a settling time, particularly "RX A" and
+  // "RX B" on the Yaesu FTdx3000.
+  int constexpr yaesu_delay {250};
+}
+
+void HRDTransceiver::register_transceivers (TransceiverFactory::Transceivers * registry, int id)
+{
+  (*registry)[HRD_transceiver_name] = TransceiverFactory::Capabilities (id, TransceiverFactory::Capabilities::network, true);
+}
+
+struct HRDMessage
+{
+  // Placement style new overload for outgoing messages that does the
+  // construction too.
+  static void * operator new (size_t size, QString const& payload)
+  {
+    size += sizeof (QChar) * (payload.size () + 1); // space for terminator too
+    HRDMessage * storage (reinterpret_cast<HRDMessage *> (new char[size]));
+    storage->size_ = size ;
+    ushort const * pl (payload.utf16 ());
+    qCopy (pl, pl + payload.size () + 1, storage->payload_); // copy terminator too
+    storage->magic_1_ = magic_1_value_;
+    storage->magic_2_ = magic_2_value_;
+    storage->checksum_ = 0;
+    return storage;
+  }
+
+  // Placement style new overload for incoming messages that does the
+  // construction too.
+  //
+  // No memory allocation here.
+  static void * operator new (size_t /* size */, QByteArray const& message)
+  {
+    // Nasty const_cast here to avoid copying the message buffer.
+    return const_cast<HRDMessage *> (reinterpret_cast<HRDMessage const *> (message.data ()));
+  }
+
+  void operator delete (void * p, size_t)
+  {
+    delete [] reinterpret_cast<char *> (p); // Mirror allocation in operator new above.
+  }
+
+  quint32 size_;
+  qint32 magic_1_;
+  qint32 magic_2_;
+  qint32 checksum_;            // Apparently not used.
+  QChar payload_[0];           // UTF-16 (which is wchar_t on Windows)
+
+  static qint32 const magic_1_value_;
+  static qint32 const magic_2_value_;
+};
+
+qint32 const HRDMessage::magic_1_value_ (0x1234ABCD);
+qint32 const HRDMessage::magic_2_value_ (0xABCD1234);
+
+HRDTransceiver::HRDTransceiver (std::unique_ptr<TransceiverBase> wrapped
+                                , QString const& server
+                                , bool use_for_ptt
+                                , int poll_interval)
+  : PollingTransceiver {poll_interval}
+  , wrapped_ {std::move (wrapped)}
+  , use_for_ptt_ {use_for_ptt}
+  , server_ {server}
+  , hrd_ {0}
+  , protocol_ {none}
+  , current_radio_ {0}
+  , vfo_count_ {0}
+  , vfo_A_button_ {-1}
+  , vfo_B_button_ {-1}
+  , vfo_toggle_button_ {-1}
+  , mode_A_dropdown_ {-1}
+  , mode_B_dropdown_ {-1}
+  , split_mode_button_ {-1}
+  , split_mode_dropdown_ {-1}
+  , split_mode_dropdown_write_only_ {false}
+  , split_mode_dropdown_selection_on_ {-1}
+  , split_mode_dropdown_selection_off_ {-1}
+  , split_off_button_ {-1}
+  , tx_A_button_ {-1}
+  , tx_B_button_ {-1}
+  , rx_A_button_ {-1}
+  , rx_B_button_ {-1}
+  , receiver_dropdown_ {-1}
+  , ptt_button_ {-1}
+  , reversed_ {false}
+{
+}
+
+HRDTransceiver::~HRDTransceiver ()
+{
+}
+
+void HRDTransceiver::do_start ()
+{
+  TRACE_CAT ("starting");
+  wrapped_->start ();
+
+  auto server_details = network_server_lookup (server_, 7809u);
+  if (!hrd_)
+    {
+      hrd_ = new QTcpSocket {this}; // QObject takes ownership
+    }
+  hrd_->connectToHost (std::get<0> (server_details), std::get<1> (server_details));
+  if (!hrd_->waitForConnected ())
+    {
+      TRACE_CAT ("failed to connect:" <<  hrd_->errorString ());
+      throw error {tr ("Failed to connect to Ham Radio Deluxe\n") + hrd_->errorString ()};
+    }
+
+  if (none == protocol_)
+    {
+      try
+        {
+          protocol_ = v5;	// try this first (works for v6 too)
+          send_command ("get context", false, false);
+        }
+      catch (error const&)
+        {
+          protocol_ = none;
+        }
+    }
+
+  if (none == protocol_)
+    {
+      hrd_->close ();
+
+      protocol_ = v4;		// try again with older protocol
+      hrd_->connectToHost (std::get<0> (server_details), std::get<1> (server_details));
+      if (!hrd_->waitForConnected ())
+        {
+          TRACE_CAT ("failed to connect:" <<  hrd_->errorString ());
+          throw error {tr ("Failed to connect to Ham Radio Deluxe\n") + hrd_->errorString ()};
+        }
+
+      send_command ("get context", false, false);
+    }
+
+  QFile HRD_info_file {QDir {QStandardPaths::writableLocation (QStandardPaths::DataLocation)}.absoluteFilePath ("HRD Interface Information.txt")};
+  if (!HRD_info_file.open (QFile::WriteOnly | QFile::Text | QFile::Truncate))
+    {
+      throw error {tr ("Failed to open file \"%1\": %2.").arg (HRD_info_file.fileName ()).arg (HRD_info_file.errorString ())};
+    }
+  QTextStream HRD_info {&HRD_info_file};
+
+  auto id = send_command ("get id", false, false);
+  auto version = send_command ("get version", false, false);
+
+  TRACE_CAT ("Id:" << id << "Version:" << version);
+  HRD_info << "Id: " << id << "\n";
+  HRD_info << "Version: " << version << "\n";
+
+  auto radios = send_command ("get radios", false, false).trimmed ().split (',', QString::SkipEmptyParts);
+  if (radios.isEmpty ())
+    {
+      TRACE_CAT ("no rig found");
+      throw error {tr ("Ham Radio Deluxe: no rig found")};
+    }
+
+  HRD_info << "Radios:\n";
+  Q_FOREACH (auto const& radio, radios)
+    {
+      HRD_info << "\t" << radio << "\n";
+      auto entries = radio.trimmed ().split (':', QString::SkipEmptyParts);
+      radios_.push_back (std::forward_as_tuple (entries[0].toUInt (), entries[1]));
+    }
+
+#if WSJT_TRACE_CAT
+  TRACE_CAT ("radios:-");
+  Q_FOREACH (auto const& radio, radios_)
+    {
+      TRACE_CAT ("\t[" << std::get<0> (radio) << "] " << std::get<1> (radio));
+    }
+#endif
+
+  auto current_radio_name = send_command ("get radio", false, false, true);
+  HRD_info << "Current radio: " << current_radio_name << "\n";
+  if (current_radio_name.isEmpty ())
+    {
+      TRACE_CAT ("no rig found");
+      throw error {tr ("Ham Radio Deluxe: no rig found")};
+    }
+
+  vfo_count_ = send_command ("get vfo-count").toUInt ();
+  HRD_info << "VFO count: " << vfo_count_ << "\n";
+  TRACE_CAT ("vfo count:" << vfo_count_);
+
+  buttons_ = send_command ("get buttons").trimmed ().split (',', QString::SkipEmptyParts).replaceInStrings (" ", "~");
+  TRACE_CAT ("HRD Buttons: " << buttons_);
+  HRD_info << "Buttons: {" << buttons_.join (", ") << "}\n";
+
+  dropdown_names_ = send_command ("get dropdowns").trimmed ().split (',', QString::SkipEmptyParts);
+  TRACE_CAT ("Dropdowns:");
+  HRD_info << "Dropdowns:\n";
+  Q_FOREACH (auto const& dd, dropdown_names_)
+    {
+      auto selections = send_command ("get dropdown-list {" + dd + "}").trimmed ().split (',', QString::SkipEmptyParts);
+      TRACE_CAT ("\t" << dd << ": {" << selections.join (", ") << "}");
+      HRD_info << "\t" << dd << ": {" << selections.join (", ") << "}\n";
+      dropdowns_[dd] = selections;
+    }
+
+  slider_names_ = send_command ("get sliders").trimmed ().split (',', QString::SkipEmptyParts).replaceInStrings (" ", "~");
+  TRACE_CAT ("Sliders:-");
+  HRD_info << "Sliders:\n";
+  Q_FOREACH (auto const& s, slider_names_)
+    {
+      auto range = send_command ("get slider-range " + current_radio_name + " " + s).trimmed ().split (',', QString::SkipEmptyParts);
+      TRACE_CAT ("\t" << s << ": {" << range.join (", ") << "}");
+      HRD_info << "\t" << s << ": {" << range.join (", ") << "}\n";
+      sliders_[s] = range;
+    }
+
+  // set RX VFO
+  rx_A_button_ = find_button (QRegExp ("^(RX~A)$"));
+  rx_B_button_ = find_button (QRegExp ("^(RX~B)$"));
+
+  // select VFO (sometime set as well)
+  vfo_A_button_ = find_button (QRegExp ("^(VFO~A|Main)$"));
+  vfo_B_button_ = find_button (QRegExp ("^(VFO~B|Sub)$"));
+
+  vfo_toggle_button_ = find_button (QRegExp ("^(A~/~B)$"));
+
+  split_mode_button_ = find_button (QRegExp ("^(Spl~On|Spl_On|Split)$"));
+  split_off_button_ = find_button (QRegExp ("^(Spl~Off|Spl_Off)$"));
+
+  if ((split_mode_dropdown_ = find_dropdown (QRegExp ("^(Split)$"))) >= 0)
+    {
+      split_mode_dropdown_selection_on_ = find_dropdown_selection (split_mode_dropdown_, QRegExp ("^(On)$"));
+      split_mode_dropdown_selection_off_ = find_dropdown_selection (split_mode_dropdown_, QRegExp ("^(Off)$"));
+    }
+  else if ((receiver_dropdown_ = find_dropdown (QRegExp ("^Receiver$"))) >= 0)
+    {
+      rx_A_selection_ = find_dropdown_selection (receiver_dropdown_, QRegExp ("^(RX / Off)$"));
+      rx_B_selection_ = find_dropdown_selection (receiver_dropdown_, QRegExp ("^(Mute / RX)$"));
+    }
+
+  tx_A_button_ = find_button (QRegExp ("^(TX~main|TX~-~A|TX~A)$"));
+  tx_B_button_ = find_button (QRegExp ("^(TX~sub|TX~-~B|TX~B)$"));
+
+  if ((mode_A_dropdown_ = find_dropdown (QRegExp ("^(Main Mode|Mode|Mode A)$"))) >= 0)
+    {
+      map_modes (mode_A_dropdown_, &mode_A_map_);
+    }
+  else
+    {
+      Q_ASSERT (mode_A_dropdown_ <= 0);
+    }
+
+  if ((mode_B_dropdown_ = find_dropdown (QRegExp ("^(Sub Mode|Mode B)$"))) >= 0)
+    {
+      map_modes (mode_B_dropdown_, &mode_B_map_);
+    }
+
+  ptt_button_ = find_button (QRegExp ("^(TX)$"));
+
+  if (vfo_count_ == 1 && ((vfo_B_button_ >= 0 && vfo_A_button_ >= 0) || vfo_toggle_button_ >= 0))
+    {
+      // put the rig into a known state for tricky cases like Icoms
+
+      auto f = send_command ("get frequency").toUInt ();
+      auto m = lookup_mode (get_dropdown (mode_A_dropdown_), mode_A_map_);
+      set_button (vfo_B_button_ >= 0 ? vfo_B_button_ : vfo_toggle_button_);
+      auto fo = send_command ("get frequency").toUInt ();
+      update_other_frequency (fo);
+      auto mo = lookup_mode (get_dropdown (mode_A_dropdown_), mode_A_map_);
+      set_button (vfo_A_button_ >= 0 ? vfo_A_button_ : vfo_toggle_button_);
+      if (f != fo || m != mo)
+        {
+          // we must have started with A/MAIN
+          update_rx_frequency (f);
+          update_mode (m);
+        }
+      else
+        {
+          update_rx_frequency (send_command ("get frequency").toUInt ());
+          update_mode (lookup_mode (get_dropdown (mode_A_dropdown_), mode_A_map_));
+        }
+    }
+}
+
+void HRDTransceiver::do_stop ()
+{
+  if (hrd_)
+    {
+      hrd_->close ();
+    }
+
+  if (wrapped_)
+    {
+      wrapped_->stop ();
+    }
+  TRACE_CAT ("stopped" << state () << "reversed" << reversed_);
+}
+
+int HRDTransceiver::find_button (QRegExp const& re) const
+{
+  return buttons_.indexOf (re);
+}
+
+int HRDTransceiver::find_dropdown (QRegExp const& re) const
+{
+  return dropdown_names_.indexOf (re);
+}
+
+std::vector<int> HRDTransceiver::find_dropdown_selection (int dropdown, QRegExp const& re) const
+{
+  std::vector<int> indices;
+  auto list = dropdowns_.value (dropdown_names_.value (dropdown));
+  int index {0};
+  while (-1 != (index = list.lastIndexOf (re, index - 1)))
+    {
+      // search backwards because more specialized modes tend to be later in
+      // list
+      indices.push_back (index);
+      if (!index)
+        {
+          break;
+        }
+    }
+  return indices;
+}
+
+void HRDTransceiver::map_modes (int dropdown, ModeMap *map)
+{
+  // order matters here (both in the map and in the regexps)
+  map->push_back (std::forward_as_tuple (CW, find_dropdown_selection (dropdown, QRegExp ("^(CW|CW\\(N\\))|CWL$"))));
+  map->push_back (std::forward_as_tuple (CW_R, find_dropdown_selection (dropdown, QRegExp ("^(CW-R|CW|CWU)$"))));
+  map->push_back (std::forward_as_tuple (LSB, find_dropdown_selection (dropdown, QRegExp ("^(LSB)$"))));
+  map->push_back (std::forward_as_tuple (USB, find_dropdown_selection (dropdown, QRegExp ("^(USB)$"))));
+  map->push_back (std::forward_as_tuple (DIG_U, find_dropdown_selection (dropdown, QRegExp ("^(DIG|DIGU|DATA-U|PKT-U|DATA|USER-U|USB)$"))));
+  map->push_back (std::forward_as_tuple (DIG_L, find_dropdown_selection (dropdown, QRegExp ("^(DIG|DIGL|DATA-L|PKT-L|DATA-R|USER-L|LSB)$"))));
+  map->push_back (std::forward_as_tuple (FSK, find_dropdown_selection (dropdown, QRegExp ("^(DIG|FSK|RTTY|RTTY-LSB)$"))));
+  map->push_back (std::forward_as_tuple (FSK_R, find_dropdown_selection (dropdown, QRegExp ("^(DIG|FSK-R|RTTY-R|RTTY|RTTY-USB)$"))));
+  map->push_back (std::forward_as_tuple (AM, find_dropdown_selection (dropdown, QRegExp ("^(AM|DSB|SAM|DRM)$"))));
+  map->push_back (std::forward_as_tuple (FM, find_dropdown_selection (dropdown, QRegExp ("^(FM|FM\\(N\\)|FM-N|WFM)$"))));
+  map->push_back (std::forward_as_tuple (DIG_FM, find_dropdown_selection (dropdown, QRegExp ("^(PKT-FM|PKT|FM)$"))));
+
+#if WSJT_TRACE_CAT
+  TRACE_CAT ("for dropdown" << dropdown_names_[dropdown]);
+  std::for_each (map->begin (), map->end (), [this, dropdown] (ModeMap::value_type const& item)
+                 {
+                   auto const& rhs = std::get<1> (item);
+                   TRACE_CAT ('\t' << std::get<0> (item) << "<->" << (rhs.size () ? dropdowns_[dropdown_names_[dropdown]][rhs.front ()] : "None"));
+                 });
+#endif
+}
+
+int HRDTransceiver::lookup_mode (MODE mode, ModeMap const& map) const
+{
+  auto it = std::find_if (map.begin (), map.end (), [mode] (ModeMap::value_type const& item) {return std::get<0> (item) == mode;});
+  if (map.end () == it)
+    {
+      throw error {tr ("Ham Radio Deluxe: rig doesn't support mode")};
+    }
+  return std::get<1> (*it).front ();
+}
+
+auto HRDTransceiver::lookup_mode (int mode, ModeMap const& map) const -> MODE
+{
+  if (mode < 0)
+    {
+      return UNK;               // no mode dropdown
+    }
+
+  auto it = std::find_if (map.begin (), map.end (), [mode] (ModeMap::value_type const& item)
+                          {
+                            auto const& indices = std::get<1> (item);
+                            return indices.cend () != std::find (indices.cbegin (), indices.cend (), mode);
+                          });
+  if (map.end () == it)
+    {
+      throw error {tr ("Ham Radio Deluxe: sent an unrecognised mode")};
+    }
+  return std::get<0> (*it);
+}
+
+int HRDTransceiver::get_dropdown (int dd, bool no_debug)
+{
+  if (dd < 0)
+    {
+      return -1;                // no dropdown to interrogate
+    }
+
+  auto dd_name = dropdown_names_.value (dd);
+  auto reply = send_command ("get dropdown-text {" + dd_name + "}", no_debug);
+  auto colon_index = reply.indexOf (':');
+
+  if (colon_index < 0)
+    {
+      return -1;
+    }
+
+  Q_ASSERT (reply.left (colon_index).trimmed () == dd_name);
+  return dropdowns_.value (dropdown_names_.value (dd)).indexOf (reply.mid (colon_index + 1).trimmed ());
+}
+
+void HRDTransceiver::set_dropdown (int dd, int value)
+{
+  auto dd_name = dropdown_names_.value (dd);
+  if (value >= 0)
+    {
+      send_simple_command ("set dropdown " + dd_name.replace (' ', '~') + ' ' + dropdowns_.value (dd_name).value (value).replace (' ', '~') + ' ' + QString::number (value));
+    }
+  else
+    {
+      TRACE_CAT ("item" << value << "not found in" << dd_name);
+      throw error {tr ("Ham Radio Deluxe: item not found in %1 dropdown list").arg (dd_name)};
+    }
+}
+
+void HRDTransceiver::do_ptt (bool on)
+{
+  TRACE_CAT (on);
+  if (use_for_ptt_)
+    {
+      if (ptt_button_ >= 0)
+        {
+          set_button (ptt_button_, on);
+        }
+      // else
+      // allow for pathological HRD rig interfaces that don't do
+      // PTT by simply not even trying
+    }
+  else
+    {
+      wrapped_->ptt (on);
+    }
+  update_PTT (on);
+}
+
+void HRDTransceiver::set_button (int button_index, bool checked)
+{
+  if (button_index >= 0)
+    {
+      send_simple_command ("set button-select " + buttons_.value (button_index) + (checked ? " 1" : " 0"));
+      if (button_index == rx_A_button_ || button_index == rx_B_button_)
+        {
+          QThread::msleep (yaesu_delay);
+        }
+    }
+  else
+    {
+      TRACE_CAT ("invalid button");
+      throw error {tr ("Ham Radio Deluxe: button not available")};
+    }
+}
+
+void HRDTransceiver::do_frequency (Frequency f, MODE m)
+{
+  TRACE_CAT (f << "reversed" << reversed_);
+  if (UNK != m)
+    {
+      do_mode (m, false);
+    }
+  auto fo_string = QString::number (f);
+  if (vfo_count_ > 1 && reversed_)
+    {
+      auto frequencies = send_command ("get frequencies").trimmed ().split ('-', QString::SkipEmptyParts);
+      send_simple_command ("set frequencies-hz " + QString::number (frequencies[0].toUInt ()) + ' ' + fo_string);
+    }
+  else
+    {
+      send_simple_command ("set frequency-hz " + QString::number (f));
+    }
+  update_rx_frequency (f);
+}
+
+void HRDTransceiver::do_tx_frequency (Frequency tx, bool rationalise_mode)
+{
+  TRACE_CAT (tx << "rationalize mode:" << rationalise_mode << "reversed" << reversed_);
+
+  // re-check if reversed VFOs
+  bool rx_A {true};
+  bool rx_B {false};
+  if (receiver_dropdown_ >= 0)
+    {
+      auto selection = get_dropdown (receiver_dropdown_);
+      rx_A = selection == rx_A_selection_.front ();
+      if (!rx_A)
+        {
+          rx_B = selection == rx_B_selection_.front ();
+        }
+    }
+  else if (vfo_B_button_ >= 0 || rx_B_button_ >= 0)
+    {
+      rx_A = is_button_checked (rx_A_button_ >= 0 ? rx_A_button_ : vfo_A_button_);
+      if (!rx_A)
+        {
+          rx_B = is_button_checked (rx_B_button_ >= 0 ? rx_B_button_ : vfo_B_button_);
+        }
+    }
+  reversed_ = rx_B;
+
+  bool split {tx != 0};
+  if (split)
+    {
+      if (rationalise_mode)
+        {
+          if (!reversed_ && mode_B_dropdown_ >= 0)
+            {
+              set_dropdown (mode_B_dropdown_, lookup_mode (state ().mode (), mode_B_map_));
+            }
+          else if (reversed_ && mode_B_dropdown_ >= 0)
+            {
+              set_dropdown (mode_A_dropdown_, lookup_mode (state ().mode (), mode_A_map_));
+            }
+          else
+            {
+              Q_ASSERT (mode_A_dropdown_ >= 0 && ((vfo_A_button_ >=0 && vfo_B_button_ >=0) || vfo_toggle_button_ >= 0));
+
+              if (rx_B_button_ >= 0)
+                {
+                  set_button (reversed_ ? rx_A_button_ : rx_B_button_);
+                  set_dropdown (mode_A_dropdown_, lookup_mode (state ().mode (), mode_A_map_));
+                  set_button (reversed_ ? rx_B_button_ : rx_A_button_);
+                }
+              else if (receiver_dropdown_ >= 0)
+                {
+                  set_dropdown (receiver_dropdown_, (reversed_ ? rx_A_selection_ : rx_B_selection_).front ());
+                  set_dropdown (mode_A_dropdown_, lookup_mode (state ().mode (), mode_A_map_));
+                  set_dropdown (receiver_dropdown_, (reversed_ ? rx_B_selection_ : rx_A_selection_).front ());
+                }
+              else
+                {
+                  set_button (vfo_A_button_ >= 0 ? (reversed_ ? vfo_A_button_ : vfo_B_button_) : vfo_toggle_button_);
+                  set_dropdown (mode_A_dropdown_, lookup_mode (state ().mode (), mode_A_map_));
+                  set_button (vfo_A_button_ >= 0 ? (reversed_ ? vfo_B_button_ : vfo_A_button_) : vfo_toggle_button_);
+                }
+            }
+        }
+
+      auto fo_string = QString::number (tx);
+      if (reversed_)
+        {
+          Q_ASSERT (vfo_count_ > 1);
+
+          auto frequencies = send_command ("get frequencies").trimmed ().split ('-', QString::SkipEmptyParts);
+          send_simple_command ("set frequencies-hz " + fo_string + ' ' + QString::number (frequencies[1].toUInt ()));
+        }
+      else
+        {
+          if (vfo_count_ > 1)
+            {
+              auto frequencies = send_command ("get frequencies").trimmed ().split ('-', QString::SkipEmptyParts);
+              send_simple_command ("set frequencies-hz " + QString::number (frequencies[0].toUInt ()) + ' ' + fo_string);
+            }
+          else if ((vfo_B_button_ >= 0 && vfo_A_button_ >= 0) || vfo_toggle_button_ >= 0)
+            {
+              // we rationalise the modes here as well as the frequencies
+              set_button (vfo_B_button_ >= 0 ? vfo_B_button_ : vfo_toggle_button_);
+              send_simple_command ("set frequency-hz " + fo_string);
+              if (rationalise_mode && mode_B_dropdown_ < 0)
+                {
+                  // do this here rather than later so we only
+                  // toggle/switch VFOs once
+                  set_dropdown (mode_A_dropdown_, lookup_mode (state ().mode (), mode_A_map_));
+                  rationalise_mode = false;
+                }
+              set_button (vfo_A_button_ >= 0 ? vfo_A_button_ : vfo_toggle_button_);
+            }
+        }
+    }
+  update_other_frequency (tx);
+
+  if (split_mode_button_ >= 0)
+    {
+      if (split_off_button_ >= 0 && !split)
+        {
+          set_button (split_off_button_);
+        }
+      else
+        {
+          set_button (split_mode_button_, split);
+        }
+    }
+  else if (split_mode_dropdown_ >= 0)
+    {
+      set_dropdown (split_mode_dropdown_, split ? split_mode_dropdown_selection_on_.front () : split_mode_dropdown_selection_off_.front ());
+    }
+  else if (vfo_A_button_ >= 0 && vfo_B_button_ >= 0 && tx_A_button_ >= 0 && tx_B_button_ >= 0)
+    {
+      if (split)
+        {
+          if (reversed_ != is_button_checked (tx_A_button_))
+            {
+              if (rx_A_button_ >= 0 && rx_B_button_ >= 0)
+                {
+                  set_button (reversed_ ? rx_B_button_ : rx_A_button_);
+                }
+              else if (receiver_dropdown_ >= 0)
+                {
+                  set_dropdown (receiver_dropdown_, (reversed_ ? rx_B_selection_ : rx_A_selection_).front ());
+                }
+              else
+                {
+                  set_button (reversed_ ? vfo_B_button_ : vfo_A_button_);
+                }
+              set_button (reversed_ ? tx_A_button_ : tx_B_button_);
+            }
+        }
+      else
+        {
+          if (reversed_ != is_button_checked (tx_B_button_))
+            {
+              if (rx_A_button_ >= 0 && rx_B_button_ >= 0)
+                {
+                  set_button (reversed_ ? rx_B_button_ : rx_A_button_);
+                }
+              else if (receiver_dropdown_ >= 0)
+                {
+                  set_dropdown (receiver_dropdown_, (reversed_ ? rx_B_selection_ : rx_A_selection_).front ());
+                }
+              else
+                {
+                  set_button (reversed_ ? vfo_B_button_ : vfo_A_button_);
+                }
+              set_button (reversed_ ? tx_B_button_ : tx_A_button_);
+            }
+        }
+    }
+  update_split (split);
+}
+
+void HRDTransceiver::do_mode (MODE mode, bool rationalise)
+{
+  TRACE_CAT (mode);
+  if (reversed_ && mode_B_dropdown_ >= 0)
+    {
+      set_dropdown (mode_B_dropdown_, lookup_mode (mode, mode_B_map_));
+    }
+  else
+    {
+      set_dropdown (mode_A_dropdown_, lookup_mode (mode, mode_A_map_));
+    }
+  if (rationalise && state ().split ()) // rationalise mode if split
+    {
+      if (reversed_)
+        {
+          if (mode_B_dropdown_ >= 0)
+            {
+              set_dropdown (mode_A_dropdown_, lookup_mode (mode, mode_A_map_));
+            }
+          else
+            {
+              Q_ASSERT ((vfo_B_button_ >= 0 && vfo_A_button_ >= 0) || vfo_toggle_button_ >= 0);
+
+              if (rx_B_button_ >= 0)
+                {
+                  set_button (rx_A_button_);
+                  set_dropdown (mode_A_dropdown_, lookup_mode (mode, mode_A_map_));
+                  set_button (rx_B_button_);
+                }
+              else if (receiver_dropdown_ >= 0)
+                {
+                  set_dropdown (receiver_dropdown_, rx_A_selection_.front ());
+                  set_dropdown (mode_A_dropdown_, lookup_mode (mode, mode_A_map_));
+                  set_dropdown (receiver_dropdown_, rx_B_selection_.front ());
+                }
+              else
+                {
+                  set_button (vfo_A_button_ >= 0 ? vfo_A_button_ : vfo_toggle_button_);
+                  set_dropdown (mode_A_dropdown_, lookup_mode (mode, mode_A_map_));
+                  set_button (vfo_B_button_ >= 0 ? vfo_B_button_ : vfo_toggle_button_);
+                }
+              if ( tx_A_button_ >= 0)
+                {
+                  set_button (tx_A_button_);
+                }
+            }
+        }
+      else
+        {
+          if (mode_B_dropdown_ >= 0)
+            {
+              set_dropdown (mode_B_dropdown_, lookup_mode (mode, mode_B_map_));
+            }
+          else
+            {
+              Q_ASSERT ((vfo_B_button_ >= 0 && vfo_A_button_ >= 0) || vfo_toggle_button_ >= 0);
+
+              if (rx_B_button_ >= 0)
+                {
+                  set_button (rx_B_button_);
+                  set_dropdown (mode_A_dropdown_, lookup_mode (mode, mode_A_map_));
+                  set_button (rx_A_button_);
+                }
+              else if (receiver_dropdown_ >= 0)
+                {
+                  set_dropdown (receiver_dropdown_, rx_B_selection_.front ());
+                  set_dropdown (mode_A_dropdown_, lookup_mode (mode, mode_A_map_));
+                  set_dropdown (receiver_dropdown_, rx_A_selection_.front ());
+                }
+              else
+                {
+                  set_button (vfo_B_button_ >= 0 ? vfo_B_button_ : vfo_toggle_button_);
+                  set_dropdown (mode_A_dropdown_, lookup_mode (mode, mode_A_map_));
+                  set_button (vfo_A_button_ >= 0 ? vfo_A_button_ : vfo_toggle_button_);
+                }
+              if ( tx_B_button_ >= 0)
+                {
+                  set_button (tx_B_button_);
+                }
+            }
+        }
+    }
+  update_mode (mode);
+}
+
+bool HRDTransceiver::is_button_checked (int button_index, bool no_debug)
+{
+  if (button_index < 0)
+    {
+      return false;
+    }
+
+  auto reply = send_command ("get button-select " + buttons_.value (button_index), no_debug);
+  if ("1" != reply && "0" != reply)
+    {
+      TRACE_CAT ("bad response");
+      throw error {tr ("Ham Radio Deluxe didn't respond as expected")};
+    }
+  return "1" == reply;
+}
+
+void HRDTransceiver::poll ()
+{
+#if WSJT_TRACE_CAT && WSJT_TRACE_CAT_POLLS
+  bool quiet {false};
+  qDebug () << "+++++++ poll dump +++++++";
+  qDebug () << "reversed:" << reversed_;
+  is_button_checked (vfo_A_button_);
+  is_button_checked (vfo_B_button_);
+  is_button_checked (vfo_toggle_button_);
+  is_button_checked (split_mode_button_);
+  is_button_checked (split_off_button_);
+  is_button_checked (rx_A_button_);
+  is_button_checked (rx_B_button_);
+  get_dropdown (receiver_dropdown_);
+  is_button_checked (tx_A_button_);
+  is_button_checked (tx_B_button_);
+  is_button_checked (ptt_button_);
+  get_dropdown (mode_A_dropdown_);
+  get_dropdown (mode_B_dropdown_);
+  if (!split_mode_dropdown_write_only_)
+    {
+      get_dropdown (split_mode_dropdown_);
+    }
+  qDebug () << "------- poll dump -------";
+#else
+  bool quiet {true};
+#endif
+
+  if (split_off_button_ >= 0)
+    {
+      // we are probably dealing with an Icom and have to guess SPLIT mode :(
+    }
+  else if (split_mode_button_ >= 0)
+    {
+      update_split (is_button_checked (split_mode_button_, quiet));
+    }
+  else if (split_mode_dropdown_ >= 0)
+    {
+      if (!split_mode_dropdown_write_only_)
+        {
+          auto selection = get_dropdown (split_mode_dropdown_, quiet);
+          if (selection >= 0)
+            {
+              update_split (selection == split_mode_dropdown_selection_on_.front ());
+            }
+          else
+            {
+              // leave split alone as we can't query it - it should be
+              // correct so long as rig or HRD haven't been changed
+              split_mode_dropdown_write_only_ = true;
+            }
+        }
+    }
+  else if (vfo_A_button_ >= 0 && vfo_B_button_ >= 0 && tx_A_button_ >= 0 && tx_B_button_ >= 0)
+    {
+      bool rx_A {true};         // no Rx taken as not reversed
+      bool rx_B {false};
+
+      auto tx_A = is_button_checked (tx_A_button_, quiet);
+
+      // some rigs have dual Rx, we take VFO A/MAIN receiving as
+      // normal and only say reversed when only VFO B/SUB is active
+      // i.e. VFO A/MAIN muted VFO B/SUB active
+      if (receiver_dropdown_ >= 0)
+        {
+          auto selection = get_dropdown (receiver_dropdown_);
+          rx_A = selection == rx_A_selection_.front ();
+          if (!rx_A)
+            {
+              rx_B = selection == rx_B_selection_.front ();
+            }
+        }
+      else if (vfo_B_button_ >= 0 || rx_B_button_ >= 0)
+        {
+          rx_A = is_button_checked (rx_A_button_ >= 0 ? rx_A_button_ : vfo_A_button_, quiet);
+          if (!rx_A)
+            {
+              rx_B = is_button_checked (rx_B_button_ >= 0 ? rx_B_button_ : vfo_B_button_, quiet);
+            }
+        }
+
+      update_split (rx_B == tx_A);
+      reversed_ = rx_B;
+    }
+
+  if (vfo_count_ > 1)
+    {
+      auto frequencies = send_command ("get frequencies", quiet).trimmed ().split ('-', QString::SkipEmptyParts);
+      update_rx_frequency (frequencies[reversed_ ? 1 : 0].toUInt ());
+      update_other_frequency (frequencies[reversed_ ? 0 : 1].toUInt ());
+    }
+  else
+    {
+      update_rx_frequency (send_command ("get frequency", quiet).toUInt ());
+    }
+
+  update_mode (lookup_mode (get_dropdown (mode_A_dropdown_, quiet), mode_A_map_));
+}
+
+QString HRDTransceiver::send_command (QString const& cmd, bool no_debug, bool prepend_context, bool recurse)
+{
+  Q_ASSERT (hrd_);
+
+  QString result;
+
+  if (current_radio_ && prepend_context && vfo_count_ < 2)
+    {
+      // required on some radios because commands don't get executed
+      // correctly otherwise (ICOM for example)
+      QThread::msleep (50);
+   }
+
+  if (!recurse && prepend_context)
+    {
+      auto radio_name = send_command ("get radio", true, current_radio_, true);
+      auto radio_iter = std::find_if (radios_.begin (), radios_.end (), [this, &radio_name] (RadioMap::value_type const& radio)
+                                      {
+                                        return std::get<1> (radio) == radio_name;
+                                      });
+      if (radio_iter == radios_.end ())
+        {
+          TRACE_CAT ("rig disappeared or changed");
+          throw error {tr ("Ham Radio Deluxe: rig has disappeared or changed")};
+        }
+
+      if (0u == current_radio_ || std::get<0> (*radio_iter) != current_radio_)
+        {
+          current_radio_ = std::get<0> (*radio_iter);
+        }
+    }
+
+  auto context = '[' + QString::number (current_radio_) + "] ";
+
+  if (QTcpSocket::ConnectedState != hrd_->state ())
+    {
+      TRACE_CAT (cmd << "failed" << hrd_->errorString ());
+      throw error {
+        tr ("Ham Radio Deluxe send command \"%1\" failed %2\n")
+          .arg (cmd)
+          .arg (hrd_->errorString ())
+          };
+    }
+
+  if (v4 == protocol_)
+    {
+      auto message = ((prepend_context ? context + cmd : cmd) + "\r").toLocal8Bit ();
+      if (!write_to_port (message.constData (), message.size ()))
+        {
+          TRACE_CAT ("failed to write command" << cmd << "to HRD");
+          throw error {
+            tr ("Ham Radio Deluxe: failed to write command \"%1\"")
+              .arg (cmd)
+              };
+        }
+    }
+  else
+    {
+      auto string = prepend_context ? context + cmd : cmd;
+      QScopedPointer<HRDMessage> message {new (string) HRDMessage};
+      if (!write_to_port (reinterpret_cast<char const *> (message.data ()), message->size_))
+        {
+          TRACE_CAT ("failed to write command" << cmd << "to HRD");
+          throw error {
+            tr ("Ham Radio Deluxe: failed to write command \"%1\"")
+              .arg (cmd)
+              };
+        }
+    }
+  auto buffer = read_reply (cmd);
+  if (v4 == protocol_)
+    {
+      result = QString {buffer}.trimmed ();
+    }
+  else
+    {
+      HRDMessage const * reply {new (buffer) HRDMessage};
+      if (reply->magic_1_value_ != reply->magic_1_ && reply->magic_2_value_ != reply->magic_2_)
+        {
+          TRACE_CAT (cmd << "invalid reply");
+          throw error {
+            tr ("Ham Radio Deluxe sent an invalid reply to our command \"%1\"")
+              .arg (cmd)
+              };
+        }
+
+      // keep reading until expected size arrives
+      while (buffer.size () - offsetof (HRDMessage, size_) < reply->size_)
+        {
+          if (!no_debug)
+            {
+              TRACE_CAT (cmd << "reading more reply data");
+            }
+          buffer += read_reply (cmd);
+          reply = new (buffer) HRDMessage;
+        }
+
+      result = QString {reply->payload_}; // this is not a memory leak (honest!)
+    }
+  if (!no_debug)
+    {
+      TRACE_CAT (cmd << " ->" << result);
+    }
+  return result;
+}
+
+bool HRDTransceiver::write_to_port (char const * data, qint64 length)
+{
+  qint64 total_bytes_sent {0};
+  while (total_bytes_sent < length)
+    {
+      auto bytes_sent = hrd_->write (data + total_bytes_sent, length - total_bytes_sent);
+      if (bytes_sent < 0 || !hrd_->waitForBytesWritten ())
+        {
+          return false;
+        }
+
+      total_bytes_sent += bytes_sent;
+    }
+  return true;
+}
+
+QByteArray HRDTransceiver::read_reply (QString const& cmd)
+{
+  // waitForReadReady appears to be occasionally unreliable on Windows
+  // timing out when data is waiting so retry a few times
+  unsigned retries {3};
+  bool replied {false};
+  while (!replied && retries--)
+    {
+      replied = hrd_->waitForReadyRead ();
+      if (!replied && hrd_->error () != hrd_->SocketTimeoutError)
+        {
+          TRACE_CAT (cmd << "failed to reply" << hrd_->errorString ());
+          throw error {
+            tr ("Ham Radio Deluxe failed to reply to command \"%1\" %2\n")
+              .arg (cmd)
+              .arg (hrd_->errorString ())
+              };
+        }
+    }
+  if (!replied)
+    {
+      TRACE_CAT (cmd << "retries exhausted");
+      throw error {
+        tr ("Ham Radio Deluxe retries exhausted sending command \"%1\"")
+          .arg (cmd)
+          };
+    }
+  return hrd_->readAll ();
+}
+
+void HRDTransceiver::send_simple_command (QString const& command, bool no_debug)
+{
+  if ("OK" != send_command (command, no_debug))
+    {
+      TRACE_CAT (command << "unexpected response");
+      throw error {
+        tr ("Ham Radio Deluxe didn't respond to command \"%1\" as expected")
+          .arg (command)
+          };
+    }
+}
diff --git a/HRDTransceiver.hpp b/HRDTransceiver.hpp
new file mode 100644
index 0000000..87a9a43
--- /dev/null
+++ b/HRDTransceiver.hpp
@@ -0,0 +1,179 @@
+#ifndef HRD_TRANSCEIVER_HPP__
+#define HRD_TRANSCEIVER_HPP__
+
+#include <vector>
+#include <tuple>
+#include <memory>
+
+#include <QScopedPointer>
+#include <QString>
+#include <QStringList>
+
+#include "TransceiverFactory.hpp"
+#include "PollingTransceiver.hpp"
+
+class QRegExp;
+class QTcpSocket;
+class QByteArray;
+
+//
+// Ham Radio Deluxe Transceiver Interface
+//
+// Implemented as a Transceiver decorator  because we may want the PTT
+// services of another Transceiver  type such as the HamlibTransceiver
+// which can  be enabled by wrapping  a HamlibTransceiver instantiated
+// as a "Hamlib Dummy" transceiver in the Transceiver factory method.
+//
+class HRDTransceiver final
+  : public PollingTransceiver
+{
+public:
+  static void register_transceivers (TransceiverFactory::Transceivers *, int id);
+
+  // takes ownership of wrapped Transceiver
+  explicit HRDTransceiver (std::unique_ptr<TransceiverBase> wrapped
+                           , QString const& server
+                           , bool use_for_ptt
+                           , int poll_interval);
+  ~HRDTransceiver ();
+
+protected:
+  // Implement the TransceiverBase interface.
+  void do_start () override;
+  void do_stop () override;
+  void do_frequency (Frequency, MODE) override;
+  void do_tx_frequency (Frequency, bool rationalise_mode) override;
+  void do_mode (MODE, bool rationalise) override;
+  void do_ptt (bool on) override;
+
+  // Implement the PollingTransceiver interface.
+  void poll () override;
+
+private:
+  QString send_command (QString const&, bool no_debug = false, bool prepend_context = true, bool recurse = false);
+  QByteArray read_reply (QString const& command);
+  void send_simple_command (QString const&, bool no_debug = false);
+  bool write_to_port (char const *, qint64 length);
+  int find_button (QRegExp const&) const;
+  int find_dropdown (QRegExp const&) const;
+  std::vector<int> find_dropdown_selection (int dropdown, QRegExp const&) const;
+  int get_dropdown (int, bool no_debug = false);
+  void set_dropdown (int, int);
+  void set_button (int button_index, bool checked = true);
+  bool is_button_checked (int button_index, bool no_debug = false);
+
+  // This dictionary type maps Transceiver::MODE to a list of mode
+  // drop down selection indexes that equate to that mode.  It is used
+  // to map internal MODE values to HRD drop down selections and vice
+  // versa.
+  using ModeMap = std::vector<std::tuple<MODE, std::vector<int> > >;
+
+  void map_modes (int dropdown, ModeMap *);
+  int lookup_mode (MODE, ModeMap const&) const;
+  MODE lookup_mode (int, ModeMap const&) const;
+
+  // An alternate TransceiverBase instance that can be used to drive
+  // PTT if required.
+  std::unique_ptr<TransceiverBase> wrapped_;
+
+  bool use_for_ptt_;            // Use HRD for PTT.
+
+  QString server_;              // The TCP/IP addrress and port for
+                                // the HRD server.
+
+  QTcpSocket * hrd_;            // The TCP/IP client that links to the
+                                // HRD server.
+
+  enum {none, v4, v5} protocol_; // The HRD protocol that has been
+                                 // detected.
+
+  using RadioMap = std::vector<std::tuple<unsigned, QString> >;
+
+  RadioMap radios_;             // Dictionary of available radios.
+
+  unsigned current_radio_;      // The current addressed radio.
+
+  unsigned vfo_count_;          // How many VFOs are supported.
+
+  QStringList buttons_;         // The buttons available to click.
+
+  QStringList dropdown_names_;  // The names of drop down selectors
+                                // available.
+
+  QMap<QString, QStringList> dropdowns_; // Dictionary of available
+                                         // drop down selections.
+
+  QStringList slider_names_;    // The name of available sliders.
+
+  QMap<QString, QStringList> sliders_; // Dictionary of available
+                                // slider ranges.
+
+  int vfo_A_button_;            // The button we use to select VFO
+                                // A. May be -1 if none available.
+
+  int vfo_B_button_;            // Index of button we use to select
+                                // VFO B. May be -1 if none available.
+
+  int vfo_toggle_button_;       // Index of button we use to toggle
+                                // the VFOs. Use this if VFO A and VFO
+                                // B selection are not available.
+
+  int mode_A_dropdown_;         // Index of the mode drop down for VFO
+                                // A.
+
+  ModeMap mode_A_map_;          // The map of modes available for VFO
+                                // A.
+
+  int mode_B_dropdown_;         // The drop down index for VFO B mode
+                                // setting. May be -1 if independent
+                                // VFO mode setting not available.
+
+  ModeMap mode_B_map_;          // The map of modes for VFO B.
+
+  int split_mode_button_;       // Button to use to select split
+                                // operation. May be -1 if no button
+                                // is available.
+
+  int split_mode_dropdown_;     // The drop down index that allows
+                                // split mode to be turned on and
+                                // off. May be -1 if no such drop down
+                                // exists.
+
+  bool split_mode_dropdown_write_only_; // Some rigs cannot report
+                                        // split status.
+
+  std::vector<int> split_mode_dropdown_selection_on_; // The drop down
+                                                      // selection to
+                                                      // turn on
+                                                      // split.
+
+  std::vector<int> split_mode_dropdown_selection_off_; // The drop
+                                                       // down
+                                                       // selection to
+                                                       // disable
+                                                       // split.
+
+  int split_off_button_;        // The button to turn off split mode.
+
+  int tx_A_button_;             // The button to transmit on VFO A.
+
+  int tx_B_button_;             // The button to transmit on VFO B.
+
+  int rx_A_button_;             // The button to receive on VFO A
+                                // A. May be -1 if none available.
+
+  int rx_B_button_;             // The button to receive on VFO B
+                                // May be -1 if none available.
+
+  int receiver_dropdown_;       // Select receiver
+
+  std::vector<int> rx_A_selection_;
+
+  std::vector<int> rx_B_selection_;
+
+  int ptt_button_;              // The button to toggle PTT.
+
+  bool reversed_;               // True if VFOs are reversed.
+};
+
+#endif
diff --git a/HamlibTransceiver.cpp b/HamlibTransceiver.cpp
new file mode 100644
index 0000000..fcad237
--- /dev/null
+++ b/HamlibTransceiver.cpp
@@ -0,0 +1,874 @@
+#include "HamlibTransceiver.hpp"
+
+#include <cstring>
+
+#include <QByteArray>
+#include <QString>
+#include <QDebug>
+
+#include "moc_HamlibTransceiver.cpp"
+
+namespace
+{
+  // Unfortunately bandwidth is conflated  with mode, this is probably
+  // because Icom do  the same. So we have to  care about bandwidth if
+  // we want  to set  mode otherwise we  will end up  setting unwanted
+  // bandwidths every time we change mode.  The best we can do via the
+  // Hamlib API is to request the  normal option for the mode and hope
+  // that an appropriate filter is selected.  Also ensure that mode is
+  // only set is absolutely necessary.  On Icoms (and probably others)
+  // the filter is  selected by number without checking  the actual BW
+  // so unless the  "normal" defaults are set on the  rig we won't get
+  // desirable results.
+  //
+  // As  an ultimate  workaround make  sure  the user  always has  the
+  // option to skip mode setting altogether.
+
+  // reroute Hamlib diagnostic messages to Qt
+  int debug_callback (enum rig_debug_level_e level, rig_ptr_t /* arg */, char const * format, va_list ap)
+  {
+    QString message;
+    static char const fmt[] = "Hamlib: %s";
+    message = message.vsprintf (format, ap).trimmed ();
+
+    switch (level)
+      {
+      case RIG_DEBUG_BUG:
+        qFatal (fmt, message.toLocal8Bit ().data ());
+        break;
+
+      case RIG_DEBUG_ERR:
+        qCritical (fmt, message.toLocal8Bit ().data ());
+        break;
+
+      case RIG_DEBUG_WARN:
+        qWarning (fmt, message.toLocal8Bit ().data ());
+        break;
+
+      default:
+        qDebug (fmt, message.toLocal8Bit ().data ());
+        break;
+      }
+
+    return 0;
+  }
+
+  // callback function that receives transceiver capabilities from the
+  // hamlib libraries
+  int rigCallback (rig_caps const * caps, void * callback_data)
+  {
+    TransceiverFactory::Transceivers * rigs = reinterpret_cast<TransceiverFactory::Transceivers *> (callback_data);
+
+    QString key;
+    if (RIG_MODEL_DUMMY == caps->rig_model)
+      {
+        key = TransceiverFactory::basic_transceiver_name_;
+      }
+    else
+      {
+        key = QString::fromLatin1 (caps->mfg_name).trimmed ()
+          + ' '+ QString::fromLatin1 (caps->model_name).trimmed ()
+          // + ' '+ QString::fromLatin1 (caps->version).trimmed ()
+          // + " (" + QString::fromLatin1 (rig_strstatus (caps->status)).trimmed () + ')'
+          ;
+      }
+
+    auto port_type = TransceiverFactory::Capabilities::none;
+    switch (caps->port_type)
+      {
+      case RIG_PORT_SERIAL:
+        port_type = TransceiverFactory::Capabilities::serial;
+        break;
+
+      case RIG_PORT_NETWORK:
+        port_type = TransceiverFactory::Capabilities::network;
+        break;
+
+      default: break;
+      }
+    (*rigs)[key] = TransceiverFactory::Capabilities (caps->rig_model
+                                                     , port_type
+                                                     , RIG_MODEL_DUMMY != caps->rig_model
+                                                     && (RIG_PTT_RIG == caps->ptt_type
+                                                         || RIG_PTT_RIG_MICDATA == caps->ptt_type)
+                                                     , RIG_PTT_RIG_MICDATA == caps->ptt_type);
+
+    return 1;			// keep them coming
+  }
+
+  // int frequency_change_callback (RIG * /* rig */, vfo_t vfo, freq_t f, rig_ptr_t arg)
+  // {
+  //   (void)vfo;			// unused in release build
+
+  //   Q_ASSERT (vfo == RIG_VFO_CURR); // G4WJS: at the time of writing only current VFO is signalled by hamlib
+
+  //   HamlibTransceiver * transceiver (reinterpret_cast<HamlibTransceiver *> (arg));
+  //   Q_EMIT transceiver->frequency_change (f, Transceiver::A);
+  //   return RIG_OK;
+  // }
+
+  class hamlib_tx_vfo_fixup final
+  {
+  public:
+    hamlib_tx_vfo_fixup (RIG * rig, vfo_t tx_vfo)
+      : rig_ {rig}
+    {
+      original_vfo_ = rig_->state.tx_vfo;
+      rig_->state.tx_vfo = tx_vfo;
+    }
+
+    ~hamlib_tx_vfo_fixup ()
+    {
+      rig_->state.tx_vfo = original_vfo_;
+    }
+
+  private:
+    RIG * rig_;
+    vfo_t original_vfo_;
+  };
+}
+
+freq_t HamlibTransceiver::dummy_frequency_;
+rmode_t HamlibTransceiver::dummy_mode_ {RIG_MODE_NONE};
+
+void HamlibTransceiver::register_transceivers (TransceiverFactory::Transceivers * registry)
+{
+  rig_set_debug_callback (debug_callback, nullptr);
+
+#if WSJT_HAMLIB_TRACE
+#if WSJT_HAMLIB_VERBOSE_TRACE
+  rig_set_debug (RIG_DEBUG_TRACE);
+#else
+  rig_set_debug (RIG_DEBUG_VERBOSE);
+#endif
+#elif defined (NDEBUG)
+  rig_set_debug (RIG_DEBUG_ERR);
+#else
+  rig_set_debug (RIG_DEBUG_WARN);
+#endif
+
+  rig_load_all_backends ();
+  rig_list_foreach (rigCallback, registry);
+}
+
+void HamlibTransceiver::RIGDeleter::cleanup (RIG * rig)
+{
+  if (rig)
+    {
+      // rig->state.obj = 0;
+      rig_cleanup (rig);
+    }
+}
+
+HamlibTransceiver::HamlibTransceiver (TransceiverFactory::PTTMethod ptt_type, QString const& ptt_port)
+  : PollingTransceiver {0}
+  , rig_ {rig_init (RIG_MODEL_DUMMY)}
+  , back_ptt_port_ {false}
+  , is_dummy_ {true}
+  , reversed_ {false}
+  , split_query_works_ {true}
+  , get_vfo_works_ {true}
+{
+  if (!rig_)
+    {
+      throw error {tr ("Hamlib initialisation error")};
+    }
+
+  switch (ptt_type)
+    {
+    case TransceiverFactory::PTT_method_VOX:
+      set_conf ("ptt_type", "None");
+      break;
+
+    case TransceiverFactory::PTT_method_CAT:
+      // Use the default PTT_TYPE for the rig (defined in the Hamlib
+      // rig back-end capabilities).
+      break;
+
+    case TransceiverFactory::PTT_method_DTR:
+    case TransceiverFactory::PTT_method_RTS:
+      if (!ptt_port.isEmpty ())
+        {
+#if defined (WIN32)
+          set_conf ("ptt_pathname", ("\\\\.\\" + ptt_port).toLatin1 ().data ());
+#else
+          set_conf ("ptt_pathname", ptt_port.toLatin1 ().data ());
+#endif
+        }
+
+      if (TransceiverFactory::PTT_method_DTR == ptt_type)
+        {
+          set_conf ("ptt_type", "DTR");
+        }
+      else
+        {
+          set_conf ("ptt_type", "RTS");
+        }
+    }
+}
+
+HamlibTransceiver::HamlibTransceiver (int model_number, TransceiverFactory::ParameterPack const& params)
+  : PollingTransceiver {params.poll_interval}
+  , rig_ {rig_init (model_number)}
+  , back_ptt_port_ {TransceiverFactory::TX_audio_source_rear == params.audio_source}
+  , is_dummy_ {RIG_MODEL_DUMMY == model_number}
+  , reversed_ {false}
+  , split_query_works_ {true}
+  , tickle_hamlib_ {false}
+  , get_vfo_works_ {true}
+{
+  if (!rig_)
+    {
+      throw error {tr ("Hamlib initialisation error")};
+    }
+
+  // rig_->state.obj = this;
+
+  if (RIG_MODEL_DUMMY != model_number)
+    {
+      switch (rig_->caps->port_type)
+        {
+        case RIG_PORT_SERIAL:
+          if (!params.serial_port.isEmpty ())
+            {
+              set_conf ("rig_pathname", params.serial_port.toLatin1 ().data ());
+            }
+          break;
+
+        case RIG_PORT_NETWORK:
+          if (!params.network_port.isEmpty ())
+            {
+              set_conf ("rig_pathname", params.network_port.toLatin1 ().data ());
+            }
+          break;
+
+        default:
+          throw error {tr ("Unsupported CAT type")};
+          break;
+        }
+
+      set_conf ("serial_speed", QByteArray::number (params.baud).data ());
+      set_conf ("data_bits", TransceiverFactory::seven_data_bits == params.data_bits ? "7" : "8");
+      set_conf ("stop_bits", TransceiverFactory::one_stop_bit == params.stop_bits ? "1" : "2");
+
+      switch (params.handshake)
+        {
+        case TransceiverFactory::handshake_none: set_conf ("serial_handshake", "None"); break;
+        case TransceiverFactory::handshake_XonXoff: set_conf ("serial_handshake", "XONXOFF"); break;
+        case TransceiverFactory::handshake_hardware: set_conf ("serial_handshake", "Hardware"); break;
+        }
+
+      if (params.force_line_control)
+        {
+          set_conf ("dtr_state", params.dtr_high ? "ON" : "OFF");
+          set_conf ("rts_state", params.rts_high ? "ON" : "OFF");
+        }
+    }
+
+  switch (params.ptt_type)
+    {
+    case TransceiverFactory::PTT_method_VOX:
+      set_conf ("ptt_type", "None");
+      break;
+
+    case TransceiverFactory::PTT_method_CAT:
+      // Use the default PTT_TYPE for the rig (defined in the Hamlib
+      // rig back-end capabilities).
+      break;
+
+    case TransceiverFactory::PTT_method_DTR:
+    case TransceiverFactory::PTT_method_RTS:
+      if (!params.ptt_port.isEmpty ()
+          && params.ptt_port != "None"
+          && (RIG_MODEL_DUMMY == model_number
+              || params.ptt_port != params.serial_port))
+        {
+#if defined (WIN32)
+          set_conf ("ptt_pathname", ("\\\\.\\" + params.ptt_port).toLatin1 ().data ());
+#else
+          set_conf ("ptt_pathname", params.ptt_port.toLatin1 ().data ());
+#endif
+        }
+
+      if (TransceiverFactory::PTT_method_DTR == params.ptt_type)
+        {
+          set_conf ("ptt_type", "DTR");
+        }
+      else
+        {
+          set_conf ("ptt_type", "RTS");
+        }
+    }
+
+  // Make Icom CAT split commands less glitchy
+  set_conf ("no_xchg", "1");
+
+  // would be nice to get events but not supported on Windows and also not on a lot of rigs
+  // rig_set_freq_callback (rig_.data (), &frequency_change_callback, this);
+}
+
+HamlibTransceiver::~HamlibTransceiver ()
+{
+}
+
+void HamlibTransceiver::error_check (int ret_code, QString const& doing) const
+{
+  if (RIG_OK != ret_code)
+    {
+      TRACE_CAT_POLL ("error:" << rigerror (ret_code));
+      throw error {tr ("Hamlib error: %1 while %2").arg (rigerror (ret_code)).arg (doing)};
+    }
+}
+
+void HamlibTransceiver::do_start ()
+{
+  TRACE_CAT (QString::fromLatin1 (rig_->caps->mfg_name).trimmed () << QString::fromLatin1 (rig_->caps->model_name).trimmed ());
+
+  error_check (rig_open (rig_.data ()), tr ("opening connection to rig"));
+
+  // the Net rigctl back end promises all functions work but we must
+  // test get_vfo as it determines our strategy for Icom rigs
+  vfo_t vfo;
+  int rc = rig_get_vfo (rig_.data (), &vfo);
+  if (-RIG_ENAVAIL == rc || -RIG_ENIMPL == rc)
+    {
+      get_vfo_works_ = false;
+    }
+  else
+    {
+      error_check (rc, "getting current VFO");
+    }
+
+  if (!is_dummy_ && rig_->caps->set_split_vfo) // if split is possible
+                                               // do some extra setup
+    {
+      freq_t f1;
+      freq_t f2;
+      rmode_t m {RIG_MODE_USB};
+      rmode_t mb;
+      pbwidth_t w {RIG_PASSBAND_NORMAL};
+      pbwidth_t wb;
+      if ((!get_vfo_works_ || !rig_->caps->get_vfo)
+          && (rig_->caps->set_vfo || rig_has_vfo_op (rig_.data (), RIG_OP_TOGGLE)))
+        {
+          // Icom have deficient CAT protocol with no way of reading which
+          // VFO is selected or if SPLIT is selected so we have to simply
+          // assume it is as when we started by setting at open time right
+          // here. We also gather/set other initial state.
+          error_check (rig_get_freq (rig_.data (), RIG_VFO_CURR, &f1), tr ("getting current frequency"));
+          TRACE_CAT ("current frequency =" << f1);
+
+          error_check (rig_get_mode (rig_.data (), RIG_VFO_CURR, &m, &w), tr ("getting current mode"));
+          TRACE_CAT ("current mode =" << rig_strrmode (m) << "bw =" << w);
+
+          if (!rig_->caps->set_vfo)
+            {
+              TRACE_CAT ("rig_vfo_op TOGGLE");
+              error_check (rig_vfo_op (rig_.data (), RIG_VFO_CURR, RIG_OP_TOGGLE), tr ("exchanging VFOs"));
+            }
+          else
+            {
+              TRACE_CAT ("rig_set_vfo to other VFO");
+              error_check (rig_set_vfo (rig_.data (), rig_->state.vfo_list & RIG_VFO_B ? RIG_VFO_B : RIG_VFO_SUB), tr ("setting current VFO"));
+            }
+
+          error_check (rig_get_freq (rig_.data (), RIG_VFO_CURR, &f2), tr ("getting other VFO frequency"));
+          TRACE_CAT ("rig_get_freq other frequency =" << f2);
+
+          error_check (rig_get_mode (rig_.data (), RIG_VFO_CURR, &mb, &wb), tr ("getting other VFO mode"));
+          TRACE_CAT ("rig_get_mode other mode =" << rig_strrmode (mb) << "bw =" << wb);
+
+          update_other_frequency (f2);
+
+          if (!rig_->caps->set_vfo)
+            {
+              TRACE_CAT ("rig_vfo_op TOGGLE");
+              error_check (rig_vfo_op (rig_.data (), RIG_VFO_CURR, RIG_OP_TOGGLE), tr ("exchanging VFOs"));
+            }
+          else
+            {
+              TRACE_CAT ("rig_set_vfo A/MAIN");
+              error_check (rig_set_vfo (rig_.data (), rig_->state.vfo_list & RIG_VFO_A ? RIG_VFO_A : RIG_VFO_MAIN), tr ("setting current VFO"));
+            }
+
+          if (f1 != f2 || m != mb || w != wb)	// we must have started with MAIN/A
+            {
+              update_rx_frequency (f1);
+            }
+          else
+            {
+              error_check (rig_get_freq (rig_.data (), RIG_VFO_CURR, &f1), tr ("getting frequency"));
+              TRACE_CAT ("rig_get_freq frequency =" << f1);
+
+              error_check (rig_get_mode (rig_.data (), RIG_VFO_CURR, &m, &w), tr ("getting mode"));
+              TRACE_CAT ("rig_get_mode mode =" << rig_strrmode (m) << "bw =" << w);
+
+              update_rx_frequency (f1);
+            }
+
+          // TRACE_CAT ("rig_set_split_vfo split off");
+          // error_check (rig_set_split_vfo (rig_.data (), RIG_VFO_CURR, RIG_SPLIT_OFF, RIG_VFO_CURR), tr ("setting split off"));
+          // update_split (false);
+        }
+      else
+        {
+          vfo_t v {RIG_VFO_A};  // assume RX always on VFO A/MAIN
+
+          if (get_vfo_works_ && rig_->caps->get_vfo)
+            {
+              error_check (rig_get_vfo (rig_.data (), &v), tr ("getting current VFO")); // has side effect of establishing current VFO inside hamlib
+              TRACE_CAT ("rig_get_vfo current VFO = " << rig_strvfo (v));
+            }
+
+          reversed_ = RIG_VFO_B == v;
+
+          if (!(rig_->caps->targetable_vfo & (RIG_TARGETABLE_MODE | RIG_TARGETABLE_PURE)))
+            {
+              error_check (rig_get_mode (rig_.data (), RIG_VFO_CURR, &m, &w), tr ("getting current mode"));
+              TRACE_CAT ("rig_get_mode current mode =" << rig_strrmode (m) << "bw =" << w);
+            }
+        }
+      update_mode (map_mode (m));
+    }
+
+  tickle_hamlib_ = true;
+
+  if (is_dummy_ && dummy_frequency_)
+    {
+      // return to where last dummy instance was
+      // TODO: this is going to break down if multiple dummy rigs are used
+      rig_set_freq (rig_.data (), RIG_VFO_CURR, dummy_frequency_);
+      update_rx_frequency (dummy_frequency_);
+      if (RIG_MODE_NONE != dummy_mode_)
+        {
+          rig_set_mode (rig_.data (), RIG_VFO_CURR, dummy_mode_, RIG_PASSBAND_NORMAL);
+          update_mode (map_mode (dummy_mode_));
+        }
+    }
+
+  poll ();
+
+  TRACE_CAT ("exit" << state () << "reversed =" << reversed_);
+}
+
+void HamlibTransceiver::do_stop ()
+{
+  if (is_dummy_)
+    {
+      rig_get_freq (rig_.data (), RIG_VFO_CURR, &dummy_frequency_);
+      pbwidth_t width;
+      rig_get_mode (rig_.data (), RIG_VFO_CURR, &dummy_mode_, &width);
+    }
+  if (rig_)
+    {
+      rig_close (rig_.data ());
+    }
+
+  TRACE_CAT ("state:" << state () << "reversed =" << reversed_);
+}
+
+auto HamlibTransceiver::get_vfos () const -> std::tuple<vfo_t, vfo_t>
+{
+  if (get_vfo_works_ && rig_->caps->get_vfo)
+    {
+      vfo_t v;
+      error_check (rig_get_vfo (rig_.data (), &v), tr ("getting current VFO")); // has side effect of establishing current VFO inside hamlib
+      TRACE_CAT ("rig_get_vfo VFO = " << rig_strvfo (v));
+
+      reversed_ = RIG_VFO_B == v;
+    }
+  else if (rig_->caps->set_vfo && rig_->caps->set_split_vfo)
+    {
+      // use VFO A/MAIN for main frequency and B/SUB for Tx
+      // frequency if split since these type of radios can only
+      // support this way around
+
+      TRACE_CAT ("rig_set_vfo VFO = A/MAIN");
+      error_check (rig_set_vfo (rig_.data (), rig_->state.vfo_list & RIG_VFO_A ? RIG_VFO_A : RIG_VFO_MAIN), tr ("setting current VFO"));
+    }
+  // else only toggle available but both VFOs should be substitutable 
+
+  auto rx_vfo = rig_->state.vfo_list & RIG_VFO_A ? RIG_VFO_A : RIG_VFO_MAIN;
+  auto tx_vfo = !is_dummy_ && state ().split ()
+    ? (rig_->state.vfo_list & RIG_VFO_B ? RIG_VFO_B : RIG_VFO_SUB)
+    : rx_vfo;
+  if (reversed_)
+    {
+      TRACE_CAT ("reversing VFOs");
+      std::swap (rx_vfo, tx_vfo);
+    }
+
+  TRACE_CAT ("RX VFO = " << rig_strvfo (rx_vfo) << " TX VFO = " << rig_strvfo (tx_vfo));
+  return std::make_tuple (rx_vfo, tx_vfo);
+}
+
+void HamlibTransceiver::do_frequency (Frequency f, MODE m)
+{
+  TRACE_CAT (f << "mode:" << m << "reversed:" << reversed_);
+
+  // for the 1st time as a band change may cause a recalled mode to be
+  // set
+  error_check (rig_set_freq (rig_.data (), RIG_VFO_CURR, f), tr ("setting frequency"));
+
+  if (UNK != m)
+    {
+      do_mode (m, false);
+
+      // for the 2nd time because a mode change may have caused a
+      // frequency change
+      error_check (rig_set_freq (rig_.data (), RIG_VFO_CURR, f), tr ("setting frequency"));
+
+      // for the second time because some rigs change mode according
+      // to frequency such as the TS-2000 auto mode setting
+      do_mode (m, false);
+    }
+
+  update_rx_frequency (f);
+}
+
+void HamlibTransceiver::do_tx_frequency (Frequency tx, bool rationalise_mode)
+{
+  TRACE_CAT (tx << "rationalise mode:" << rationalise_mode << "reversed:" << reversed_);
+
+  if (!is_dummy_)               // split is meaning less if you can't
+                                // see it
+    {
+      auto split = tx ? RIG_SPLIT_ON : RIG_SPLIT_OFF;
+      update_split (tx);
+      auto vfos = get_vfos ();
+      // auto rx_vfo = std::get<0> (vfos); // or use RIG_VFO_CURR
+      auto tx_vfo = std::get<1> (vfos);
+
+      if (tx)
+        {
+          // Doing set split for the 1st of two times, this one
+          // ensures that the internal Hamlib state is correct
+          // otherwise rig_set_split_freq() will target the wrong VFO
+          // on some rigs
+
+          if (tickle_hamlib_)
+            {
+              // This potentially causes issues with the Elecraft K3
+              // which will block setting split mode when it deems
+              // cross mode split operation not possible. There's not
+              // much we can do since the Hamlib Library needs this
+              // call at least once to establish the Tx VFO. Best we
+              // can do is only do this once per session.
+              TRACE_CAT ("rig_set_split_vfo split =" << split);
+              auto rc = rig_set_split_vfo (rig_.data (), RIG_VFO_CURR, split, tx_vfo);
+              if (tx || (-RIG_ENAVAIL != rc && -RIG_ENIMPL != rc))
+                {
+                  // On rigs that can't have split controlled only throw an
+                  // exception when an error other than command not accepted
+                  // is returned when trying to leave split mode. This allows
+                  // fake split mode and non-split mode to work without error
+                  // on such rigs without having to know anything about the
+                  // specific rig.
+                  error_check (rc, tr ("setting/unsetting split mode"));
+                }
+
+              tickle_hamlib_ = false;
+            }
+
+          hamlib_tx_vfo_fixup fixup (rig_.data (), tx_vfo);
+          // do this before setting the mode because changing band may
+          // recall the last mode used on the target band
+          error_check (rig_set_split_freq (rig_.data (), RIG_VFO_CURR, tx), tr ("setting split TX frequency"));
+
+          if (rationalise_mode)
+            {
+              rmode_t current_mode;
+              pbwidth_t current_width;
+
+              error_check (rig_get_split_mode (rig_.data (), RIG_VFO_CURR, &current_mode, &current_width), tr ("getting mode of split TX VFO"));
+              TRACE_CAT ("rig_get_split_mode mode = " << rig_strrmode (current_mode) << "bw =" << current_width);
+
+              auto new_mode = map_mode (state ().mode ());
+              if (new_mode != current_mode)
+                {
+                  TRACE_CAT ("rig_set_split_mode mode = " << rig_strrmode (new_mode));
+                  error_check (rig_set_split_mode (rig_.data (), RIG_VFO_CURR, new_mode, RIG_PASSBAND_NORMAL), tr ("setting split TX VFO mode"));
+
+                  // do this again as setting the mode may change the frequency
+                  error_check (rig_set_split_freq (rig_.data (), RIG_VFO_CURR, tx), tr ("setting split TX frequency"));
+                }
+            }
+        }
+
+      // Enable split last since some rigs (Kenwood for one) come out
+      // of split when you switch RX VFO (to set split mode above for
+      // example). Also the Elecraft K3 will refuse to go to split
+      // with certain VFO A/B mode combinations.
+      TRACE_CAT ("rig_set_split_vfo split =" << split);
+      auto rc = rig_set_split_vfo (rig_.data (), RIG_VFO_CURR, split, tx_vfo);
+      if (tx || (-RIG_ENAVAIL != rc && -RIG_ENIMPL != rc))
+        {
+          // On rigs that can't have split controlled only throw an
+          // exception when an error other than command not accepted
+          // is returned when trying to leave split mode. This allows
+          // fake split mode and non-split mode to work without error
+          // on such rigs without having to know anything about the
+          // specific rig.
+          error_check (rc, tr ("setting/unsetting split mode"));
+        }
+
+      update_other_frequency (tx);
+    }
+}
+
+void HamlibTransceiver::do_mode (MODE mode, bool rationalise)
+{
+  TRACE_CAT (mode << "rationalise:" << rationalise);
+
+  auto vfos = get_vfos ();
+  // auto rx_vfo = std::get<0> (vfos);
+  auto tx_vfo = std::get<1> (vfos);
+
+  rmode_t current_mode;
+  pbwidth_t current_width;
+
+  error_check (rig_get_mode (rig_.data (), RIG_VFO_CURR, &current_mode, &current_width), tr ("getting current VFO mode"));
+  TRACE_CAT ("rig_get_mode mode = " << rig_strrmode (current_mode) << "bw =" << current_width);
+
+  auto new_mode = map_mode (mode);
+  if (new_mode != current_mode)
+    {
+      TRACE_CAT ("rig_set_mode mode = " << rig_strrmode (new_mode));
+      error_check (rig_set_mode (rig_.data (), RIG_VFO_CURR, new_mode, RIG_PASSBAND_NORMAL), tr ("setting current VFO mode"));
+    }
+      
+  if (!is_dummy_ && state ().split () && rationalise)
+    {
+      error_check (rig_get_split_mode (rig_.data (), RIG_VFO_CURR, &current_mode, &current_width), tr ("getting split TX VFO mode"));
+      TRACE_CAT ("rig_get_split_mode mode = " << rig_strrmode (current_mode) << "bw =" << current_width);
+
+      if (new_mode != current_mode)
+        {
+          TRACE_CAT ("rig_set_split_mode mode = " << rig_strrmode (new_mode));
+          hamlib_tx_vfo_fixup fixup (rig_.data (), tx_vfo);
+          error_check (rig_set_split_mode (rig_.data (), RIG_VFO_CURR, new_mode, RIG_PASSBAND_NORMAL), tr ("setting split TX VFO mode"));
+        }
+    }
+  update_mode (mode);
+}
+
+void HamlibTransceiver::poll ()
+{
+#if !WSJT_TRACE_CAT_POLLS
+#if defined (NDEBUG)
+  rig_set_debug (RIG_DEBUG_ERR);
+#else
+  rig_set_debug (RIG_DEBUG_WARN);
+#endif
+#endif
+
+  freq_t f;
+  rmode_t m;
+  pbwidth_t w;
+  split_t s;
+
+  if (get_vfo_works_ && rig_->caps->get_vfo)
+    {
+      vfo_t v;
+      error_check (rig_get_vfo (rig_.data (), &v), tr ("getting current VFO")); // has side effect of establishing current VFO inside hamlib
+      TRACE_CAT_POLL ("VFO =" << rig_strvfo (v));
+      reversed_ = RIG_VFO_B == v;
+    }
+
+  error_check (rig_get_freq (rig_.data (), RIG_VFO_CURR, &f), tr ("getting current VFO frequency"));
+  TRACE_CAT_POLL ("rig_get_freq frequency =" << f);
+  update_rx_frequency (f);
+
+  if (!is_dummy_ && state ().split () && (rig_->caps->targetable_vfo & (RIG_TARGETABLE_FREQ | RIG_TARGETABLE_PURE)))
+    {
+      // only read "other" VFO if in split, this allows rigs like
+      // FlexRadio to work in Kenwood TS-2000 mode despite them
+      // not having a FB; command
+
+      // we can only probe current VFO unless rig supports reading
+      // the other one directly because we can't glitch the Rx
+      error_check (rig_get_freq (rig_.data ()
+                                 , reversed_
+                                 ? (rig_->state.vfo_list & RIG_VFO_A ? RIG_VFO_A : RIG_VFO_MAIN)
+                                 : (rig_->state.vfo_list & RIG_VFO_B ? RIG_VFO_B : RIG_VFO_SUB)
+                                 , &f), tr ("getting current VFO frequency"));
+      TRACE_CAT_POLL ("rig_get_freq other VFO =" << f);
+      update_other_frequency (f);
+    }
+
+  error_check (rig_get_mode (rig_.data (), RIG_VFO_CURR, &m, &w), tr ("getting current VFO mode"));
+  TRACE_CAT_POLL ("rig_get_mode mode =" << rig_strrmode (m) << "bw =" << w);
+  update_mode (map_mode (m));
+
+  if (!is_dummy_ && rig_->caps->get_split_vfo && split_query_works_)
+    {
+      vfo_t v {RIG_VFO_NONE};		// so we can tell if it doesn't get updated :(
+      auto rc = rig_get_split_vfo (rig_.data (), RIG_VFO_CURR, &s, &v);
+      if (-RIG_OK == rc && RIG_SPLIT_ON == s)
+        {
+          TRACE_CAT_POLL ("rig_get_split_vfo split = " << s << " VFO = " << rig_strvfo (v));
+          update_split (true);
+          // if (RIG_VFO_A == v)
+          // 	{
+          // 	  reversed_ = true;	// not sure if this helps us here
+          // 	}
+        }
+      else if (-RIG_OK == rc)	// not split
+        {
+          TRACE_CAT_POLL ("rig_get_split_vfo split = " << s << " VFO = " << rig_strvfo (v));
+          update_split (false);
+        }
+      else
+        {
+          // Some rigs (Icom) don't have a way of reporting SPLIT
+          // mode
+          TRACE_CAT_POLL ("rig_get_split_vfo can't do on this rig");
+          // just report how we see it based on prior commands
+          split_query_works_ = false;
+        }
+    }
+
+  if (RIG_PTT_NONE != rig_->state.pttport.type.ptt && rig_->caps->get_ptt)
+    {
+      ptt_t p;
+      auto rc = rig_get_ptt (rig_.data (), RIG_VFO_CURR, &p);
+      if (-RIG_ENAVAIL != rc && -RIG_ENIMPL != rc) // may fail if
+        // Net rig ctl and target doesn't
+        // support command
+        {
+          error_check (rc, tr ("getting PTT state"));
+          TRACE_CAT_POLL ("rig_get_ptt PTT =" << p);
+          update_PTT (!(RIG_PTT_OFF == p));
+        }
+    }
+
+#if !WSJT_TRACE_CAT_POLLS
+#if WSJT_HAMLIB_TRACE
+#if WSJT_HAMLIB_VERBOSE_TRACE
+  rig_set_debug (RIG_DEBUG_TRACE);
+#else
+  rig_set_debug (RIG_DEBUG_VERBOSE);
+#endif
+#elif defined (NDEBUG)
+  rig_set_debug (RIG_DEBUG_ERR);
+#else
+  rig_set_debug (RIG_DEBUG_WARN);
+#endif
+#endif
+}
+
+void HamlibTransceiver::do_ptt (bool on)
+{
+  TRACE_CAT (on << state () << "reversed =" << reversed_);
+  if (on)
+    {
+      if (RIG_PTT_NONE != rig_->state.pttport.type.ptt)
+        {
+          TRACE_CAT ("rig_set_ptt PTT = true");
+          error_check (rig_set_ptt (rig_.data (), RIG_VFO_CURR
+                                    , RIG_PTT_RIG_MICDATA == rig_->caps->ptt_type && back_ptt_port_
+                                    ? RIG_PTT_ON_DATA : RIG_PTT_ON), tr ("setting PTT on"));
+        }
+    }
+  else
+    {
+      if (RIG_PTT_NONE != rig_->state.pttport.type.ptt)
+        {
+          TRACE_CAT ("rig_set_ptt PTT = false");
+          error_check (rig_set_ptt (rig_.data (), RIG_VFO_CURR, RIG_PTT_OFF), tr ("setting PTT off"));
+        }
+    }
+
+  update_PTT (on);
+}
+
+void HamlibTransceiver::set_conf (char const * item, char const * value)
+{
+  token_t token = rig_token_lookup (rig_.data (), item);
+  if (RIG_CONF_END != token)	// only set if valid for rig model
+    {
+      error_check (rig_set_conf (rig_.data (), token, value), tr ("setting a configuration item"));
+    }
+}
+
+QByteArray HamlibTransceiver::get_conf (char const * item)
+{
+  token_t token = rig_token_lookup (rig_.data (), item);
+  QByteArray value {128, '\0'};
+  if (RIG_CONF_END != token)	// only get if valid for rig model
+    {
+      error_check (rig_get_conf (rig_.data (), token, value.data ()), tr ("getting a configuration item"));
+    }
+  return value;
+}
+
+auto HamlibTransceiver::map_mode (rmode_t m) const -> MODE
+{
+  switch (m)
+    {
+    case RIG_MODE_AM:
+    case RIG_MODE_SAM:
+    case RIG_MODE_AMS:
+    case RIG_MODE_DSB:
+      return AM;
+
+    case RIG_MODE_CW:
+      return CW;
+
+    case RIG_MODE_CWR:
+      return CW_R;
+
+    case RIG_MODE_USB:
+    case RIG_MODE_ECSSUSB:
+    case RIG_MODE_SAH:
+    case RIG_MODE_FAX:
+      return USB;
+
+    case RIG_MODE_LSB:
+    case RIG_MODE_ECSSLSB:
+    case RIG_MODE_SAL:
+      return LSB;
+
+    case RIG_MODE_RTTY:
+      return FSK;
+
+    case RIG_MODE_RTTYR:
+      return FSK_R;
+
+    case RIG_MODE_PKTLSB:
+      return DIG_L;
+
+    case RIG_MODE_PKTUSB:
+      return DIG_U;
+
+    case RIG_MODE_FM:
+    case RIG_MODE_WFM:
+      return FM;
+
+    case RIG_MODE_PKTFM:
+      return DIG_FM;
+
+    default:
+      return UNK;
+    }
+}
+
+rmode_t HamlibTransceiver::map_mode (MODE mode) const
+{
+  switch (mode)
+    {
+    case AM: return RIG_MODE_AM;
+    case CW: return RIG_MODE_CW;
+    case CW_R: return RIG_MODE_CWR;
+    case USB: return RIG_MODE_USB;
+    case LSB: return RIG_MODE_LSB;
+    case FSK: return RIG_MODE_RTTY;
+    case FSK_R: return RIG_MODE_RTTYR;
+    case DIG_L: return RIG_MODE_PKTLSB;
+    case DIG_U: return RIG_MODE_PKTUSB;
+    case FM: return RIG_MODE_FM;
+    case DIG_FM: return RIG_MODE_PKTFM;
+    default: break;
+    }
+  return RIG_MODE_USB;	// quieten compiler grumble
+}
diff --git a/HamlibTransceiver.hpp b/HamlibTransceiver.hpp
new file mode 100644
index 0000000..567ac3d
--- /dev/null
+++ b/HamlibTransceiver.hpp
@@ -0,0 +1,70 @@
+#ifndef HAMLIB_TRANSCEIVER_HPP_
+#define HAMLIB_TRANSCEIVER_HPP_
+
+#include <tuple>
+
+#include <QString>
+
+#include <hamlib/rig.h>
+
+#include "TransceiverFactory.hpp"
+#include "PollingTransceiver.hpp"
+
+extern "C"
+{
+  typedef struct rig RIG;
+  struct rig_caps;
+  typedef int vfo_t;
+}
+
+// hamlib transceiver and PTT mostly delegated directly to hamlib Rig class
+class HamlibTransceiver final
+  : public PollingTransceiver
+{
+  Q_OBJECT;                     // for translation context
+
+ public:
+  static void register_transceivers (TransceiverFactory::Transceivers *);
+
+  explicit HamlibTransceiver (int model_number, TransceiverFactory::ParameterPack const&);
+  explicit HamlibTransceiver (TransceiverFactory::PTTMethod ptt_type, QString const& ptt_port);
+  ~HamlibTransceiver ();
+
+ private:
+  void do_start () override;
+  void do_stop () override;
+  void do_frequency (Frequency, MODE) override;
+  void do_tx_frequency (Frequency, bool rationalise_mode) override;
+  void do_mode (MODE, bool rationalise) override;
+  void do_ptt (bool) override;
+
+  void poll () override;
+
+  void error_check (int ret_code, QString const& doing) const;
+  void set_conf (char const * item, char const * value);
+  QByteArray get_conf (char const * item);
+  Transceiver::MODE map_mode (rmode_t) const;
+  rmode_t map_mode (Transceiver::MODE mode) const;
+  std::tuple<vfo_t, vfo_t> get_vfos () const;
+
+  struct RIGDeleter {static void cleanup (RIG *);};
+  QScopedPointer<RIG, RIGDeleter> rig_;
+
+  bool back_ptt_port_;
+  bool is_dummy_;
+
+  // these are saved on destruction so we can start new instances
+  // where the last one left off
+  static freq_t dummy_frequency_;
+  static rmode_t dummy_mode_;
+
+  bool mutable reversed_;
+
+  bool split_query_works_;
+  bool tickle_hamlib_;          // Hamlib requires a
+                                // rig_set_split_vfo() call to
+                                // establish the Tx VFO
+  bool get_vfo_works_;          // Net rigctl promises what it can't deliver
+};
+
+#endif
diff --git a/INSTALL b/INSTALL
new file mode 100644
index 0000000..fe0e8a5
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,369 @@
+
+ __       __   ______      _____  ________      __    __ 
+|  \  _  |  \ /      \    |     \|        \    |  \  |  \
+| $$ / \ | $$|  $$$$$$\    \$$$$$ \$$$$$$$$    | $$  | $$
+| $$/  $\| $$| $$___\$$      | $$   | $$ ______ \$$\/  $$
+| $$  $$$\ $$ \$$    \  __   | $$   | $$|      \ >$$  $$ 
+| $$ $$\$$\$$ _\$$$$$$\|  \  | $$   | $$ \$$$$$$/  $$$$\ 
+| $$$$  \$$$$|  \__| $$| $$__| $$   | $$       |  $$ \$$\
+| $$$    \$$$ \$$    $$ \$$    $$   | $$       | $$  | $$
+ \$$      \$$  \$$$$$$   \$$$$$$     \$$        \$$   \$$
+                                                         
+                                                         
+                                                         
+Installing WSJT-X
+=================
+
+Binary packages of WSJT-X are available from the project web site:
+
+       http://www.physics.princeton.edu/pulsar/K1JT/wsjtx.html
+
+
+Building from Source
+====================
+
+On Linux systems  some of the prerequisite libraries  are available in
+the mainstream distribution repositories. They  are Qt v5 and FFTW v3.
+For MS  Windows see the section  "Building from Source on  MS Windows"
+below. For  Apple Mac see the  section "Building from Source  on Apple
+Mac".
+
+Qt v5, preferably v5.1 or later is required to build WSJT-X.
+
+Qt v5 multimedia  support and serial port is necessary  as well as the
+core  Qt   v5  components,  normally  installing   the  Qt  multimedia
+development  package   and  Qt  serialport  development   package  are
+sufficient to pull in all the required Qt components and dependants as
+a  single  transaction.  On  some systems  the  Qt  multimedia  plugin
+component is  separate in the  distribution repository an it  may also
+need installing.
+
+The single precision FFTW v3  library libfftw3f is required along with
+the  libfftw library  development  package.   Normally installing  the
+library  development  package  pulls  in all  the  FFTW  v3  libraries
+including the single precision variant.
+
+The Hamlib  library is  required. Currently WSJT-X  needs to  be built
+using a  forked version of the  Hamlib git master. This  fork contains
+patches  not yet  accepted by  the Hamlib  development team  which are
+essential for  correct operation of  WSJT-X. To build the  Hamlib fork
+from sources something like the following recipe should suffice:
+
+     mkdir ~/hamlib-prefix
+     cd ~/hamlib-prefix
+     git clone git://git.code.sf.net/u/bsomervi/hamlib src
+     cd src
+     git checkout integration
+     mkdir ../build
+     cd ../build
+     ../src/autogen.sh --prefix=$HOME/hamlib-prefix \
+          --disable-shared --enable-static \
+          --without-cxx-binding --disable-winradio \
+          CFLAGS="-fdata-sections -ffunction-sections" \
+          LDFLAGS="-Wl,--gc-sections"
+     make
+     make install
+
+This will build a binary  hamlib package located at ~/hamlib-prefix so
+you will need  to add that to your CMAKE_PREFIX_PATH  variable in your
+WSJT-X build.  On Linux  that is  probably the only  path you  have on
+CMAKE_PREFIX_PATH  unless  you  are   using  a  locally  installed  Qt
+installation.
+
+To get the  sources either download and extract a  source tarball from
+the project web site or preferably fetch the sources directly from the
+project's  subversion repository.  The  project svn  repository has  a
+non-standard layout  in that the WSJT-X  project is not on  the trunk,
+instead the main code line is in a branch at ^/branches/wsjtx
+
+     mkdir -p ~/wsjtx-prefix/build
+     cd ~/wsjtx-prefix
+     svn checkout svn://svn.code.sf.net/p/wsjt/wsjt/branches/wsjtx src
+
+To build WSJT-X you will need CMake and asciidoc installed.
+
+     cd ~/wsjtx-prefix/build
+     cmake -D CMAKE_PREFIX_PATH=~/hamlib-prefix ../src
+     cmake --build .
+     cmake --build . --target install
+
+The recipe  above will install  into /usr by  default, if you  wish to
+install  in  you own  directory  you  can  add  a prefix-path  to  the
+configure step like:
+
+     cd ~/wsjtx-prefix/build
+     cmake -D CMAKE_PREFIX_PATH=~/hamlib-prefix \
+         -D CMAKE_INSTALL_PREFIX=~/wsjtx-prefix ../src
+     cmake --build .
+     cmake --build . --target install
+
+this will install WSJT-X at ~/wsjtx-prefix.
+
+
+Building from Source on MS Windows
+==================================
+
+Because  building on  MS  Windows  is quite  complicated  there is  an
+Software Development Kit available  that provides all the prerequisite
+libraries and tools for building  WSJT-X. This SDK is called JT-SDK-QT
+which is documented here:
+
+http://physics.princeton.edu/pulsar/K1JT/wsjtx-doc/dev-guide-main.html
+
+If you need to build Hamlib rather than use the Hamlib kit included in
+the  JT-SDK the  following recipe  should help.  Reasons for  building
+Hamlib from source might include picking up the very latest patches or
+building a different branch that you wish to contribute to.
+
+On Windows there is a complication in that the compilers used to build
+Qt  and WSJT-X  are the  MinGW ones  bundled with  the Qt  package but
+Hamlib needs to be build from an MSYS shell with the tools required to
+build  an autotools  project. This  means that  you need  to tell  the
+Hamlib configuration  to use  the Qt bundled  MinGW compilers  (if you
+don't  then  the  thread  support   library  use  by  Hamlib  will  be
+incompatible  with that  used by  Qt and  WSJT-X). So  on Windows  the
+Hamlib build recipe is something like:
+
+In an MSYS shell:-
+
+    mkdir ~/hamib-prefix
+    cd ~/hamlib-prefix
+    git clone git://git.code.sf.net/u/bsomervi/hamlib src
+    cd src
+    git checkout integration
+    mkdir ../build
+    cd ../build
+    ../src/autogen.sh --prefix=$HOME/hamlib-prefix \
+        --disable-shared --enable-static \
+        --without-cxx-binding --disable-winradio \
+        CC=<path-to-Qt-MinGW-tools>/gcc \
+        CXX=<path-to-Qt-MinGW-tools>/g++ \
+        CFLAGS="-fdata-sections -ffunction-sections" \
+        LDFLAGS="-Wl,--gc-sections"
+    make
+    make install
+
+NOTE: <path-to-Qt-MinGQ-tools>  should be substituted with  the actual
+path   to  your   Qt   bundled  tools   e.g  on   my   system  it   is
+C:\Tools\Qt\Tools\mingw48_32\bin
+
+This   will    leave   a   Hamlib   binary    package   installed   at
+c:/Users/<user-name>/hamlib-prefix which  is what needs to  be on your
+CMAKE_PREFIX_PATH. On  Windows you  almost certainly  will be  using a
+CMake tool chain  file and this is  where you will need  to specify the
+Hamlib binary location as one of the paths in CMAKE_PREFIX_PATH.
+
+
+Building from Source on Apple Mac
+=================================
+
+These instructions are adapted from my Evernote page at:
+
+    https://www.evernote.com/pub/bsomervi/wsjt-xmacbuilds
+
+There are several  ways to get the required GNU  and other open source
+tools and libraries installed, my preference is MacPorts because it is
+easy to use and does everything we need.
+
+You  will need  Xcode, MacPorts,  CMake  and, Qt.   The Xcode  install
+instructions are included in the MacPorts documentation.
+
+MacPorts
+--------
+Install MacPorts from instructions here:
+
+    http://www.macports.org/install.php
+
+More detailed instructions are available in the documentation:
+
+    https://guide.macports.org
+
+The ports that need to be installed are:
+
+autoconf
+automake
+libtool
+pkgconfig
+texinfo
+gcc49
+fftw-3-single +gcc49
+asciidoc
+
+These are install by typing:
+
+    sudo port install autoconf automake \
+        libtool pkgconfig texinfo gcc49 asciidoc \
+        fftw-3-single +gcc49
+
+Once complete you should have all the tools required to build WSJT-X.
+
+Uninstalling MacPorts
+---------------------
+If at some point  you wish to remove the ports  from your machine. The
+instructions are here:
+
+    https://guide.macports.org/#installing.macports.uninstalling .
+
+Hamlib
+------
+First fetch hamlib from the repository, in this case my fork of Hamlib
+3 until the official repository has all the fixes we need:
+
+    mkdir -p ~/hamlib-prefix/build
+    cd ~/hamlib-prefix
+    git clone git://git.code.sf.net/u/bsomervi/hamlib src
+    cd src
+    git checkout integration
+
+The integration  branch is my system  testing branch which has  all my
+latest published changes.
+
+You need  to make one  small change  to the sources  to build on  OS X
+using the MacPorts tools, here is a sed command to make the change:
+
+     sed -i.orig '/libtoolize/s/lib/glib/' autogen.sh
+
+To build:
+
+    cd ~/hamlib-prefix/build
+    ../src/hamlib/autogen.sh \
+       --enable-static \
+       --disable-shared \
+       --disable-winradio \
+       --prefix=$HOME/hamlib-prefix
+    make
+    make install-strip
+
+The above commands will build hamlib and install it into ~/hamlib-prefix
+
+
+Qt
+--
+The   binary    Qt   distributions    from   http://www.qt.io/download
+unfortunately  are built  to use  the libstdc++  C++ support  library,
+WSJT-X uses  a less  geriatric C++  dialet which  uses the  libc++ C++
+support  library.  This   means  that  you  need  to   build  Qt  from
+sources. This is not difficult but does take some time.
+
+Download       the      Qt       source       tar      ball       from
+http://www.qt.io/download-open-source/,  the link  is  about half  way
+down the page, you want the full  sources tar ball shown as a 'tar.gz'
+link.
+
+Unpack the sources and cd into the top level directory then type:
+
+$ ./configure -prefix ~/local/qt-macx-clang -opensource \
+    -confirm-license -platform macx-clang -silent -nomake tests \
+    -nomake examples -sdk macosx10.10 -skip qtwebkit \
+    -skip qtwebkit-examples -skip qtquick1 -skip qtconnectivity \
+    -skip qtlocation -skip qtsensors -skip qtscript \
+    -skip qtwebsockets -skip qtwebengine -skip qtwebchannel \
+    -skip qtwayland -skip qtquickcontrols -skip qtdeclarative \
+    -skip qtxmlpatterns -skip qtenginio
+$ make -j4
+$ make install
+
+If you are building on 10.8 or  don't have the 10.10 Mac SDK (Xcode 6)
+available, you can substitute '-sdk macosx10.9' above.
+
+The build above will take a few hours to complete.
+
+
+CMake
+-----
+Although CMake  is available via MacPorts  I prefer to use  the binary
+installer  from cake.org  as  the MacPorts  port  doesn't include  the
+graphical CMake tool cmake-gui which I find quite useful.
+
+Fetch    the    latest    CMake     universal    64-bit    DMG    from
+http://www.cmake.org/download/  open the  DMG then  drag and  drop the
+application bundle onto the supplied /Applications link.
+
+To complete the install process you  need to run the CMake application
+as root from a terminal shell:
+
+    sudo /Applications/CMake.app/Contents/MacOS/CMake
+
+in the CMake application choose  "Tools->Install For Command Line Use"
+from the menu and then click the "Install Command Line Links".
+
+
+WSJT-X
+------
+First fetch the source from the repository:
+
+    mkdir -p ~/wsjtx-prefix/build
+    cd ~/wsjtx-prefix
+    svn checkout svn://svn.code.sf.net/p/wsjt/wsjt/branches/wsjtx src
+
+this links to the Subversion repository in a read-only fashion, if you
+intend to  contribute to the project  then you probably want  to get a
+developer login  and use a read-write  checkout. Even if you  don't it
+can be upgraded at a later date.
+
+The checkout  is of  the latest  code on the  project trunk,  i.e. the
+development  branch. You  can easily  switch the  checkout to  another
+branch  or  even  a  tag  if  you want  to  build  a  prior  published
+generation. For now  we will build the latest  development sources. To
+configure:
+
+    cd ~/wsjtx-prefix/build
+    FC=gfortran-mp-4.9 \
+    cmake \
+        -D CMAKE_PREFIX_PATH="~/local/qt-macx-clang;~/hamlib-prefix;/opt/local" \
+        -D CMAKE_INSTALL_PREFIX=~/wsjtx-prefix \
+        ~/wsjtx-prefix/src
+
+The CMAKE_PREFIX_PATH variable specifies where CMake should look first
+for other packages, the two  elements may be different depending where
+you  have  installed Qt  and  what  version  you  have and  where  you
+installed  Hamlib (i.e.  the --prefix  configure option  above in  the
+hamlib section).
+
+If you already have the fftw3-dev  package installed on your system it
+may well get selected in preference to  the one you built above in the
+MacPorts installation.  It is  unlikely that  a prior  installation of
+libfftw3f is  correctly configured  for use in  a WSJT-X  package, the
+CMAKE_PREFIX_PATH above  is augmented  with the  MacPorts installation
+location  (/opt/local)  to  ensure  the  correct  libfftw3f.dylib  and
+headers are located.
+
+To build:
+
+    cmake --build .
+    cmake --build . --target install
+
+which installs the WSJT-X application bundle into ~/wsjtx-prefix
+
+
+Updating and Rebuilding Hamlib
+==============================
+
+From  time  to time  new  fixes  will be  pushed  to  the Hamlib  fork
+repository integration branch. To pick them up type:
+
+    cd ~/hamlib-prefix/src
+    git pull
+
+To rebuild hamlib with the changed sources:
+
+    cd ~/hamlib-prefix/build
+    make
+    make install-strip
+
+
+Updating and Rebuilding WSJT-X
+==============================
+
+To update to the latest sources type:
+
+    cd ~/wsjtx-prefix/src
+    svn update
+    cd ~/wsjtx-prefix/build
+    cmake --build .
+    cmake --build . --target install
+
+
+73
+Bill
+G4WJS.
\ No newline at end of file
diff --git a/LICENSE_WHEATLEY.TXT b/LICENSE_WHEATLEY.TXT
deleted file mode 100644
index 8b0ce24..0000000
--- a/LICENSE_WHEATLEY.TXT
+++ /dev/null
@@ -1,30 +0,0 @@
-+ + + This Software is released under the "Simplified BSD License"  + + +
-Copyright 2010 Moe Wheatley. 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 Moe Wheatley ``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 Moe Wheatley 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.
-
-The views and conclusions contained in the software and documentation 
-are those of the authors and should not be interpreted as representing 
-official policies, either expressed or implied, of Moe Wheatley.
diff --git a/LiveFrequencyValidator.cpp b/LiveFrequencyValidator.cpp
new file mode 100644
index 0000000..f234122
--- /dev/null
+++ b/LiveFrequencyValidator.cpp
@@ -0,0 +1,92 @@
+#include "LiveFrequencyValidator.hpp"
+
+#include <QLocale>
+#include <QString>
+#include <QComboBox>
+#include <QLineEdit>
+
+#include "Bands.hpp"
+#include "FrequencyList.hpp"
+
+#include "moc_LiveFrequencyValidator.cpp"
+
+LiveFrequencyValidator::LiveFrequencyValidator (QComboBox * combo_box
+                                                , Bands const * bands
+                                                , FrequencyList const * frequencies
+                                                , QWidget * parent)
+  : QRegExpValidator {
+  QRegExp {				// frequency in MHz or band
+    bands->data (QModelIndex {}).toString () // out of band string
+      + QString {R"(|((\d{0,6}(\)"}		 // up to 6 digits
+    + QLocale {}.decimalPoint () // (followed by decimal separator
+                   + R"(\d{0,2})?)([Mm]{1,2}|([Cc][Mm])))|(\d{0,4}(\)" // followed by up to 2 digits and either 'm' or 'cm' or 'mm' (case insensitive))
+                   + QLocale {}.decimalPoint () // or a decimal separator
+                                  + R"(\d{0,6})?))"	       //  followed by up to 6 digits
+                                  }
+  , parent
+      }
+  , bands_ {bands}
+  , frequencies_ {frequencies}
+  , combo_box_ {combo_box}
+{
+}
+
+auto LiveFrequencyValidator::validate (QString& input, int& pos) const -> State
+{
+  auto state = QRegExpValidator::validate (input, pos);
+
+  // by never being Acceptable we force fixup calls on ENTER or
+  // losing focus
+  return Acceptable == state ? Intermediate : state;
+}
+
+void LiveFrequencyValidator::fixup (QString& input) const
+{
+  QRegExpValidator::fixup (input);
+
+  auto out_of_band = bands_->data (QModelIndex {}).toString ();
+
+  if (!out_of_band.startsWith (input))
+    {
+      if (input.contains ('m', Qt::CaseInsensitive))
+	{
+	  input = input.toLower ();
+
+	  QVector<QVariant> frequencies;
+	  for (int r = 0; r < frequencies_->rowCount (); ++r)
+	    {
+	      auto frequency = frequencies_->index (r, 0).data ();
+	      auto band_index = bands_->find (frequency);
+	      if (band_index.data ().toString () == input)
+		{
+		  frequencies << frequency;
+		}
+	    }
+	  if (!frequencies.isEmpty ())
+	    {
+	      Q_EMIT valid (frequencies.first ().value<Frequency> ());
+	    }
+	  else
+	    {
+	      input = QString {};
+	    }
+	}
+      else
+	{
+	  // frequency input
+	  auto f = Radio::frequency (input, 6);
+	  input = bands_->data (bands_->find (f)).toString ();
+	  Q_EMIT valid (f);
+	}
+
+      if (out_of_band == input)
+	{
+	  combo_box_->lineEdit ()->setStyleSheet ("QLineEdit {color: yellow; background-color : red;}");
+	}
+      else
+	{
+	  combo_box_->lineEdit ()->setStyleSheet ({});
+	}
+      combo_box_->setCurrentText (input);
+    }
+}
diff --git a/LiveFrequencyValidator.hpp b/LiveFrequencyValidator.hpp
new file mode 100644
index 0000000..d4d6cc6
--- /dev/null
+++ b/LiveFrequencyValidator.hpp
@@ -0,0 +1,52 @@
+#ifndef LIVE_FREQUENCY_VALIDATOR_HPP__
+#define LIVE_FREQUENCY_VALIDATOR_HPP__
+
+#include <QObject>
+#include <QRegExpValidator>
+
+#include "Radio.hpp"
+
+class Bands;
+class FrequencyList;
+class QComboBox;
+class QWidget;
+
+//
+// Class LiveFrequencyValidator
+//
+//	QLineEdit validator that controls input to an editable
+//	QComboBox where the user can enter a valid band or a valid
+//	frequency in megahetz.
+//
+// Collabrations
+//
+//	Implements the QRegExpValidator interface. Validates input
+//	from the supplied QComboBox as either a valid frequency in
+//	megahertz or a valid band as defined by the supplied column of
+//	the supplied QAbstractItemModel.
+//
+class LiveFrequencyValidator final
+  : public QRegExpValidator
+{
+  Q_OBJECT;
+
+public:
+  using Frequency = Radio::Frequency;
+
+  LiveFrequencyValidator (QComboBox * combo_box // associated combo box
+                          , Bands const * bands // bands model
+                          , FrequencyList const * frequencies // working frequencies model
+                          , QWidget * parent = nullptr);
+
+  State validate (QString& input, int& pos) const override;
+  void fixup (QString& input) const override;
+
+  Q_SIGNAL void valid (Frequency) const;
+
+private:
+  Bands const * bands_;
+  FrequencyList const * frequencies_;
+  QComboBox * combo_box_;
+};
+
+#endif
diff --git a/MessageAggregator.cpp b/MessageAggregator.cpp
new file mode 100644
index 0000000..9f4d139
--- /dev/null
+++ b/MessageAggregator.cpp
@@ -0,0 +1,509 @@
+//
+// MessageAggregator - an example application that utilizes the WSJT-X
+//                     messaging facility
+//
+// This  application is  only  provided as  a  simple GUI  application
+// example to demonstrate the WSJT-X messaging facility. It allows the
+// user to set  the server details either as a  unicast UDP server or,
+// if a  multicast group address  is provided, as a  multicast server.
+// The benefit of the multicast server is that multiple servers can be
+// active at  once each  receiving all  WSJT-X broadcast  messages and
+// each able to  respond to individual WSJT_X clients.  To utilize the
+// multicast  group features  each  WSJT-X client  must  set the  same
+// multicast  group address  as  the UDP  server  address for  example
+// 239.255.0.0 for a site local multicast group.
+//
+// The  UI is  a small  panel  to input  the service  port number  and
+// optionally  the  multicast  group  address.   Below  that  a  table
+// representing  the  log  entries   where  any  QSO  logged  messages
+// broadcast  from WSJT-X  clients are  displayed. The  bottom of  the
+// application main  window is a  dock area  where a dock  window will
+// appear for each WSJT-X client, this  window contains a table of the
+// current decode  messages broadcast  from that  WSJT-X client  and a
+// status line showing  the status update messages  broadcast from the
+// WSJT_X client. The dock windows may  be arranged in a tab bar, side
+// by side,  below each  other or, completely  detached from  the dock
+// area as floating windows. Double clicking the dock window title bar
+// or  dragging and  dropping with  the mouse  allows these  different
+// arrangements.
+//
+// The application  also provides a  simple menu bar including  a view
+// menu that allows each dock window to be hidden or revealed.
+//
+
+#include <iostream>
+#include <exception>
+
+#include <QtWidgets>
+#include <QFile>
+#include <QStandardItemModel>
+#include <QStandardItem>
+#include <QSortFilterProxyModel>
+#include <QFont>
+#include <QDateTime>
+#include <QTime>
+#include <QHash>
+
+#include "MessageServer.hpp"
+#include "NetworkMessage.hpp"
+
+#include "qt_helpers.hpp"
+
+using port_type = MessageServer::port_type;
+using Frequency = MessageServer::Frequency;
+
+QRegExp message_alphabet {"[- A-Za-z0-9+./?]*"};
+
+//
+// Decodes Model - simple data model for all decodes
+//
+// The model is a basic table with uniform row format. Rows consist of
+// QStandardItem instances containing the string representation of the
+// column data  and if the underlying  field is not a  string then the
+// UserRole+1 role contains the underlying data item.
+//
+// Three slots  are provided to add  a new decode, remove  all decodes
+// for a client  and, to build a  reply to CQ message for  a given row
+// which is emitted as a signal respectively.
+//
+class DecodesModel
+  : public QStandardItemModel
+{
+  Q_OBJECT;
+
+public:
+  DecodesModel (QObject * parent = nullptr)
+    : QStandardItemModel {0, 7, parent}
+    , text_font_ {"Courier", 10}
+  {
+    setHeaderData (0, Qt::Horizontal, tr ("Client"));
+    setHeaderData (1, Qt::Horizontal, tr ("Time"));
+    setHeaderData (2, Qt::Horizontal, tr ("Snr"));
+    setHeaderData (3, Qt::Horizontal, tr ("DT"));
+    setHeaderData (4, Qt::Horizontal, tr ("DF"));
+    setHeaderData (5, Qt::Horizontal, tr ("Md"));
+    setHeaderData (6, Qt::Horizontal, tr ("Message"));
+  }
+
+  Q_SLOT void add_decode (bool is_new, QString const& client_id, QTime time, qint32 snr, float delta_time
+                          , quint32 delta_frequency, QString const& mode, QString const& message)
+  {
+    if (!is_new)
+      {
+        int target_row {-1};
+        for (auto row = 0; row < rowCount (); ++row)
+          {
+            if (data (index (row, 0)).toString () == client_id)
+              {
+                auto row_time = item (row, 1)->data ().toTime ();
+                if (row_time == time
+                    && item (row, 2)->data ().toInt () == snr
+                    && item (row, 3)->data ().toFloat () == delta_time
+                    && item (row, 4)->data ().toUInt () == delta_frequency
+                    && data (index (row, 5)).toString () == mode
+                    && data (index (row, 6)).toString () == message)
+                  {
+                    return;
+                  }
+                if (time <= row_time)
+                  {
+                    target_row = row; // last row with same time
+                  }
+              }
+          }
+        if (target_row >= 0)
+          {
+            insertRow (target_row + 1, make_row (client_id, time, snr, delta_time, delta_frequency, mode, message));
+            return;
+          }
+      }
+
+    appendRow (make_row (client_id, time, snr, delta_time, delta_frequency, mode, message));
+  }
+
+  QList<QStandardItem *> make_row (QString const& client_id, QTime time, qint32 snr, float delta_time
+                                   , quint32 delta_frequency, QString const& mode, QString const& message) const
+  {
+    auto time_item = new QStandardItem {time.toString ("hh:mm")};
+    time_item->setData (time);
+    time_item->setTextAlignment (Qt::AlignRight);
+
+    auto snr_item = new QStandardItem {QString::number (snr)};
+    snr_item->setData (snr);
+    snr_item->setTextAlignment (Qt::AlignRight);
+
+    auto dt = new QStandardItem {QString::number (delta_time)};
+    dt->setData (delta_time);
+    dt->setTextAlignment (Qt::AlignRight);
+
+    auto df = new QStandardItem {QString::number (delta_frequency)};
+    df->setData (delta_frequency);
+    df->setTextAlignment (Qt::AlignRight);
+
+    auto md = new QStandardItem {mode};
+    md->setTextAlignment (Qt::AlignHCenter);
+
+    QList<QStandardItem *> row {
+      new QStandardItem {client_id}, time_item, snr_item, dt, df, md, new QStandardItem {message}};
+    Q_FOREACH (auto& item, row)
+      {
+        item->setEditable (false);
+        item->setFont (text_font_);
+        item->setTextAlignment (item->textAlignment () | Qt::AlignVCenter);
+      }
+    return row;
+  }
+
+  Q_SLOT void clear_decodes (QString const& client_id)
+  {
+    for (auto row = rowCount () - 1; row >= 0; --row)
+      {
+        if (data (index (row, 0)).toString () == client_id)
+          {
+            removeRow (row);
+          }
+      }
+  }
+
+  Q_SLOT void do_reply (QModelIndex const& source)
+  {
+    auto row = source.row ();
+    Q_EMIT reply (data (index (row, 0)).toString ()
+                  , item (row, 1)->data ().toTime ()
+                  , item (row, 2)->data ().toInt ()
+                  , item (row, 3)->data ().toFloat ()
+                  , item (row, 4)->data ().toInt ()
+                  , data (index (row, 5)).toString ()
+                  , data (index (row, 6)).toString ());
+  }
+
+  Q_SIGNAL void reply (QString const& id, QTime time, qint32 snr, float delta_time, quint32 delta_frequency
+                       , QString const& mode, QString const& message);
+
+private:
+  QFont text_font_;
+};
+
+class ClientWidget
+  : public QDockWidget
+{
+  Q_OBJECT;
+
+public:
+  explicit ClientWidget (QAbstractItemModel * decodes_model, QString const& id, QWidget * parent = 0)
+    : QDockWidget {id, parent}
+    , id_ {id}
+    , decodes_table_view_ {new QTableView}
+    , message_line_edit_ {new QLineEdit}
+    , auto_off_button_ {new QPushButton {tr ("&Auto Off")}}
+    , halt_tx_button_ {new QPushButton {tr ("&Halt Tx")}}
+    , mode_label_ {new QLabel}
+    , dx_call_label_ {new QLabel}
+    , frequency_label_ {new QLabel}
+    , report_label_ {new QLabel}
+  {
+    auto content_layout = new QVBoxLayout;
+    content_layout->setContentsMargins (QMargins {2, 2, 2, 2});
+
+    // set up table
+    auto proxy_model = new DecodesFilterModel {id, this};
+    proxy_model->setSourceModel (decodes_model);
+    decodes_table_view_->setModel (proxy_model);
+    decodes_table_view_->verticalHeader ()->hide ();
+    decodes_table_view_->hideColumn (0);
+    content_layout->addWidget (decodes_table_view_);
+
+    // set up controls
+    auto control_layout = new QHBoxLayout;
+    auto form_layout = new QFormLayout;
+    form_layout->addRow (tr ("Free text:"), message_line_edit_);
+    message_line_edit_->setValidator (new QRegExpValidator {message_alphabet, this});
+    connect (message_line_edit_, &QLineEdit::textEdited, [this] (QString const& text) {
+        Q_EMIT do_free_text (id_, text, false);
+      });
+    connect (message_line_edit_, &QLineEdit::editingFinished, [this] () {
+        Q_EMIT do_free_text (id_, message_line_edit_->text (), !message_line_edit_->text ().isEmpty ());
+      });
+    control_layout->addLayout (form_layout);
+    control_layout->addWidget (auto_off_button_);
+    control_layout->addWidget (halt_tx_button_);
+    connect (auto_off_button_, &QAbstractButton::clicked, [this] (bool /* checked */) {
+        Q_EMIT do_halt_tx (id_, true);
+      });
+    connect (halt_tx_button_, &QAbstractButton::clicked, [this] (bool /* checked */) {
+        Q_EMIT do_halt_tx (id_, false);
+      });
+    content_layout->addLayout (control_layout);
+
+    // set up status area
+    auto status_bar = new QStatusBar;
+    status_bar->addPermanentWidget (mode_label_);
+    status_bar->addPermanentWidget (dx_call_label_);
+    status_bar->addPermanentWidget (frequency_label_);
+    status_bar->addPermanentWidget (report_label_);
+    content_layout->addWidget (status_bar);
+    connect (this, &ClientWidget::topLevelChanged, status_bar, &QStatusBar::setSizeGripEnabled);
+
+    // set up central widget
+    auto content_widget = new QFrame;
+    content_widget->setFrameStyle (QFrame::StyledPanel | QFrame::Sunken);
+    content_widget->setLayout (content_layout);
+    setWidget (content_widget);
+    // setMinimumSize (QSize {550, 0});
+    setFeatures (DockWidgetMovable | DockWidgetFloatable);
+    setAllowedAreas (Qt::BottomDockWidgetArea);
+
+    // connect up table view signals
+    connect (decodes_table_view_, &QTableView::doubleClicked, this, [this, proxy_model] (QModelIndex const& index) {
+        Q_EMIT do_reply (proxy_model->mapToSource (index));
+      });
+  }
+
+  Q_SLOT void update_status (QString const& id, Frequency f, QString const& mode, QString const& dx_call
+                             , QString const& report, QString const& tx_mode, bool tx_enabled, bool transmitting)
+  {
+    if (id == id_)
+      {
+        mode_label_->setText (QString {"Mode: %1%2"}.arg (mode).arg (tx_mode.isEmpty () ? tx_mode : '(' + tx_mode + ')'));
+        dx_call_label_->setText ("DX CALL: " + dx_call);
+        frequency_label_->setText ("QRG: " + Radio::pretty_frequency_MHz_string (f));
+        report_label_->setText ("SNR: " + report);
+        update_dynamic_property (frequency_label_, "transmitting", transmitting);
+        auto_off_button_->setEnabled (tx_enabled);
+        halt_tx_button_->setEnabled (transmitting);
+      }
+  }
+
+  Q_SLOT void decode_added (bool /*is_new*/, QString const& client_id, QTime /*time*/, qint32 /*snr*/
+                            , float /*delta_time*/, quint32 /*delta_frequency*/, QString const& /*mode*/
+                            , QString const& /*message*/)
+  {
+    if (client_id == id_)
+      {
+        decodes_table_view_->resizeColumnsToContents ();
+        decodes_table_view_->horizontalHeader ()->setStretchLastSection (true);
+        decodes_table_view_->scrollToBottom ();
+      }
+  }
+
+  Q_SIGNAL void do_reply (QModelIndex const&);
+  Q_SIGNAL void do_halt_tx (QString const& id, bool auto_only);
+  Q_SIGNAL void do_free_text (QString const& id, QString const& text, bool);
+
+private:
+  class DecodesFilterModel final
+    : public QSortFilterProxyModel
+  {
+  public:
+    DecodesFilterModel (QString const& id, QObject * parent = nullptr)
+      : QSortFilterProxyModel {parent}
+      , id_ {id}
+    {}
+
+  protected:
+    bool filterAcceptsRow (int source_row, QModelIndex const& source_parent) const override
+    {
+      auto source_index_col0 = sourceModel ()->index (source_row, 0, source_parent);
+      return sourceModel ()->data (source_index_col0).toString () == id_;
+    }
+
+  private:
+    QString id_;
+  };
+
+  QString id_;
+  QTableView * decodes_table_view_;
+  QLineEdit * message_line_edit_;
+  QAbstractButton * set_free_text_button_;
+  QAbstractButton * auto_off_button_;
+  QAbstractButton * halt_tx_button_;
+  QLabel * mode_label_;
+  QLabel * dx_call_label_;
+  QLabel * frequency_label_;
+  QLabel * report_label_;
+};
+
+class MainWindow
+  : public QMainWindow
+{
+  Q_OBJECT;
+
+public:
+  MainWindow ()
+    : log_ {new QStandardItemModel {0, 10, this}}
+    , decodes_model_ {new DecodesModel {this}}
+    , server_ {new MessageServer {this}}
+    , multicast_group_line_edit_ {new QLineEdit}
+    , log_table_view_ {new QTableView}
+  {
+    // logbook
+    log_->setHeaderData (0, Qt::Horizontal, tr ("Date/Time"));
+    log_->setHeaderData (1, Qt::Horizontal, tr ("Callsign"));
+    log_->setHeaderData (2, Qt::Horizontal, tr ("Grid"));
+    log_->setHeaderData (3, Qt::Horizontal, tr ("Name"));
+    log_->setHeaderData (4, Qt::Horizontal, tr ("Frequency"));
+    log_->setHeaderData (5, Qt::Horizontal, tr ("Mode"));
+    log_->setHeaderData (6, Qt::Horizontal, tr ("Sent"));
+    log_->setHeaderData (7, Qt::Horizontal, tr ("Rec'd"));
+    log_->setHeaderData (8, Qt::Horizontal, tr ("Power"));
+    log_->setHeaderData (9, Qt::Horizontal, tr ("Comments"));
+    connect (server_, &MessageServer::qso_logged, this, &MainWindow::log_qso);
+
+    // menu bar
+    auto file_menu = menuBar ()->addMenu (tr ("&File"));
+
+    auto exit_action = new QAction {tr ("E&xit"), this};
+    exit_action->setShortcuts (QKeySequence::Quit);
+    exit_action->setToolTip (tr ("Exit the application"));
+    file_menu->addAction (exit_action);
+    connect (exit_action, &QAction::triggered, this, &MainWindow::close);
+
+    view_menu_ = menuBar ()->addMenu (tr ("&View"));
+
+    // central layout
+    auto central_layout = new QVBoxLayout;
+
+    // server details
+    auto port_spin_box = new QSpinBox;
+    port_spin_box->setMinimum (1);
+    port_spin_box->setMaximum (std::numeric_limits<port_type>::max ());
+    auto group_box_layout = new QFormLayout;
+    group_box_layout->addRow (tr ("Port number:"), port_spin_box);
+    group_box_layout->addRow (tr ("Multicast Group (blank for unicast server):"), multicast_group_line_edit_);
+    auto group_box = new QGroupBox {tr ("Server Details")};
+    group_box->setLayout (group_box_layout);
+    central_layout->addWidget (group_box);
+
+    log_table_view_->setModel (log_);
+    log_table_view_->verticalHeader ()->hide ();
+    central_layout->addWidget (log_table_view_);
+
+    // central widget
+    auto central_widget = new QWidget;
+    central_widget->setLayout (central_layout);
+
+    // main window setup
+    setCentralWidget (central_widget);
+    setDockOptions (AnimatedDocks | AllowNestedDocks | AllowTabbedDocks);
+    setTabPosition (Qt::BottomDockWidgetArea, QTabWidget::North);
+
+    // connect up server
+    connect (server_, &MessageServer::error, [this] (QString const& message) {
+        QMessageBox::warning (this, tr ("Network Error"), message);
+      });
+    connect (server_, &MessageServer::client_opened, this, &MainWindow::add_client);
+    connect (server_, &MessageServer::client_closed, this, &MainWindow::remove_client);
+    connect (server_, &MessageServer::client_closed, decodes_model_, &DecodesModel::clear_decodes);
+    connect (server_, &MessageServer::decode, decodes_model_, &DecodesModel::add_decode);
+    connect (server_, &MessageServer::clear_decodes, decodes_model_, &DecodesModel::clear_decodes);
+    connect (decodes_model_, &DecodesModel::reply, server_, &MessageServer::reply);
+
+    // UI behaviour
+    connect (port_spin_box, static_cast<void (QSpinBox::*)(int)> (&QSpinBox::valueChanged)
+             , [this] (port_type port) {server_->start (port);});
+    connect (multicast_group_line_edit_, &QLineEdit::editingFinished, [this, port_spin_box] () {
+        server_->start (port_spin_box->value (), QHostAddress {multicast_group_line_edit_->text ()});
+      });
+
+    port_spin_box->setValue (2237); // start up in unicast mode
+    show ();
+  }
+
+  Q_SLOT void log_qso (QString const& /*id*/, QDateTime time, QString const& dx_call, QString const& dx_grid
+                       , Frequency dial_frequency, QString const& mode, QString const& report_sent
+                       , QString const& report_received, QString const& tx_power, QString const& comments
+                       , QString const& name)
+  {
+    QList<QStandardItem *> row;
+    row << new QStandardItem {time.toString ("dd-MMM-yyyy hh:mm")}
+        << new QStandardItem {dx_call}
+        << new QStandardItem {dx_grid}
+        << new QStandardItem {name}
+        << new QStandardItem {Radio::frequency_MHz_string (dial_frequency)}
+        << new QStandardItem {mode}
+        << new QStandardItem {report_sent}
+        << new QStandardItem {report_received}
+        << new QStandardItem {tx_power}
+        << new QStandardItem {comments};
+    log_->appendRow (row);
+    log_table_view_->resizeColumnsToContents ();
+    log_table_view_->horizontalHeader ()->setStretchLastSection (true);
+    log_table_view_->scrollToBottom ();
+  }
+
+private:
+  void add_client (QString const& id)
+  {
+    auto dock = new ClientWidget {decodes_model_, id, this};
+    dock->setAttribute (Qt::WA_DeleteOnClose);
+    auto view_action = dock->toggleViewAction ();
+    view_action->setEnabled (true);
+    view_menu_->addAction (view_action);
+    addDockWidget (Qt::BottomDockWidgetArea, dock);
+    connect (server_, &MessageServer::status_update, dock, &ClientWidget::update_status);
+    connect (server_, &MessageServer::decode, dock, &ClientWidget::decode_added);
+    connect (dock, &ClientWidget::do_reply, decodes_model_, &DecodesModel::do_reply);
+    connect (dock, &ClientWidget::do_halt_tx, server_, &MessageServer::halt_tx);
+    connect (dock, &ClientWidget::do_free_text, server_, &MessageServer::free_text);
+    connect (view_action, &QAction::toggled, dock, &ClientWidget::setVisible);
+    dock_widgets_[id] = dock;
+    server_->replay (id);
+  }
+
+  void remove_client (QString const& id)
+  {
+    auto iter = dock_widgets_.find (id);
+    if (iter != std::end (dock_widgets_))
+      {
+        (*iter)->close ();
+        dock_widgets_.erase (iter);
+      }
+  }
+
+  QStandardItemModel * log_;
+  QMenu * view_menu_;
+  DecodesModel * decodes_model_;
+  MessageServer * server_;
+  QLineEdit * multicast_group_line_edit_;
+  QTableView * log_table_view_;
+
+  // maps client id to widgets
+  QHash<QString, ClientWidget *> dock_widgets_;
+};
+
+#include "MessageAggregator.moc"
+
+int main (int argc, char * argv[])
+{
+  QApplication app {argc, argv};
+  try
+    {
+      QObject::connect (&app, SIGNAL (lastWindowClosed ()), &app, SLOT (quit ()));
+
+      app.setApplicationName ("WSJT-X Reference UDP Message Aggregator Server");
+      app.setApplicationVersion ("1.0");
+
+      {
+        QFile file {":/qss/default.qss"};
+        if (!file.open (QFile::ReadOnly))
+          {
+            throw_qstring ("failed to open \"" + file.fileName () + "\": " + file.errorString ());
+          }
+        app.setStyleSheet (file.readAll());
+      }
+
+      MainWindow window;
+      return app.exec ();
+    }
+  catch (std::exception const & e)
+    {
+      QMessageBox::critical (nullptr, app.applicationName (), e.what ());
+      std:: cerr << "Error: " << e.what () << '\n';
+    }
+  catch (...)
+    {
+      QMessageBox::critical (nullptr, app.applicationName (), QObject::tr ("Unexpected error"));
+      std:: cerr << "Unexpected error\n";
+    }
+  return -1;
+}
diff --git a/MessageClient.cpp b/MessageClient.cpp
new file mode 100644
index 0000000..17475a7
--- /dev/null
+++ b/MessageClient.cpp
@@ -0,0 +1,342 @@
+#include "MessageClient.hpp"
+
+#include <stdexcept>
+
+#include <QUdpSocket>
+#include <QHostInfo>
+#include <QTimer>
+
+#include "NetworkMessage.hpp"
+
+#include "pimpl_impl.hpp"
+
+#include "moc_MessageClient.cpp"
+
+class MessageClient::impl
+  : public QUdpSocket
+{
+  Q_OBJECT;
+
+public:
+  impl (QString const& id, port_type server_port, MessageClient * self)
+    : self_ {self}
+    , id_ {id}
+    , server_port_ {server_port}
+    , heartbeat_timer_ {new QTimer {this}}
+  {
+    connect (heartbeat_timer_, &QTimer::timeout, this, &impl::heartbeat);
+    connect (this, &QIODevice::readyRead, this, &impl::pending_datagrams);
+
+    heartbeat_timer_->start (NetworkMessage::pulse * 1000);
+
+    // bind to an ephemeral port
+    bind ();
+  }
+
+  ~impl ()
+  {
+    closedown ();
+  }
+
+  enum StreamStatus {Fail, Short, OK};
+
+  void parse_message (QByteArray const& msg);
+  void pending_datagrams ();
+  void heartbeat ();
+  void closedown ();
+  StreamStatus check_status (QDataStream const&) const;
+
+  Q_SLOT void host_info_results (QHostInfo);
+
+  MessageClient * self_;
+  QString id_;
+  QHostAddress server_;
+  port_type server_port_;
+  QTimer * heartbeat_timer_;
+};
+
+#include "MessageClient.moc"
+
+void MessageClient::impl::host_info_results (QHostInfo host_info)
+{
+  if (QHostInfo::NoError != host_info.error ())
+    {
+      Q_EMIT self_->error ("UDP server lookup failed:\n" + host_info.errorString ());
+    }
+  else if (host_info.addresses ().size ())
+    {
+      server_ = host_info.addresses ()[0];
+    }
+}
+
+void MessageClient::impl::pending_datagrams ()
+{
+  while (hasPendingDatagrams ())
+    {
+      QByteArray datagram;
+      datagram.resize (pendingDatagramSize ());
+      QHostAddress sender_address;
+      port_type sender_port;
+      if (0 <= readDatagram (datagram.data (), datagram.size (), &sender_address, &sender_port))
+        {
+          parse_message (datagram);
+        }
+    }
+}
+
+void MessageClient::impl::parse_message (QByteArray const& msg)
+{
+  try
+    {
+      // 
+      // message format is described in NetworkMessage.hpp
+      // 
+      NetworkMessage::Reader in {msg};
+
+      if (OK == check_status (in) && id_ == in.id ()) // OK and for us
+        {
+          //
+          // message format is described in NetworkMessage.hpp
+          //
+          switch (in.type ())
+            {
+            case NetworkMessage::Reply:
+              {
+                // unpack message
+                QTime time;
+                qint32 snr;
+                float delta_time;
+                quint32 delta_frequency;
+                QByteArray mode;
+                QByteArray message;
+                in >> time >> snr >> delta_time >> delta_frequency >> mode >> message;
+                if (check_status (in) != Fail)
+                  {
+                    Q_EMIT self_->reply (time, snr, delta_time, delta_frequency
+                                         , QString::fromUtf8 (mode), QString::fromUtf8 (message));
+                  }
+              }
+              break;
+
+            case NetworkMessage::Replay:
+              if (check_status (in) != Fail)
+                {
+                  Q_EMIT self_->replay ();
+                }
+              break;
+
+            case NetworkMessage::HaltTx:
+              {
+                bool auto_only {false};
+                in >> auto_only;
+                if (check_status (in) != Fail)
+                  {
+                    Q_EMIT self_->halt_tx (auto_only);
+                  }
+              }
+              break;
+
+            case NetworkMessage::FreeText:
+              {
+                QByteArray message;
+                bool send {true};
+                in >> message >> send;
+                if (check_status (in) != Fail)
+                  {
+                    Q_EMIT self_->free_text (QString::fromUtf8 (message), send);
+                  }
+              }
+              break;
+
+            default:
+              // Ignore
+              break;
+            }
+        }
+    }
+  catch (std::exception const& e)
+    {
+      Q_EMIT self_->error (QString {"MessageClient exception: %1"}.arg (e.what ()));
+    }
+  catch (...)
+    {
+      Q_EMIT self_->error ("Unexpected exception in MessageClient");
+    }
+}
+
+void MessageClient::impl::heartbeat ()
+{
+   if (server_port_ && !server_.isNull ())
+    {
+      QByteArray message;
+      NetworkMessage::Builder hb {&message, NetworkMessage::Heartbeat, id_};
+      if (OK == check_status (hb))
+        {
+          writeDatagram (message, server_, server_port_);
+        }
+    }
+}
+
+void MessageClient::impl::closedown ()
+{
+   if (server_port_ && !server_.isNull ())
+    {
+      QByteArray message;
+      NetworkMessage::Builder out {&message, NetworkMessage::Close, id_};
+      if (OK == check_status (out))
+        {
+          writeDatagram (message, server_, server_port_);
+        }
+    }
+}
+
+auto MessageClient::impl::check_status (QDataStream const& stream) const -> StreamStatus
+{
+  auto stat = stream.status ();
+  StreamStatus result {Fail};
+  switch (stat)
+    {
+    case QDataStream::ReadPastEnd:
+      qDebug () << __PRETTY_FUNCTION__ << " warning: short UDP message received.";
+      result = Short;
+      break;
+
+    case QDataStream::ReadCorruptData:
+      Q_EMIT self_->error ("Message serialization error: read corrupt data");
+      break;
+
+    case QDataStream::WriteFailed:
+      Q_EMIT self_->error ("Message serialization error: write error");
+      break;
+
+    default:
+      result = OK;
+      break;
+    }
+  return result;
+}
+
+MessageClient::MessageClient (QString const& id, QString const& server, port_type server_port, QObject * self)
+  : QObject {self}
+  , m_ {id, server_port, this}
+{
+  connect (&*m_, static_cast<void (impl::*) (impl::SocketError)> (&impl::error)
+           , [this] (impl::SocketError /* e */)
+           {
+             Q_EMIT error (m_->errorString ());
+           });
+  set_server (server);
+}
+
+QHostAddress MessageClient::server_address () const
+{
+  return m_->server_;
+}
+
+auto MessageClient::server_port () const -> port_type
+{
+  return m_->server_port_;
+}
+
+void MessageClient::set_server (QString const& server)
+{
+  m_->server_.clear ();
+  if (!server.isEmpty ())
+    {
+      // queue a host address lookup
+      QHostInfo::lookupHost (server, &*m_, SLOT (host_info_results (QHostInfo)));
+    }
+}
+
+void MessageClient::set_server_port (port_type server_port)
+{
+  m_->server_port_ = server_port;
+}
+
+void MessageClient::send_raw_datagram (QByteArray const& message, QHostAddress const& dest_address
+                                       , port_type dest_port)
+{
+  if (dest_port && !dest_address.isNull ())
+    {
+      m_->writeDatagram (message, dest_address, dest_port);
+    }
+}
+
+void MessageClient::status_update (Frequency f, QString const& mode, QString const& dx_call
+                                   , QString const& report, QString const& tx_mode
+                                   , bool tx_enabled, bool transmitting)
+{
+   if (m_->server_port_ && !m_->server_.isNull ())
+    {
+      QByteArray message;
+      NetworkMessage::Builder out {&message, NetworkMessage::Status, m_->id_};
+      out << f << mode.toUtf8 () << dx_call.toUtf8 () << report.toUtf8 () << tx_mode.toUtf8 ()
+          << tx_enabled << transmitting;
+      if (impl::OK == m_->check_status (out))
+        {
+          m_->writeDatagram (message, m_->server_, m_->server_port_);
+        }
+      else
+        {
+          Q_EMIT error ("Error creating UDP message");
+        }
+    }
+}
+
+void MessageClient::decode (bool is_new, QTime time, qint32 snr, float delta_time, quint32 delta_frequency
+                            , QString const& mode, QString const& message_text)
+{
+   if (m_->server_port_ && !m_->server_.isNull ())
+    {
+      QByteArray message;
+      NetworkMessage::Builder out {&message, NetworkMessage::Decode, m_->id_};
+      out << is_new << time << snr << delta_time << delta_frequency << mode.toUtf8 () << message_text.toUtf8 ();
+      if (impl::OK == m_->check_status (out))
+        {
+          m_->writeDatagram (message, m_->server_, m_->server_port_);
+        }
+      else
+        {
+          Q_EMIT error ("Error creating UDP message");
+        }
+    }
+}
+
+void MessageClient::clear_decodes ()
+{
+   if (m_->server_port_ && !m_->server_.isNull ())
+    {
+      QByteArray message;
+      NetworkMessage::Builder out {&message, NetworkMessage::Clear, m_->id_};
+      if (impl::OK == m_->check_status (out))
+        {
+          m_->writeDatagram (message, m_->server_, m_->server_port_);
+        }
+      else
+        {
+          Q_EMIT error ("Error creating UDP message");
+        }
+    }
+}
+
+void MessageClient::qso_logged (QDateTime time, QString const& dx_call, QString const& dx_grid
+                                , Frequency dial_frequency, QString const& mode, QString const& report_sent
+                                , QString const& report_received, QString const& tx_power
+                                , QString const& comments, QString const& name)
+{
+   if (m_->server_port_ && !m_->server_.isNull ())
+    {
+      QByteArray message;
+      NetworkMessage::Builder out {&message, NetworkMessage::QSOLogged, m_->id_};
+      out << time << dx_call.toUtf8 () << dx_grid.toUtf8 () << dial_frequency << mode.toUtf8 ()
+          << report_sent.toUtf8 () << report_received.toUtf8 () << tx_power.toUtf8 () << comments.toUtf8 () << name.toUtf8 ();
+      if (impl::OK == m_->check_status (out))
+        {
+          m_->writeDatagram (message, m_->server_, m_->server_port_);
+        }
+      else
+        {
+          Q_EMIT error ("Error creating UDP message");
+        }
+    }
+}
diff --git a/MessageClient.hpp b/MessageClient.hpp
new file mode 100644
index 0000000..89bca3e
--- /dev/null
+++ b/MessageClient.hpp
@@ -0,0 +1,89 @@
+#ifndef MESSAGE_CLIENT_HPP__
+#define MESSAGE_CLIENT_HPP__
+
+#include <QObject>
+#include <QHostAddress>
+#include <QTime>
+#include <QDateTime>
+#include <QString>
+#include <QByteArray>
+
+#include "Radio.hpp"
+#include "pimpl_h.hpp"
+
+//
+// MessageClient - Manage messages sent and replies received from a
+//              	 matching server (MessageServer) at the other end of
+//								 the wire
+//
+//
+// Each outgoing message type is a Qt slot
+//
+class MessageClient
+  : public QObject
+{
+  Q_OBJECT;
+
+public:
+  using Frequency = Radio::Frequency;
+  using port_type = quint16;
+
+  // instantiate and initiate a host lookup on the server
+  //
+  // messages will be silently dropped until a server host lookup is complete
+  MessageClient (QString const& id, QString const& server, port_type server_port, QObject * parent = nullptr);
+
+  // query server details
+  QHostAddress server_address () const;
+  port_type server_port () const;
+
+  // initiate a new server host lookup or is the server name is empty
+  // the sending of messages is disabled
+  Q_SLOT void set_server (QString const& server = QString {});
+
+  // change the server port messages are sent to
+  Q_SLOT void set_server_port (port_type server_port = 0u);
+
+  // outgoing messages
+  Q_SLOT void status_update (Frequency, QString const& mode, QString const& dx_call, QString const& report
+                             , QString const& tx_mode, bool tx_enabled, bool transmitting);
+  Q_SLOT void decode (bool is_new, QTime time, qint32 snr, float delta_time, quint32 delta_frequency
+                      , QString const& mode, QString const& message);
+  Q_SLOT void clear_decodes ();
+  Q_SLOT void qso_logged (QDateTime time, QString const& dx_call, QString const& dx_grid
+                          , Frequency dial_frequency, QString const& mode, QString const& report_sent
+                          , QString const& report_received, QString const& tx_power, QString const& comments
+                          , QString const& name);
+
+  // this slot may be used to send arbitrary UDP datagrams to and
+  // destination allowing the underlying socket to be used for general
+  // UDP messaging if desired
+  Q_SLOT void send_raw_datagram (QByteArray const&, QHostAddress const& dest_address, port_type dest_port);
+
+  // this signal is emitted if the server sends us a reply, the only
+  // reply supported is reply to a prior CQ or QRZ message
+  Q_SIGNAL void reply (QTime, qint32 snr, float delta_time, quint32 delta_frequency, QString const& mode
+                       , QString const& message_text);
+
+  // this signal is emitted if the server has requested a replay of
+  // all decodes
+  Q_SIGNAL void replay ();
+
+  // this signal is emitted if the server has requested immediate (or
+  // auto Tx if auto_only is true) transmission to halt
+  Q_SIGNAL void halt_tx (bool auto_only);
+
+  // this signal is emitted if the server has requested a new free
+  // message text
+  Q_SIGNAL void free_text (QString const&, bool send);
+
+  // this signal is emitted when network errors occur or if a host
+  // lookup fails
+  Q_SIGNAL void error (QString const&) const;
+
+private:
+  class impl;
+  pimpl<impl> m_;
+};
+
+#endif
diff --git a/MessageServer.cpp b/MessageServer.cpp
new file mode 100644
index 0000000..7770816
--- /dev/null
+++ b/MessageServer.cpp
@@ -0,0 +1,376 @@
+#include "MessageServer.hpp"
+
+#include <stdexcept>
+
+#include <QUdpSocket>
+#include <QTimer>
+#include <QHash>
+
+#include "NetworkMessage.hpp"
+#include "qt_helpers.hpp"
+
+#include "pimpl_impl.hpp"
+
+#include "moc_MessageServer.cpp"
+
+class MessageServer::impl
+  : public QUdpSocket
+{
+  Q_OBJECT;
+
+public:
+  impl (MessageServer * self)
+    : self_ {self}
+    , port_ {0u}
+    , clock_ {new QTimer {this}}
+  {
+    connect (this, &QIODevice::readyRead, this, &MessageServer::impl::pending_datagrams);
+    connect (this, static_cast<void (impl::*) (SocketError)> (&impl::error)
+             , [this] (SocketError /* e */)
+             {
+               Q_EMIT self_->error (errorString ());
+             });
+    connect (clock_, &QTimer::timeout, this, &impl::tick);
+    clock_->start (NetworkMessage::pulse * 1000);
+  }
+
+  enum StreamStatus {Fail, Short, OK};
+
+  void leave_multicast_group ();
+  void join_multicast_group ();
+  void parse_message (QHostAddress const& sender, port_type sender_port, QByteArray const& msg);
+  void tick ();
+  void pending_datagrams ();
+  StreamStatus check_status (QDataStream const&) const;
+
+  MessageServer * self_;
+  port_type port_;
+  QHostAddress multicast_group_address_;
+  static BindMode const bind_mode_;
+  struct Client
+  {
+    QHostAddress sender_address_;
+    port_type sender_port_;
+    QDateTime last_activity_;
+  };
+  QHash<QString, Client> clients_; // maps id to Client
+  QTimer * clock_;
+};
+
+#include "MessageServer.moc"
+
+MessageServer::impl::BindMode const MessageServer::impl::bind_mode_ = ShareAddress | ReuseAddressHint;
+
+void MessageServer::impl::leave_multicast_group ()
+{
+  if (!multicast_group_address_.isNull () && BoundState == state ())
+    {
+      leaveMulticastGroup (multicast_group_address_);
+    }
+}
+
+void MessageServer::impl::join_multicast_group ()
+{
+  if (BoundState == state ()
+      && !multicast_group_address_.isNull ())
+    {
+      if (IPv4Protocol == multicast_group_address_.protocol ()
+          && IPv4Protocol != localAddress ().protocol ())
+        {
+          close ();
+          bind (QHostAddress::AnyIPv4, port_, bind_mode_);
+        }
+      if (!joinMulticastGroup (multicast_group_address_))
+        {
+          multicast_group_address_.clear ();
+        }
+    }
+}
+
+void MessageServer::impl::pending_datagrams ()
+{
+  while (hasPendingDatagrams ())
+    {
+      QByteArray datagram;
+      datagram.resize (pendingDatagramSize ());
+      QHostAddress sender_address;
+      port_type sender_port;
+      if (0 <= readDatagram (datagram.data (), datagram.size (), &sender_address, &sender_port))
+        {
+          parse_message (sender_address, sender_port, datagram);
+        }
+    }
+}
+
+void MessageServer::impl::parse_message (QHostAddress const& sender, port_type sender_port, QByteArray const& msg)
+{
+  try
+    {
+      //
+      // message format is described in NetworkMessage.hpp
+      //
+      NetworkMessage::Reader in {msg};
+
+      auto id = in.id ();
+      if (OK == check_status (in))
+        {
+          bool new_client {false};
+          if (!clients_.contains (id))
+            {
+              new_client = true;
+            }
+          clients_[id] = {sender, sender_port, QDateTime::currentDateTime ()};
+          if (new_client)
+            {
+              Q_EMIT self_->client_opened (id);
+            }
+  
+          //
+          // message format is described in NetworkMessage.hpp
+          //
+          switch (in.type ())
+            {
+            case NetworkMessage::Heartbeat:
+              //nothing to do here as time out handling deals with lifetime
+              break;
+
+            case NetworkMessage::Clear:
+              Q_EMIT self_->clear_decodes (id);
+              break;
+
+            case NetworkMessage::Status:
+              {
+                // unpack message
+                Frequency f;
+                QByteArray mode;
+                QByteArray dx_call;
+                QByteArray report;
+                QByteArray tx_mode;
+                bool tx_enabled {false};
+                bool transmitting {false};
+                in >> f >> mode >> dx_call >> report >> tx_mode >> tx_enabled >> transmitting;
+                if (check_status (in) != Fail)
+                  {
+                    Q_EMIT self_->status_update (id, f, QString::fromUtf8 (mode), QString::fromUtf8 (dx_call)
+                                                 , QString::fromUtf8 (report), QString::fromUtf8 (tx_mode)
+                                                 , tx_enabled, transmitting);
+                  }
+              }
+              break;
+
+            case NetworkMessage::Decode:
+              {
+                // unpack message
+                bool is_new {true};
+                QTime time;
+                qint32 snr;
+                float delta_time;
+                quint32 delta_frequency;
+                QByteArray mode;
+                QByteArray message;
+                in >> is_new >> time >> snr >> delta_time >> delta_frequency >> mode >> message;
+                if (check_status (in) != Fail)
+                  {
+                    Q_EMIT self_->decode (is_new, id, time, snr, delta_time, delta_frequency
+                                          , QString::fromUtf8 (mode), QString::fromUtf8 (message));
+                  }
+              }
+              break;
+
+            case NetworkMessage::QSOLogged:
+              {
+                QDateTime time;
+                QByteArray dx_call;
+                QByteArray dx_grid;
+                Frequency dial_frequency;
+                QByteArray mode;
+                QByteArray report_sent;
+                QByteArray report_received;
+                QByteArray tx_power;
+                QByteArray comments;
+                QByteArray name;
+                in >> time >> dx_call >> dx_grid >> dial_frequency >> mode >> report_sent >> report_received
+                   >> tx_power >> comments >> name;
+                if (check_status (in) != Fail)
+                  {
+                    Q_EMIT self_->qso_logged (id, time, QString::fromUtf8 (dx_call), QString::fromUtf8 (dx_grid)
+                                              , dial_frequency, QString::fromUtf8 (mode), QString::fromUtf8 (report_sent)
+                                              , QString::fromUtf8 (report_received), QString::fromUtf8 (tx_power)
+                                              , QString::fromUtf8 (comments), QString::fromUtf8 (name));
+                  }
+              }
+              break;
+
+            case NetworkMessage::Close:
+              if (check_status (in) != Fail)
+                {
+                  Q_EMIT self_->client_closed (id);
+                  clients_.remove (id);
+                }
+              break;
+
+            default:
+              // Ignore
+              break;
+            }
+        }
+      else
+        {
+          Q_EMIT self_->error ("MessageServer warning: invalid UDP message received");
+        }
+    }
+  catch (std::exception const& e)
+    {
+      Q_EMIT self_->error (QString {"MessageServer exception: %1"}.arg (e.what ()));
+    }
+  catch (...)
+    {
+      Q_EMIT self_->error ("Unexpected exception in MessageServer");
+    }
+}
+
+void MessageServer::impl::tick ()
+{
+  auto now = QDateTime::currentDateTime ();
+  for (auto iter = std::begin (clients_); iter != std::end (clients_); ++iter)
+    {
+      if (now > (*iter).last_activity_.addSecs (NetworkMessage::pulse))
+        {
+          Q_EMIT self_->clear_decodes (iter.key ());
+          Q_EMIT self_->client_closed (iter.key ());
+          clients_.erase (iter); // safe while iterating as doesn't rehash
+        }
+    }
+}
+
+auto MessageServer::impl::check_status (QDataStream const& stream) const -> StreamStatus
+{
+  auto stat = stream.status ();
+  StreamStatus result {Fail};
+  switch (stat)
+    {
+    case QDataStream::ReadPastEnd:
+      qDebug () << __PRETTY_FUNCTION__ << " warning: short UDP message received.";
+      result = Short;
+      break;
+
+    case QDataStream::ReadCorruptData:
+      Q_EMIT self_->error ("Message serialization error: read corrupt data");
+      break;
+
+    case QDataStream::WriteFailed:
+      Q_EMIT self_->error ("Message serialization error: write error");
+      break;
+
+    default:
+      result = OK;
+      break;
+    }
+  return result;
+}
+
+MessageServer::MessageServer (QObject * parent)
+  : QObject {parent}
+  , m_ {this}
+{
+}
+
+void MessageServer::start (port_type port, QHostAddress const& multicast_group_address)
+{
+  if (port != m_->port_
+      || multicast_group_address != m_->multicast_group_address_)
+    {
+      m_->leave_multicast_group ();
+      if (impl::BoundState == m_->state ())
+        {
+          m_->close ();
+        }
+      m_->multicast_group_address_ = multicast_group_address;
+      auto address = m_->multicast_group_address_.isNull ()
+        || impl::IPv4Protocol != m_->multicast_group_address_.protocol () ? QHostAddress::Any : QHostAddress::AnyIPv4;
+      if (port && m_->bind (address, port, m_->bind_mode_))
+        {
+          m_->port_ = port;
+          m_->join_multicast_group ();
+        }
+      else
+        {
+          m_->port_ = 0;
+        }
+    }
+}
+
+void MessageServer::reply (QString const& id, QTime time, qint32 snr, float delta_time, quint32 delta_frequency, QString const& mode, QString const& message_text)
+{
+  auto iter = m_->clients_.find (id);
+  if (iter != std::end (m_->clients_))
+    {
+      QByteArray message;
+      NetworkMessage::Builder out {&message, NetworkMessage::Reply, id};
+      out << time << snr << delta_time << delta_frequency << mode.toUtf8 () << message_text.toUtf8 ();
+      if (impl::OK == m_->check_status (out))
+        {
+          m_->writeDatagram (message, iter.value ().sender_address_, (*iter).sender_port_);
+        }
+      else
+        {
+          Q_EMIT error ("Error creating UDP message");
+        }
+    }
+}
+
+void MessageServer::replay (QString const& id)
+{
+  auto iter = m_->clients_.find (id);
+  if (iter != std::end (m_->clients_))
+    {
+      QByteArray message;
+      NetworkMessage::Builder out {&message, NetworkMessage::Replay, id};
+      if (impl::OK == m_->check_status (out))
+        {
+          m_->writeDatagram (message, iter.value ().sender_address_, (*iter).sender_port_);
+        }
+      else
+        {
+          Q_EMIT error ("Error creating UDP message");
+        }
+    }
+}
+
+void MessageServer::halt_tx (QString const& id, bool auto_only)
+{
+  auto iter = m_->clients_.find (id);
+  if (iter != std::end (m_->clients_))
+    {
+      QByteArray message;
+      NetworkMessage::Builder out {&message, NetworkMessage::HaltTx, id};
+      out << auto_only;
+      if (impl::OK == m_->check_status (out))
+        {
+          m_->writeDatagram (message, iter.value ().sender_address_, (*iter).sender_port_);
+        }
+      else
+        {
+          Q_EMIT error ("Error creating UDP message");
+        }
+    }
+}
+
+void MessageServer::free_text (QString const& id, QString const& text, bool send)
+{
+  auto iter = m_->clients_.find (id);
+  if (iter != std::end (m_->clients_))
+    {
+      QByteArray message;
+      NetworkMessage::Builder out {&message, NetworkMessage::FreeText, id};
+      out << text.toUtf8 () << send;
+      if (impl::OK == m_->check_status (out))
+        {
+          m_->writeDatagram (message, iter.value ().sender_address_, (*iter).sender_port_);
+        }
+      else
+        {
+          Q_EMIT error ("Error creating UDP message");
+        }
+    }
+}
diff --git a/MessageServer.hpp b/MessageServer.hpp
new file mode 100644
index 0000000..45b9aa1
--- /dev/null
+++ b/MessageServer.hpp
@@ -0,0 +1,81 @@
+#ifndef MESSAGE_SERVER_HPP__
+#define MESSAGE_SERVER_HPP__
+
+#include <QObject>
+#include <QTime>
+#include <QDateTime>
+#include <QString>
+#include <QByteArray>
+#include <QHostAddress>
+
+#include "Radio.hpp"
+
+#include "pimpl_h.hpp"
+
+//
+// MessageServer - a reference implementation of a message server
+//                  matching the MessageClient class at the other end
+//                  of the wire
+//
+// This class is fully functioning and suitable for use in C++
+// applications that use the Qt framework. Other applications should
+// use this classes' implementation as a reference implementation.
+//
+class MessageServer
+  : public QObject
+{
+  Q_OBJECT;
+
+public:
+  using port_type = quint16;
+  using Frequency = Radio::Frequency;
+
+  MessageServer (QObject * parent = nullptr);
+
+  // start or restart the server, if the multicast_group_address
+  // argument is given it is assumed to be a multicast group address
+  // which the server will join
+  Q_SLOT void start (port_type port, QHostAddress const& multicast_group_address = QHostAddress {});
+
+  // ask the client with identification 'id' to make the same action
+  // as a double click on the decode would
+  //
+  // note that the client is not obliged to take any action and only
+  // takes any action if the decode is present and is a CQ or QRZ message
+  Q_SLOT void reply (QString const& id, QTime time, qint32 snr, float delta_time, quint32 delta_frequency
+                     , QString const& mode, QString const& message);
+
+  // ask the client with identification 'id' to replay all decodes
+  Q_SLOT void replay (QString const& id);
+
+  // ask the client with identification 'id' to halt transmitting
+  // auto_only just disables auto Tx, otherwise halt is immediate
+  Q_SLOT void halt_tx (QString const& id, bool auto_only);
+
+  // ask the client with identification 'id' to set the free text
+  // message and optionally send it ASAP
+  Q_SLOT void free_text (QString const& id, QString const& text, bool send);
+
+  // the following signals are emitted when a client broadcasts the
+  // matching message
+  Q_SIGNAL void client_opened (QString const& id);
+  Q_SIGNAL void status_update (QString const& id, Frequency, QString const& mode, QString const& dx_call
+                               , QString const& report, QString const& tx_mode, bool tx_enabled, bool transmitting);
+  Q_SIGNAL void client_closed (QString const& id);
+  Q_SIGNAL void decode (bool is_new, QString const& id, QTime time, qint32 snr, float delta_time
+                        , quint32 delta_frequency, QString const& mode, QString const& message);
+  Q_SIGNAL void qso_logged (QString const& id, QDateTime time, QString const& dx_call, QString const& dx_grid
+                            , Frequency dial_frequency, QString const& mode, QString const& report_sent
+                            , QString const& report_received, QString const& tx_power, QString const& comments
+                            , QString const& name);
+  Q_SIGNAL void clear_decodes (QString const& id);
+
+  // this signal is emitted when a network error occurs
+  Q_SIGNAL void error (QString const&) const;
+
+private:
+  class impl;
+  pimpl<impl> m_;
+};
+
+#endif
diff --git a/Modulator.cpp b/Modulator.cpp
new file mode 100644
index 0000000..30b275b
--- /dev/null
+++ b/Modulator.cpp
@@ -0,0 +1,296 @@
+#include "Modulator.hpp"
+#include <limits>
+#include <qmath.h>
+#include <QDateTime>
+#include <QDebug>
+#include "mainwindow.h"
+
+#include "moc_Modulator.cpp"
+
+extern float gran();		// Noise generator (for tests only)
+
+#define RAMP_INCREMENT 64  // MUST be an integral factor of 2^16
+
+#if defined (WSJT_SOFT_KEYING)
+# define SOFT_KEYING WSJT_SOFT_KEYING
+#else
+# define SOFT_KEYING 1
+#endif
+
+double const Modulator::m_twoPi = 2.0 * 3.141592653589793238462;
+
+//    float wpm=20.0;
+//    unsigned m_nspd=1.2*48000.0/wpm;
+//    m_nspd=3072;                           //18.75 WPM
+unsigned const Modulator::m_nspd = 2048 + 512; // 22.5 WPM
+
+Modulator::Modulator (unsigned frameRate, unsigned periodLengthInSeconds, QObject * parent)
+  : AudioDevice {parent}
+  , m_stream {nullptr}
+  , m_quickClose {false}
+  , m_phi {0.0}
+  , m_toneSpacing {0.0}
+  , m_fSpread {0.0}
+  , m_frameRate {frameRate}
+  , m_period {periodLengthInSeconds}
+  , m_state {Idle}
+  , m_tuning {false}
+  , m_cwLevel {false}
+{
+  qsrand (QDateTime::currentMSecsSinceEpoch()); // Initialize random
+                                                // seed
+}
+
+void Modulator::start (unsigned symbolsLength, double framesPerSymbol, unsigned frequency, double toneSpacing, SoundOutput * stream, Channel channel, bool synchronize, double dBSNR)
+{
+  Q_ASSERT (stream);
+
+  // Time according to this computer which becomes our base time
+  qint64 ms0 = QDateTime::currentMSecsSinceEpoch() % 86400000;
+
+  // qDebug () << "Modulator: Using soft keying for CW is " << SOFT_KEYING;;
+
+  if (m_state != Idle)
+    {
+      stop ();
+    }
+
+  m_quickClose = false;
+
+  m_symbolsLength = symbolsLength;
+  m_isym0 = std::numeric_limits<unsigned>::max (); // Arbitrary big
+                                                   // number
+  m_frequency0 = 0.;
+  m_addNoise = dBSNR < 0.;
+  m_nsps = framesPerSymbol;
+  m_frequency = frequency;
+  m_amp = std::numeric_limits<qint16>::max ();
+  m_toneSpacing = toneSpacing;
+
+  // noise generator parameters
+  if (m_addNoise) {
+    m_snr = qPow (10.0, 0.05 * (dBSNR - 6.0));
+    m_fac = 3000.0;
+    if (m_snr > 1.0) m_fac = 3000.0 / m_snr;
+  }
+
+  unsigned mstr = ms0 % (1000 * m_period); // ms in period
+  m_ic = (mstr / 1000) * m_frameRate; // we start exactly N seconds
+  // into period where N is the next whole second
+
+  m_silentFrames = 0;
+  // calculate number of silent frames to send
+  if (synchronize && !m_tuning)	{
+    m_silentFrames = m_ic + m_frameRate - (mstr * m_frameRate / 1000);
+  }
+
+  //  qDebug () << "Modulator: starting at " << m_ic / m_frameRate << " sec, sending " << m_silentFrames << " silent frames";
+
+  initialize (QIODevice::ReadOnly, channel);
+  Q_EMIT stateChanged ((m_state = (synchronize && m_silentFrames) ?
+                        Synchronizing : Active));
+  m_stream = stream;
+  if (m_stream)
+    {
+      m_stream->restart (this);
+    }
+}
+
+void Modulator::tune (bool newState)
+{
+  m_tuning = newState;
+  if (!m_tuning)
+    {
+      stop (true);
+    }
+}
+
+void Modulator::stop (bool quick)
+{
+  m_quickClose = quick;
+  close ();
+}
+
+void Modulator::close ()
+{
+  if (m_stream)
+    {
+      if (m_quickClose)
+        {
+          m_stream->reset ();
+        }
+      else
+        {
+          m_stream->stop ();
+        }
+    }
+  if (m_state != Idle)
+    {
+      Q_EMIT stateChanged ((m_state = Idle));
+    }
+  AudioDevice::close ();
+}
+
+qint64 Modulator::readData (char * data, qint64 maxSize)
+{
+  static int j0=-1;
+  static double toneFrequency0;
+  double toneFrequency;
+
+  if(maxSize==0) return 0;
+  Q_ASSERT (!(maxSize % qint64 (bytesPerFrame ()))); // no torn frames
+  Q_ASSERT (isOpen ());
+
+  qint64 numFrames (maxSize / bytesPerFrame ());
+  qint16 * samples (reinterpret_cast<qint16 *> (data));
+  qint16 * end (samples + numFrames * (bytesPerFrame () / sizeof (qint16)));
+  qint64 framesGenerated (0);
+
+  //  qDebug () << "Modulator: " << numFrames << " requested, m_ic = " << m_ic << ", tune mode is " << m_tuning;
+  //  qDebug() << "C" << maxSize << numFrames << bytesPerFrame();
+  switch (m_state)
+    {
+    case Synchronizing:
+      {
+        if (m_silentFrames)	{  // send silence up to first second
+          framesGenerated = qMin (m_silentFrames, numFrames);
+          for ( ; samples != end; samples = load (0, samples)) { // silence
+          }
+          m_silentFrames -= framesGenerated;
+          return framesGenerated * bytesPerFrame ();
+        }
+
+        Q_EMIT stateChanged ((m_state = Active));
+        m_cwLevel = false;
+        m_ramp = 0;		// prepare for CW wave shaping
+      }
+      // fall through
+
+    case Active:
+      {
+        unsigned isym (m_tuning ? 0 : m_ic / (4.0 * m_nsps)); // Actual fsample=48000
+        if (isym >= m_symbolsLength && icw[0] > 0) { // start CW condition
+          // Output the CW ID
+          m_dphi = m_twoPi * m_frequency / m_frameRate;
+          unsigned const ic0 = m_symbolsLength * 4 * m_nsps;
+          unsigned j (0);
+
+          while (samples != end) {
+            j = (m_ic - ic0) / m_nspd + 1; // symbol of this sample
+            bool level {bool (icw[j])};
+
+            m_phi += m_dphi;
+            if (m_phi > m_twoPi) m_phi -= m_twoPi;
+
+            qint16 sample ((SOFT_KEYING ? qAbs (m_ramp - 1) :
+                            (m_ramp ? 32767 : 0)) * qSin (m_phi));
+
+            if (int (j) <= icw[0] && j < NUM_CW_SYMBOLS) // stop condition
+              {
+                samples = load (postProcessSample (sample), samples);
+                ++framesGenerated;
+                ++m_ic;
+              }
+            else
+              {
+                Q_EMIT stateChanged ((m_state = Idle));
+                return framesGenerated * bytesPerFrame ();
+              }
+
+            // adjust ramp
+            if ((m_ramp != 0 && m_ramp != std::numeric_limits<qint16>::min ()) || level != m_cwLevel)
+              {
+                // either ramp has terminated at max/min or direction
+                // has changed
+                m_ramp += RAMP_INCREMENT; // ramp
+              }
+
+            // if (m_cwLevel != level)
+            //   {
+            //     qDebug () << "@m_ic:" << m_ic << "icw[" << j << "] =" << icw[j] << "@" << framesGenerated << "in numFrames:" << numFrames;
+            //   }
+
+            m_cwLevel = level;
+          }
+
+          return framesGenerated * bytesPerFrame ();
+        }
+
+        double const baud (12000.0 / m_nsps);
+        // fade out parameters (no fade out for tuning)
+        unsigned const i0 = m_tuning ? 999 * m_nsps :
+          (m_symbolsLength - 0.017) * 4.0 * m_nsps;
+        unsigned const i1 = m_tuning ? 999 * m_nsps :
+          m_symbolsLength * 4.0 * m_nsps;
+
+        for (unsigned i = 0; i < numFrames && m_ic <= i1; ++i) {
+          isym = m_tuning ? 0 : m_ic / (4.0 * m_nsps); //Actual fsample=48000
+          if (isym != m_isym0 || m_frequency != m_frequency0) {
+            // qDebug () << "@m_ic:" << m_ic << "itone[" << isym << "] =" << itone[isym] << "@" << i << "in numFrames:" << numFrames;
+
+            if(m_toneSpacing==0.0) {
+              toneFrequency0=m_frequency + itone[isym]*baud;
+            } else {
+              toneFrequency0=m_frequency + itone[isym]*m_toneSpacing;
+            }
+            m_dphi = m_twoPi * toneFrequency0 / m_frameRate;
+            m_isym0 = isym;
+            m_frequency0 = m_frequency;
+          }
+
+          int j=m_ic/480;
+          if(m_fSpread>0.0 and j!=j0) {
+            float x1=(float)rand()/RAND_MAX;
+            float x2=(float)rand()/RAND_MAX;
+            toneFrequency = toneFrequency0 + 0.5*m_fSpread*(x1+x2-1.0);
+            m_dphi = m_twoPi * toneFrequency / m_frameRate;
+            j0=j;
+          }
+
+          m_phi += m_dphi;
+          if (m_phi > m_twoPi) m_phi -= m_twoPi;
+          if (m_ic > i0) m_amp = 0.98 * m_amp;
+          if (m_ic > i1) m_amp = 0.0;
+
+          samples = load (postProcessSample (m_amp * qSin (m_phi)), samples);
+          ++framesGenerated;
+          ++m_ic;
+        }
+
+        if (m_amp == 0.0) { // TODO G4WJS: compare double with zero might not be wise
+          if (icw[0] == 0) {
+            // no CW ID to send
+            Q_EMIT stateChanged ((m_state = Idle));
+            return framesGenerated * bytesPerFrame ();
+          }
+
+          m_phi = 0.0;
+        }
+
+        // done for this chunk - continue on next call
+        return framesGenerated * bytesPerFrame ();
+      }
+      // fall through
+
+    case Idle:
+      break;
+    }
+
+  Q_ASSERT (Idle == m_state);
+  return 0;
+}
+
+qint16 Modulator::postProcessSample (qint16 sample) const
+{
+  if (m_addNoise) {  // Test frame, we'll add noise
+    qint32 s = m_fac * (gran () + sample * m_snr / 32768.0);
+    if (s > std::numeric_limits<qint16>::max ()) {
+      s = std::numeric_limits<qint16>::max ();
+    }
+    if (s < std::numeric_limits<qint16>::min ()) {
+      s = std::numeric_limits<qint16>::min ();
+    }
+    sample = s;
+  }
+  return sample;
+}
diff --git a/Modulator.hpp b/Modulator.hpp
new file mode 100644
index 0000000..80c900c
--- /dev/null
+++ b/Modulator.hpp
@@ -0,0 +1,84 @@
+#ifndef MODULATOR_HPP__
+#define MODULATOR_HPP__
+
+#include <QAudio>
+
+#include "AudioDevice.hpp"
+
+class SoundOutput;
+
+//
+// Input device that generates PCM audio frames that encode a message
+// and an optional CW ID.
+//
+// Output can be muted while underway, preserving waveform timing when
+// transmission is resumed.
+//
+class Modulator
+  : public AudioDevice
+{
+  Q_OBJECT;
+
+public:
+  enum ModulatorState {Synchronizing, Active, Idle};
+
+  Modulator (unsigned frameRate, unsigned periodLengthInSeconds, QObject * parent = nullptr);
+
+  void close () override;
+
+  bool isTuning () const {return m_tuning;}
+  unsigned frequency () const {return m_frequency;}
+  bool isActive () const {return m_state != Idle;}
+  void setSpread(double s) {m_fSpread=s;}
+
+  Q_SLOT void start (unsigned symbolsLength, double framesPerSymbol, unsigned frequency, double toneSpacing, SoundOutput *, Channel = Mono, bool synchronize = true, double dBSNR = 99.);
+  Q_SLOT void stop (bool quick = false);
+  Q_SLOT void tune (bool newState = true);
+  Q_SLOT void setFrequency (unsigned newFrequency) {m_frequency = newFrequency;}
+  Q_SIGNAL void stateChanged (ModulatorState) const;
+
+protected:
+  qint64 readData (char * data, qint64 maxSize);
+  qint64 writeData (char const * /* data */, qint64 /* maxSize */)
+  {
+    return -1;			// we don't consume data
+  }
+
+private:
+  qint16 postProcessSample (qint16 sample) const;
+
+  SoundOutput * m_stream;
+  bool m_quickClose;
+
+  unsigned m_symbolsLength;
+
+  static double const m_twoPi;
+  static unsigned const m_nspd;	// CW ID WPM factor
+
+  double m_phi;
+  double m_dphi;
+  double m_amp;
+  double m_nsps;
+  double volatile m_frequency;
+  double m_frequency0;
+  double m_snr;
+  double m_fac;
+  double m_toneSpacing;
+  double m_fSpread;
+
+  qint64 m_silentFrames;
+
+  unsigned m_frameRate;
+  unsigned m_period;
+  ModulatorState volatile m_state;
+
+  bool volatile m_tuning;
+  bool m_addNoise;
+
+  bool m_cwLevel;
+  unsigned m_ic;
+  unsigned m_isym0;
+  qint16 m_ramp;
+};
+
+#endif
diff --git a/NEWS b/NEWS
new file mode 100644
index 0000000..4c4048f
--- /dev/null
+++ b/NEWS
@@ -0,0 +1,1285 @@
+
+ __       __   ______      _____  ________      __    __ 
+|  \  _  |  \ /      \    |     \|        \    |  \  |  \
+| $$ / \ | $$|  $$$$$$\    \$$$$$ \$$$$$$$$    | $$  | $$
+| $$/  $\| $$| $$___\$$      | $$   | $$ ______ \$$\/  $$
+| $$  $$$\ $$ \$$    \  __   | $$   | $$|      \ >$$  $$ 
+| $$ $$\$$\$$ _\$$$$$$\|  \  | $$   | $$ \$$$$$$/  $$$$\ 
+| $$$$  \$$$$|  \__| $$| $$__| $$   | $$       |  $$ \$$\
+| $$$    \$$$ \$$    $$ \$$    $$   | $$       | $$  | $$
+ \$$      \$$  \$$$$$$   \$$$$$$     \$$        \$$   \$$
+                                                         
+                                                         
+Copyright 2001 - 2015 by Joe Taylor, K1JT.
+
+
+WSJT-X v1.5.0 Release Notice
+============================
+
+Decoder Performance Improvements
+--------------------------------
+
+The most notable change in v1.5.0 is improved speed and quality of the
+JT9 and JT65 decoders.  Algorithms have been fine-tuned, and advantage
+is taken of the multiple CPUs  found on most modern computers. Overall
+speedup factors of  three or more have been attained  since the v1.4.0
+release and more signals are being successfully decoded as well.
+
+For  those  interested, here's  a  summary  of  speed tests  of  three
+benchmark  versions  of  WSJT-X,  based on  reading  and  decoding  an
+identical  set of  10,682 *.wav  files.   The files  were recorded  on
+various bands from 160 m to 10 m; the number of decodable JT65 signals
+is typically about  5 times the number of JT9  signals.  For each test
+the program was set to "JT9+JT65"  mode with "Deepest" selected on the
+*Decode* menu.   Other setup parameters  were identical in  all cases.
+The test  computer runs Windows 7  and has an Intel  i5-2500 processor
+with 4 CPUs.
+
+Columns  labeled "JT9"  and "JT65"  in  the following  table give  the
+number of decoded signals in each  mode.  Numbers in the "Time" column
+are total  processing time  in seconds,  and columns  labaled "Factor"
+give ratios of the corresponding numbers, relative to WSJT-X v1.3.
+
+Program Version  JT9 Factor   JT65 Factor   Time Factor
+-------------------------------------------------------
+v1.3 r3673      7691  1.000  40831  1.000  14061  1.00
+v1.4.0          7693  1.000  41796  1.024  13320  1.06
+v1.5.0-rc1      8024  1.043  43946  1.076   4224  3.32
+
+On the  benchmark computer the  decoder in  v1.5.0-rc1 is more  than 3
+times faster than the ones in  program releases v1.3 r3673 and v1.4.0.
+At the  same time, the number  of decoded signals has  increased by as
+much as 7.6%.
+
+Users will notice another consequence  of taking advantage of multiple
+CPUs.  JT65  and JT9 decodes in  dual "JT9+JT65" mode are  now done in
+parallel, so decodes  are delivered to the Rx activity  window as they
+are decoded rather than finishing the current mode before starting the
+other mode.   Decoding at the  QSO frequency is still  given priority,
+but it may not be the first decode displayed because the first decodes
+of the other mode may be produced more quickly.  Dual mode decodes are
+now interleaved in the Rx activity window.
+
+
+UDP Broadcast
+-------------
+
+WSJT-X v1.5.0 introduces a new facility that broadcasts status, decode
+and logged  QSO information  via the  network. Although  this facility
+gives  no obvious  change  to the  application other  than  a few  new
+settings options, it should allow cooperating applications to interact
+with WSJT-X  far more smoothly  than the current file  based mechanism
+which  is prone  to  contention.  The file  access  contention can  be
+detrimental to both WSJT-X and the cooperating application whereas the
+new broadcast mechanism will not.
+
+Currently the only only cooperating application we know of is JTAlertX
+by Laurie VK3AMA and that currently  uses the file based mechanism. We
+hope that  Laurie will try the  new mechanism but we  will continue to
+provide the file based mechanism as well. We also know of at least one
+other application in development for the Apple Mac platform to provide
+similar features to  JTAlertX. A contribution for Linux  would also be
+most welcome.
+
+
+Rig Control
+-----------
+
+This continues  to be  an area  of development.  There are  still many
+untested combinations of equipment since we  have to wait until a user
+tries WSJT-X for the first time with each combination before we can be
+sure that any defects have been  removed. Hundreds of hours of testing
+have been done and we thank those who have reported issues and offered
+their time to test fixes where necessary.
+
+
+FlexRadio & HPSDR Users
+-----------------------
+
+Currently the  Hamlib library that  we use  for direct CAT  control of
+your  rigs does  not  provide  a fully  functioning  driver for  these
+radios. Instead the TS-2000 emulation mode  of these SDRs must be used
+as the Hamlib driver for this  has tweaks added to cooperate correctly
+with SDRs.  Version  v1.4 of WSJT-X did not work  with these radios in
+TS-2000 emulation mode  and at the time we were  not informed of that,
+it  appears to  have become  common  knowledge that  using the  TS-480
+emulation mode was  the correct procedure, this  is incorrect although
+it did work at the time.  The  TS-480 emulation may cease to work in a
+future version because it  is due to a defect in  Hamlib that it works
+at all. The TS-2000 emulation mode is the correct selection and should
+be used with these radios.
+
+
+Generated Messages for Type 1 and Type 2 Compound Callsigns
+-----------------------------------------------------------
+
+This is  a complex  area because  it requires  special action  by both
+parties in a  QSO since the automatically  generated standard messages
+are not always suitable. We have tried to improve the standard message
+generation and recognition  along with better recognition  of own call
+messages. As before it is imperative that operators take note of their
+QSO partners responses  and be prepared to manually  edit replies when
+communicating with compound callsign stations.
+
+
+                                                         
+
+WSJT-X v1.4.0 Release Notice
+============================
+
+Migration of User Files
+-----------------------
+
+This  release includes  a new  install mechanism  that separates  user
+files  from installation  and  program files.  This  means that  going
+forward  upgrades  will be  seamless  with  user files  preserved  and
+automatically  carried forward  without  user  intervention. For  this
+release only it  is necessary to move your user  files manually if you
+wish to  preserve them. The locations  of user files have  changed and
+now vary depending  on the installation platform.  The following notes
+are intended  to guide you  in moving your user  files, this is  a one
+time action.
+
+On Microsoft Windows:
+
+The  new  location  for  user  files is  %LOCALAPPDATA%  which  is  an
+environment variable defined automatically by Windows, you may use the
+environment variable  any place  where a file  path would  normally be
+used e.g.   in the location entry  bar in Windows File  Explorer or in
+arguments to command line programs from a Command Prompt window.
+
+On Linux and other Unix systems:
+
+The new location for user files ~/.local/share
+
+On Mac:
+
+The new location for user files is ~/Library/Application\ Support
+
+In all cases  the files are stored in a  subdirectory which by default
+is WSJT-X
+
+In the case of users who run  multiple instances of WSJT-X on a single
+computer   there  are   different   user  file   locations  for   each
+instance. The non-default locations are in sibling subdirectories each
+suffixed by  the rig name  argument passed  to WSJT-X at  startup (See
+Running Multiple Instances below).
+
+The user  files that you  may wish to  migrate from older  versions of
+WSJT-X are:
+
+  ALL.TXT
+  CALL3.TXT
+  wsjtx.log
+  wsjtx_log.adi
+
+The format of each  of these files is unchanged in  WSJT-X v1.4 so all
+that is  needed is to  copy them to the  new location.
+
+For example on  Microsoft Windows assuming a  WSJT-X v1.3 installation
+in C:\WSJT\wsjtx-1.3, using a command prompt window:
+
+  copy C:\WSJT\wsjtx-1.3\ALL.TXT %LOCALAPPDATA%\WSJT-X\
+  copy C:\WSJT\wsjtx-1.3\CALL3.TXT %LOCALAPPDATA%\WSJT-X\
+  copy C:\WSJT\wsjtx-1.3\wsjtx.log %LOCALAPPDATA%\WSJT-X\
+  copy C:\WSJT\wsjtx-1.3\wsjtx_log.adi %LOCALAPPDATA%\WSJT-X\
+
+On Linux:
+
+  cp ~/wsjtx-1.3/ALL.TXT ~/.local/share/WSJT-X/
+  cp ~/wsjtx-1.3/CALL3.TXT ~/.local/share/WSJT-X/
+  cp ~/wsjtx-1.3/wsjtx.log ~/.local/share/WSJT-X/
+  cp ~/wsjtx-1.3/wsjtx_log.adi ~/.local/share/WSJT-X/
+
+On Mac:
+
+  cp ~/wsjtx-1.3/ALL.TXT ~/Library/Application\ Support/WSJT-X/
+  cp ~/wsjtx-1.3/CALL3.TXT ~/Library/Application\ Support/WSJT-X/
+  cp ~/wsjtx-1.3/wsjtx.log ~/Library/Application\ Support/WSJT-X/
+  cp ~/wsjtx-1.3/wsjtx_log.adi ~/Library/Application\ Support/WSJT-X/
+
+If you have a customized cty.dat  file installed, then that too should
+be copied to the new directory.
+
+
+Settings
+--------
+
+WSJT-X v1.4 introduces a new settings  regime. There is no facility to
+migrate  settings  from  prior  versions  and  copying  the  wsjtx.ini
+settings file to  the new user files location will  not carry over any
+useful information.   The new settings  dialog is very  different from
+prior versions but it is intuitive and will not take long to configure
+for you equipment and preferences.
+
+
+Running Multiple Instances
+--------------------------
+
+For users  with multiple radios  or multi-receiver SDRs  WSJT-X offers
+multiple  instance  support.   Prior  to  WSJT-X  v1.4  this  involved
+installing the application multiple  times in separate locations, this
+is  no longer  necessary and  multiple instances  MUST be  run from  a
+single installation. This is possible  as user and other writable data
+files are stored in a unique location for each instance.
+
+WSJT-X  has  a  new  command line  option  that  coordinates  multiple
+instances called --rig-name (-r for  short) which allow you to specify
+a unique key for each instance.  If no --rig-name option is supplied a
+default  location is  used  for  writable files  as  specified in  the
+Migrating of User  Files section above. If a key  is provided then the
+same key  must be used  every time that instance  is started so  as to
+associate it with the correct data files.
+
+If the  unique key were ft-857  then you must start  WSJT-X using that
+key e.g.
+
+   wsjtx --rig-name=ft-857
+
+and the data files will be stored in a directory "WSJT-X - ft-857" for
+example on Windows:
+
+   "%LOCALAPPDATA%\WSJT-X - ft-857\"
+
+Multiple instance support  may also be used if more  than one operator
+uses the same computer with their own call signs, or a single operator
+who  operates  in multiple  locations  with  different call  signs  or
+wishing to maintain separate log files for each location.
+
+
+Known Issues
+------------
+
+Editing station details in the  frequencies tab of the settings window
+may not  save the changes to  the settings file. Updates  will show in
+the settings tables until application exit  but may not be used by the
+application.  A workaround  is  available, delete  the  whole row  and
+re-enter  the details  rather  than editing  individual fields.   This
+defect is resolved in the next release (v1.5).
+
+
+
+
+			WSJT-X ChangeLog
+------------------------------------------------------------------
+October 7, 2013: Version 1.2.1, r3590
+
+Windows Vista has a broken rate converter which gets invoked when an
+input audio stream at 48kHz sample rate is requested.  To correct this
+problem, WSJT-X revision 3590 reverts to input sampling at 12000 Hz by
+default when run under Vista.  All other platforms use 48000 Hz sample
+rate for both input and output.
+
+October 3, 2013: Version 1.2.1, r3587
+
+1. Input sample rate is now uniformly 48000 Hz on all supported
+platforms.
+
+2. Properly handle DNS lookup failures for PSKreporter site.
+
+3. Clear the logbook "Name" field after logging a QSO.
+
+4. Add tuning paramegters for better audio performance on some machines.
+
+5. Improved handling of displayed text when larger fonts are used.
+
+6. Fix message truncation when a callsign is unexpectedly long.
+
+7. Fix the "stuck decode" bug experienced by some users.
+
+8. Remove the bogus error message sometimes printed upon program exit.
+
+
+August 17, 2013: Version 1.2, r3563
+------------------------------------
+Changes since revision 3556 include the following:
+
+1. Fix bug preventing program restart with "+2 kHz" already set.
+
+2. Fix bug causing problems if program is installed in a directory
+with embedded space(s) in the name.
+
+3. Fixed an audio input problem (seen on some computers) by moving
+audio input to the audio thread, running at High Priority.
+
+4. Re-enabled the capability for running multiple instances.
+
+August 16, 2013: Version 1.2, r3556
+------------------------------------
+Changes since code revision 3520 include the following:
+
+1. Audio I/O now uses Qt's built-in multimedia library inatead of
+PortAudio.  User options are provided for input (mono/left/right) and
+output (mono/left/right/both), and a digital attenuation slider to
+control Tx audio level.  In "Split Tx" mode, Tx signals are now
+cleaner because Tx audio is constrained to the range 1500 - 2000 Hz.
+
+2. Windows reports to PSKReporter now use our own code, rather than
+PSKReporter.dll.
+
+3. Many new optional palettes for waterfall colors, selectable from a
+drop-down list on the Wide Graph window.
+
+4. Fixed bug causing misalignment of Cumulative spectrum when start
+frequency is not 0.  Decoding begins at start frequency rather than 
+0 Hz.
+
+5. Tx message #6 is now selected at program startup.
+
+6. Faster logbook lookup when "Show DXCC entity and worked B4 status"
+is selected.  Also better ADIF compatibility and better text alignment
+in left and right text windows.
+
+7. Improved Tool Tips for on-screen controls.
+
+8. Various other code changes for uniformity across platforms, ease of
+maintenance, and good programming practice.  (Most of these will be
+invisible to users.)
+
+9. Program is now built with the latest Qt, version 5.1.
+
+10. Updates to User's Guide.
+
+
+August 2, 2013: Version 1.1.1, r3520
+------------------------------------
+Improvements since Version 1.1, r3496 include the following:
+
+1. New organization of the "Band Settings" tab on the configuration
+screen, including antenna descriptions for PSK Reporter on a "per
+band" basis.
+
+2. Full control is provided for DTR and RTS lines on the serial port
+used for CAT control.
+
+3. Optional user control of font sizes.  Use a text editor to create a
+file "fonts.txt" in the WSJT-X installation directory.  It should have
+four numbers on a single line.  The first two are point size and
+weight (0-100 scale) for GUI labels, the next two are point size and
+weight for the decoded text windows.  For example, try "9 50 12 100".
+
+4. New user control at bottom of Wide Graph window sets the start
+frequency of the waterfall scale.
+
+5. New optional palette "gray1" for the waterfall.
+
+6. The small colored button just right of the "+2 kHz" checkbox now
+shows the letter "S" if "Split Tx" has been checked.
+
+7. New user option appends DXCC country name and "QSO B4" status to
+decoded CQ messages.
+
+8. Setting of dial frequencies through Commander should should now
+be aware of local convention for decimal separator.
+
+9. Several minor bug fixes.
+
+10. Refactoring of code to move audio input.output into the GUI thread.
+(Should be invisible to users).
+
+11. Updated credits displayed in the "About" window.
+
+12. Updated User's Guide.
+
+
+July 19, 2013: Version 1.1, r3496
+---------------------------------
+This is a full release of WSJT-X Version 1.1.  It provides an easy way
+to make QSOs in both JT65 and JT9 modes.  
+
+Changes from the most recent beta release, r3487, include the
+following:
+
+1. Significant optimizations of the JT9 decoder, providing speed 
+improvements up to 5 times.
+
+2. Frequency-setting through DX Lab Commander now works properly at
+non-integral kHz frequencies.
+
+3. A new meter widget has been added (thanks to PY2SDR).
+
+4. Implementation of "multiple instances" has been completed and
+tested (thanks to KK1D). 
+
+5. Several minor bug fixes.
+
+
+July 15, 2013: Version 1.1 Beta Release, r3487
+----------------------------------------------
+
+Version 1.1 of WSJT-X is "bi-lingual" -- it transmits and receives
+both JT9 and JT65 signals, switching between modes automatically as
+needed.  The maximum displayed bandwidth has been increased from 1 to
+5 kHz.  If your receiver has an upper-sideband filter at least 4 kHz
+wide, on most bands you can have all the JT65 *and* all the JT9
+activity on screen at once, available for making QSOs.
+
+Other improvements since v1.0, r3323 include the following:
+
+1. CAT control via DxLab Commander.
+
+2. Improved GUI appearance, especially on Linux and OS X.
+
+3. Compilable with Qt5 as well as Qt4.
+
+4. Fixed occasional program crashes caused by receiving a message in
+the form "call1 call2" (with no grid, report, etc.).
+
+5. Improved handling of audio device selection in Linux.
+
+6. Log QSO frequency, instead of dial frequency only.
+
+7. Added Tx Power to ADIF log information.
+
+8. Added option to retain between QSOs the Power and Comments fields
+for ADIF and wsjtx logs.
+
+9. Added optional antenna description for PSK Reporter.
+
+10 Fixed a bug in handling of logged grid locator when none was
+available on the double-clicked line.
+
+11. Fixed a bug that caused small differences in the lengths of
+transmitted symbols.  This leads to improved decoding.
+
+12. Tx message (highlighted in yellow) now includes a mode flag and
+the audio offset from dial frequency.
+
+13. Added a spinner control for Rx Freq.
+
+14. New on-screen button "Lock Tx=Rx" locks Tx and Rx frequencies
+together.
+
+15. Allow Windows COM port number greater than 9.
+
+16. Don't clear DxGrid when user double-clicks on a message with no
+grid, if the message's Tx call is same as DxCall.
+
+17. Double-click on yellow Tx message now sets frequency, but does
+nothing else.
+
+18. Rationalized the logic of the CAT control indicator button. Now
+colored grey/green/orange/red -- see User's Guide.
+
+19. Operating in "Split Tx" mode is optional (but with most radios is
+necessary if you will transmit at more than 2.7 kHz above dial
+frequency).
+
+20. The correct TxMode label now appears on program startup.
+
+21. "Transmitting..." message in ALL.TXT now has the correct TxMode.
+
+22. File wsjt_status.txt includes TxMode.
+
+23. F4 clears Az, Dist, and the Tx message boxes.
+
+24. You can decode JT9 signals in the JT65 frequency range, and
+vice-versa, by double-clicking the signal in the waterfall.
+
+25. Better logic for enabling/disabling the TestPTT button.
+
+26. Do not call getFreq() when the TestPTT button is clicked and
+PTTmethod is via CAT control.
+
+27. New cold-start default frequencies are set at reasonable values
+for JT65.  A "+2 kHz" checkbox is provided for quick setup in JT9-only
+mode.
+
+28. Default macros added as simple examples.
+
+In case you wondered about r3482, which was posted for a few hours 
+only...
+
+It was repleced by r3487 in order to fix two bugs.  Revision 3487 
+uses more sensible logic for what to do when the "DX Grid" entry is 
+edited, and it fixes a bug that could prevent program restart if 
+you had exited the program with "+2 kHz" checked.
+
+May 30, 2013: Version 1.0, r3323
+--------------------------------
+
+With this release of WSJT-X Version 1.0 we include a few (relatively
+minor) enhancements in response to user requests, as well as some
+program polishing and cleanup.  Active program development will
+continue, but new releases will become less frequent.
+
+1. New option on the Setup menu: "Tx freq locked to Rx freq".
+
+2. Double-click on a decoded "73" message now sets Tx5, rather than Tx6.
+
+3. New keyboard shortcuts: Alt+1 through Alt+6 set the next Tx message 
+   at the corresponding number.
+
+4. PTT control via Ham Radio Deluxe has been imnplemented and tested.
+
+5. "Tool Tips" are now provided for most on-screen controls.
+
+6. Under Linux and OS X, listings of available audio devices and APIs
+   have been corrected.
+
+7. Tab order among GUI controls has been cleaned up.
+
+8. Updates to the WSJT-X User's Guide.
+
+
+May 22, 2013: v0.99, r3297
+--------------------------
+
+1. CAT control via Ham Radio Deluxe is now available.  For setup
+   details see item #5 at the top of page 6 of the updated WSJT-X
+   User's Guide.
+
+2. Submodes JT9-5, JT8-10, JT9-30 have been de-activated.  (As far as I
+   know, nobody was using them.)  This action makes the program smaller 
+   by some 150 MB and able to run effectively on some older computers.
+
+3. Bizarre ordering of COM port numbers on the drop-down list has been
+   corrected, and suitable serial ports added to the list displayed in
+   Linux.
+
+4. Gray bar between decoding periods now contains a dashed line.
+
+5. Corrected a bug that prevented use of Setup | Configuration with
+   no existing wsjtx.ini file.
+
+May 17, 2013: v0.95, r3278
+--------------------------
+1.  Double-clicking on a decoded text line in "Band Activity" window
+    now copies the line into the "QSO Frequency" window if it was not
+    already there.
+
+2.  Option "Color highlighting in left window" removed from Setup
+    menu.  Highlighting is now always done.
+
+3.  Positions of "QSO Frequency" and "Band Activity" windows have been
+    swapped.  
+
+4.  F4 was restored to its previous use; F5 is now used to display
+    Special Mouse Commands
+
+5.  Small square between Band selector and Frequency readout was made
+    a control button.  Orange indicates one-way CAT control from
+    program to radio, red indicates bi-directional control.  Clicking
+    the orange button causes a one-time readout of dial frequency.
+
+6.  If Save=None, the last recorded file is deleted on program exit.
+    This prevents unwanted accumulation of files in the Save
+    directory.
+
+7.  Status-bar messages were re-arranged in a more logical order.
+
+8.  Tx signal report was added to wsjtx_status.txt (for JT-Alert)
+
+9.  More informative labels were placed on the "Tab 2" GUI controls.
+
+10. Better default scaling for the "Cumulative" spectrum.
+
+11. New algorithm for identifying JT9 signals to send to decoder,
+    resulting major improvements in decoder speed.
+
+12. Bug fixes:
+     - Incorrect displayed frequencies for JT9-2 signals
+     - Infinitely repeated "Error rigOpen -1" messages
+     - User tries to open CAT control using busy or nonexistent serial port
+
+13. Many updates to the User's Guide
+
+
+May 2, 2013: v0.95, r3251
+-------------------------
+
+1. The "band change" function is executed whenever the Band combobox
+   is activated, even if the selected band has not changed.
+
+2. The program does not set rig mode.  That task is left to the user.
+
+3. Time interval for polling rig frequency is now a user parameter on
+   the setup screen.  I set mine to 1 second, which works fine with
+   the Kenwood TS-2000.  Set it to 0 if you want no polling for
+   frequency (which means unidirectional CAT control from program to
+   radio).  Choose something like 10 s for the K3.
+
+4. Much new work on the WSJT-X User's Guide, which is approaching its
+   final form for Version 1.0.  Please read it and tell us about
+   anything you find unclear or missing!
+
+These changes address nearly all of the CAT issues found by a few
+users -- those with K3, IC-746, IC-706, in particular.  
+
+One additional piece of advice when running WSJT-X in Windows: connect
+and turn on the radio and any interface equipment before starting
+WSJT-X, and exit the program before turning such equipment off.
+
+April 29, 2013: v0.95, r3243
+----------------------------
+
+1. Now has bi-directionsl CAT control using direct calls to hamlib
+   functions.  Highlights displayed dial frequency with red background
+   if frequency differs from nominal for the selected band by more
+   than 100 kHz.  (Is there a more useful or logical condition to
+   flag?)  Small red square between Band selector and Dial Frequency
+   display to indicate that CAT control is active.  Mode is set to USB
+   on startup.  (Note: CAT control diagnostics are presently rather
+   rudimentary, we're still working on this.  Feedback is welcome!)
+
+2. New controls on Setup | Configuration screen: 
+   - RTS/DTR OFF -- needed by K2 and maybe other radios
+   - Data / Mic -- select CAT-control PTT type
+   - Test CAT Control -- try settings before returning to main screen
+   - Test PTT -- try settings for toggling PTT On/Off
+
+3. Help menu now provides displays of Keyboard Shortcuts (quick access
+   via F3) and Special Mouse Commands (F4).
+
+4. Option "Setup | Advanced | Allow multiple instances" enables the
+   use of more than one instance of WSJT-X for special applications.
+   (The program must be copied into and run from different
+   directories.)
+
+5. No posts to PSK Reporter if band was changed during the reception
+   period.
+
+6. Improved behavior of Tune button.
+
+7. Improved inter-process communication between WSJT-X and JT-Alert-X.
+
+8. Better interaction between "Report" spinner control and Tx messages.
+
+9. Removed the NB checkbox and slider.  (Has anyone found these useful?)
+
+10. New buttons on main window: "Tx=Rx" sets Tx frequency to current
+    Rx frequency; "Rx=Tx" does the opposite.
+
+11. Log QSO confirmation window is now "non-modal": you can keep it 
+    open and still access controls on the main window.
+
+12. Tab-order has been rationalized on most screens.
+
+13. Dial frequency and mode written to file ALL.TXT.
+
+14. Double-click on decoded line sets Tx message #3 if message has
+     the form "MyCall Call2 rpt".
+
+15. Bug causing occasional, seemingly unpredictable program crashes
+    has been fixed.
+
+16. The WSJT-X User's Guide is somewhat closer to being complete.  User
+    feedback on the Guide will be most welcome.  What is unclear?  What
+    is missing?
+
+April 17, 2013: v0.9, r3195
+---------------------------
+1. Sorry, the CAT control changes in r3187/3188 were a dismal failure
+in many stations, and they introduced other bugs as well.  This revision
+goes back to uni-directional CAT control: the program can set the 
+radio's dial frequency and do T/R switching, but that's all.  The band
+setting is not reset on program startup.
+
+2. Logic for the Tune button has been corrected.
+
+3. For Linux compile-it-yourself enthusiasts: the interface to 
+PSK Reporter is now working undel Linux.
+
+April 16, 2013: v0.9, r3188
+---------------------------
+
+1. CAT control now reads and follows changes in radio's dial
+frequency.  Readout gets red highlighting if radio is on wrong band.
+On program restart, band is reset to the last selected band.
+
+2. New "Tune" button generates an unmodulated carrier.  Toggle button
+a second time to turn Tx off.
+
+3. Added labels at top of "Tab 2" and enlarged the text entry fields.
+
+4. Fixed the broken logic for "Runaway Tx watchdog".
+
+5. Fixed "Prompt me to log QSO" so that it no longer requires also
+setting "ID after 73".
+
+6. Additional changes of (eventual) interest to Linux users.  Code for
+sending spots to PSK Reporter now in place.
+
+April 13, 2013: v0.9, r3166
+---------------------------
+1. Option to send Tx messages (highlighted in yellow) to the QSO window.
+
+2. Prevent starting a transmission more than 24 sec into a Tx period.
+
+3. "Setup | Options" changed to "Setup | Configuration".
+
+4. Type Alt-V to save the most recently completed Rx file.
+
+5. Fixed bug that truncated Rx messages to 16 characters.
+
+6. Internal program changes that should provide better user diagnostics
+when necessary at program startup.
+
+April 11, 2013: v0.9, r3157
+---------------------------
+1. Maximum size of several window areas increased to accommodate system 
+fonts set larger than default.
+
+2. New behavior of Erase button: click once to erase the left (QSO) window,
+twice to erase both decoded text windows.
+
+3. Keyboard shortcuts:
+   Alt-D: decode again at QSO frequency (same as clicking the Decode() button)
+   Shift-D: do another full decode in both windows
+   Alt-E: Erase()
+   Ctrl-F: Edit the free text message box
+   Alt-H: Halt Tx()
+   Alt M: Monitor()
+   Alt-N: Enable Tx()
+   Alt-Q: Log QSO()
+   Alt-S: Stop()
+
+4. New Setup options: "Tx disabled after sending 73" and "Runaway Tx 
+watchdog".
+
+5. Fixed bug in saving the "report received" for logging purposes.
+
+6. Corrected the logic for "Runaway Tx watchdog".
+
+7. Fixed bug that truncated characters 17 and 18 of decoded messages.
+
+April 10, 2013: v0.9, r3151
+---------------------------
+1. Blank line between decoding periods is now in the right-hand 
+text window, where it should be.
+2. Decoding range defined by fMin and fMax is now enforced.
+
+April 9, 2013: v0.9, r3143
+--------------------------
+This minor release restores the decoding speed of earlier revisions
+and corrects a bug that prevented sending CW ID.
+
+April 9, 2013: v0.9, r3142
+--------------------------
+
+This version of WSJT-X has a number of significant changes.  Please
+read the following notes carefully.  Also -- even if you are already
+familiar with WSJT-X -- be sure to read the updated WSJT-X User's 
+Guide at 
+http://www.physics.princeton.edu/pulsar/K1JT/WSJT-X_Users_Guide.pdf ,
+especially pages 3 and 4.
+
+Changes since v0.8 r3118 include the following:
+
+1. There are now two scrolling windows for decoded text.  The left
+window contains decodes only from close to the designated QSO
+frequency.  The right window includes signals over the full decoding
+range.
+
+2. An alternative set of controls is now available for generating and
+selecting Tx messages.  Some may find these more convenient to use
+than the Tx1 through Tx6 message boxes.
+
+3. A number of new user options are available on the Setup menu:
+   - Blank line between decoding periods (right window only)
+   - Clear DX Call and DX Grid after logging QSO
+   - Display distances in miles
+   - Runaway Tx watchdog
+   - Background colors for left window
+   - Double-click on decoded message sets Tx Enable
+
+4. New or changed on-screen features
+   - "Tol" replaced by fMin and fMax on waterfall screen (see User's Guide)
+   - Spinner control for signal report
+   - On waterfall scale: green marker for Rx freq, red for Tx. blue
+     for decoding range
+
+5. New behavior
+   - "CQ DX" is now treated properly when decoded line is double-clicked
+   - Message formate for compound callsigns (e.g., PJ4/K1ABC, G4XYZ/P)
+     are now handled correctly.  (Some restrictions apply, and will
+     be spelled out in the completed User's Guide.)
+   - Decode button now causes a decode only at the specified Rx frequency.
+   - Click on waterfall spectrum sets Rx freq; double-click also invokes
+     decoder (as though Decode button had been clicked).  CTRL-click moves
+     both Rx and Tx freqs.
+   - Amplitude at end of transmission is ramped down to prevent a final
+     key click.
+
+6. The following bugs have been fixed:
+   - Logic error in decoder
+   - Certain non-standard Tx messages could cause a program crash.
+   - Certain (rarely used) messages did not pack/unpack correctly
+
+April 2, 2013: v0.8, r3118
+--------------------------
+1. Improved interface to program JT-Alert, by VK3AMA.
+
+2. The LogQSO confirmation dialog no longer blocks the GUI updating
+   process.
+
+3. A blank line with gray background separates the decoded text lines for
+   each new invocation of the decoder.
+
+4. New suggested default frequencies: 5.357, 18.104, and 24.918 MHz.  
+   Be sure to edit these entries on the 'Default Frequencies' tab of the
+   Setup screen.  (When you have done this once, the new values will be
+   remembered.)
+
+5. The LogQSO button now does nothing is the 'DX call' entry field is
+   blank.
+
+6. Several minor bugs were fixed.
+
+
+March 27, 2013: v0.8, r3113
+---------------------------
+1. Bug fix: VOX control of T/R switching now works.
+
+2. Potentially useful error messages now appear when CAT control
+   has failed.
+
+3. Added an instruction on the Log QSO confirmation screen.
+
+4. Clear the DXcall and DXgrid entries after logging a QSO.
+
+March 26, 2013: v0.8, r3112
+---------------------------
+
+Edson Pereira, PY2SDR, recently became an active contributor to this
+open-source project.  Edson and I have been very busy over the past
+few days!  WSJT-X revision 3112 has many changes and new features.
+
+1. The GUI layout has been adjusted and optimized.
+
+2. CAT control is now operational, offering optional control of your
+   radio's dial frequency and T/R status.  Go to the Setup | Options
+   window to select the necessary parameters.
+
+3. CW ID has been implemented.  You can have your ID sent after a fixed 
+   time interval, or automatically when you transmit a "73" or free
+   text message.  
+
+4. Default dial frequencies are available for each band on a new tab
+   on the Setup | Options window.  Please note: some of these
+   frequencies are probably wrong!  You can edit them as needed.  
+   (Please let us know if the original values are inconsistent with
+   actual practice on any band.)
+
+5. Several new options appear on the Setup menu.  Try them!
+
+6. Azimuth and Distance information is displayed whenever a valid grid
+   locator appears in the "Dx Grid" box.
+
+7. The decoder has again been adjusted for better compromise between
+   sensitivity and decoding time.  
+   
+8. The User's Guide is out of date, and needs work.  We hope to get to
+   that task soon.
+
+9. Very important for some would-be users: WSJT-X now runs properly
+   under Linux.  We haven't made a package yet, so for now you must
+   compile your own.  If you don't know how, we hope to be set up
+   to make packages before too long.
+
+10. If you know someone who might be interested in contributing to the
+    development of WSJT-X and related projects, please send him/her
+    our way!  We're especially looking for someone interested in
+    producing packaged Linux distributions -- for example, *.deb or
+    *.rpm packages, but other programming help is also wanted.
+
+As always: please report bugs, and don't be bashful about sending us
+your feature requests!
+
+March 22, 2013: v0.7, r3071
+---------------------------
+1. Correct a bug that (still) allowed display of previous decodes
+when nothing new was decoded.
+
+2. Add a user confirmation screen activated when you click Log QSO.
+This lets you edit or add information before it is written to the
+ADIF file.
+
+3. Tx message macros and now available.  Configure them on the Setup 
+window.  They are invoked as a pop-up menu by right-clicking on the 
+Tx5 message window; then select the desired message by left-clicking 
+on the desired message. 
+
+March 20, 2013: v0.7, r3063
+---------------------------
+1. Add Frequency to the generated ADIF records.
+
+2. Correct a decoder bug that led to duplication of previous output 
+when nothing new was decoded.
+
+March 19, 2013: v0.7, r3061
+---------------------------
+1. Allow Windows COM port numbers up to 99.
+
+2. Replace status files wsjtx_qrg.txt and wsjtx_txcall.txt with
+a single file, wsjtx_status.txt.
+
+3. Combine wsjtx_rx.log and wsjtx_tx.log into a single file ALL.TXT.
+
+4. "Log QSO" now writes a file in ADIF format.
+
+5. Starting to implement popup macros for Tx message #5.
+
+6. Big improvement in decoding speed.
+
+*** More changes to come!  Please report any problems, especially
+*** with the ADIF-format log.
+
+March 12, 2013: v0.6, r3046
+---------------------------
+1. Decoded calls can now be uploaded to the PSK Reporter web site. 
+Check the box "Enable PSK Reporter" on the Setup screen, and go to
+http://pskreporter.info/pskmap.html to see the spots.  Be sure to
+enter your "Dial Frequency (MHz)" at lower right of the Wide Graph
+window.  (Rig control features are yet to come...)
+
+2. Added some interfaces to permit use with the program JT-Alert,
+by VK3AMA.  Look for this capability in the near future. 
+
+March 6, 2013: v0.5, r3038
+--------------------------
+1. Selection of Current/Cumulative/JT9Sync for the 2d spectral display
+changed to a combobox.
+
+2. Double-click on decoded text does not change frequency settings
+if first decoded call is MyCall.
+
+March 1, 2013: v0.5, r3026
+--------------------------
+1. The horizontal scale of 2d spectra (e.g., the "red curve") is now
+correct when the user has selected FFT Bins/Pixel > 1.
+
+2. Double-clicking on a decoded text line now selects the second
+callsign independent of exactly where one has clicked on the line.  
+In addition, it sets the selected frequencies (both Tx and Rx) to
+the frequency of the decoded transmission.
+
+December 11, 2012: v0.5, r2791
+------------------------------
+1. Messages of the form "CQ DX K1ABC" are now supported.
+
+November 30, 2012: v0.5, r2788
+------------------------------
+1. A bug was introduced when support for positive signal reports was
+added.  It could cause a program crash when certain free-text messages
+were composed for transmission.  The bug has been fixed.
+
+2. In the slower JT9 sub-modes, the UTC listed on decoded text lines
+has been changed to the start time of the Rx sequence, rather than the
+time of the final minute.
+
+3. The waterfall's "Auto Zero" button had no function, and has been
+removed.
+
+4. In previous revisions the installer put a number of DLLs into
+the Windows system directory, normally C:\Windows\System32.  This
+revision installs the DLLs to the WSJT-X installation directory.
+
+
+November 29, 2012: v0.5, r2786
+------------------------------
+1. In r2783, the companion program jt9.exe (started automatically when
+you start WSJT-X) was a CPU hog for no good reason.  This was an
+oversight on my part, and the bug has been corrected.
+
+2. The program should now run correctly if installed in a directory
+whose name contains embedded spaces.  (Under Vista and Win7, however,
+it's still not a good idea to install WSJT-X into C:\Program Files,
+because of restricted write permissions there.)
+
+3. In r2783 and earlier, stopping a transmission by toggling to "Auto
+OFF" would terminate Tx audio and release PTT almost simultaneously,
+possibly hot-switching your T/R relay(s).  This has been corrected so
+that proper sequencing takes place.
+
+
+November 28, 2012: v0.5, r2783
+------------------------------
+This revision has an unusually large number of changes relative to the
+previous release, v0.4 r2746.  These changes include:
+
+1. PTT control via COM ports COM10 and higher is enabled.
+
+2. Improved decoder performance: higher speed as well as better
+chances of success.  Moderate amounts of frequency drift are detected
+and compensated.  Computed S/N values are more reliable.  Time offsets
+from -2.5 to +5 s are now supported, which makes JT9 usable for EME.
+(EME tests on 144 MHz have been successful, and performance on that
+propagation mode appears to be good.)
+
+3. Tx Frequency now tracks the selected QSO Frequency (unless you hold
+down the CTRL key when setting QSO Frequency via mouse-clicks or the
+F11/F12 keys).
+
+4. Decoded text containing "CQ " is highlighted with green background;
+text including "MyCall" is highlighted in red.
+
+5. In previous versions, signal reports were required to be in the
+range -30 to -01 dB.  In v0.5 r2782 the range has been extended to -50
+to +49 dB.  There is backward compatibility for the range -30 to -01,
+but reports in the range -50 to -31 and 0 to +49 will NOT be decoded
+correctly by previous program versions.  It is important to upgrade!
+
+6. Items "Save Synced" and "Save Decoded" are now implemented.
+
+7. UTC Date, JT9 submode, and a parameter related to the decoding
+procedure are now included in file wsjtx_rx.log.
+
+8. Editing of Tx messages (in any of the six Tx message boxes) is
+complete when you hit "Tab" or "Return".  The message is then parsed
+and converted to the form in which it will be displayed if decoding is
+successful.  Free-text messages are trimmed to 13 characters and
+highlighted with a pink background.
+
+9. The most recent transmitted message is displayed in the right-most
+label on the status bar.  This can be useful if you have lost track of
+where you were in a QSO.
+
+10. By default, the program now starts with Monitor ON.  An option on
+the Setup menu allows you to select "Monitor OFF at startup".
+
+11. Better scaling is provided for the red "JT9 Sync" curve.  Note
+that JT9 signals in the active sub-mode should appear in this plot as
+a bump of width equal to the total signal bandwidth, with a narrow and
+slightly higher bump at the left edge.  The narrow bump is the
+frequency of the Sync tone, which is defined as the nominal frequency
+of the JT9 signal.
+
+12. Basic QSO information is now written to file wsjt.log when you
+click the "Log QSO" button.
+
+13. The WSJT-X User's Guide has been updated.
+
+14. Other known bugs have been fixed.  There will probably be new
+ones!  When you find one, or if you know of any old ones that have NOT
+been fixed, please send me email.
+
+Summary of Present Status
+----------------------------------------------------------------------
+I believe that WSJT-X is now a stable and very usable program.  Many
+thousands of QSOs have been made with JT9-1, mostly at HF -- I have
+made nearly 100, myself.  Also a number of QSOs have also been
+completed at MF, and successful tests have been made on 2m EME, etc.
+A number of QSOs have also been made with JT9-2.
+
+As far as I know the slower modes (JT9-5, JT9-10, and JT9-30) also
+work correctly.  (Certainly they do in my laboratory test setup.)
+Most people will find these modes too slow for "everyday" use, and
+they require high frequency stability.  It remains to be seen whether
+they will be widely used.
+
+An alternative approach to obtaining improved sensitivity would be to
+give the decoder an ability to average over several successive
+transmissions.  For example, the average of five JT9-1 transmissions
+could reach a decoding threshold around -32 dB, only 2 dB worse than a
+single JT9-5 transmission.  Because of QSB, the shorter transmissions
+may actually succeed in less total time.  Stability requirements would
+be those of JT9-1, much less stringent than those of JT9-5.
+
+Program development is not finished, by any means.  I will be grateful
+for your feedback on performance issues, as well as your "wish-list"
+of features to be added.  As always, example recordings of files that
+you think should have decoded, but did not, will be much appreciated.
+
+November 16, 2012: v0.4, r2746
+------------------------------
+
+Changes from v0.4 r2731 include the following:
+
+1. Valid signal reports are now generated by double-clicking on a
+callsign in the decoded text window.
+
+2. Consecutive spaces in a Tx message are now collapsed into a single
+space.
+
+3. Decoding speed is much improved, especially when strong (possibly
+non-JT9) signals are present and "Tol" is set to a relatively large
+value.
+
+4. Scaling of the "JT9 Sync" plot (red curve) is more reasonable.
+
+5. Layout of widgets on the main window has been improved.
+
+6. Several minor bug fixes. 
+
+November 14, 2012: v0.4, r2731
+------------------------------
+
+A number of known bugs have been fixed, and the JT9 decoder is
+significantly improved.  Among other improvements, the program is now
+much less fussy about timing issues.
+
+November 6, 2012: v0.3, r2717
+------------------------------
+
+Changes from r2713 include the following:
+
+1. A bug in the decoder that led to erratic behavior (failed decodes)
+under certain conditions has been corrected.  Decoding is now much
+more reliable.
+
+2. A valid algorithm is now used to calculate S/N values for received
+JT9 signals.
+
+3. The header format of recorded *.wav files has been corrected.
+These files will now play correctly in Windows programs that expect
+the standard header.
+
+November 6, 2012: v0.2, r2713
+------------------------------
+
+Changes from r2711 include the following:
+
+1. Updates to the Quick-Start User's Guide,
+http://www.physics.princeton.edu/pulsar/K1JT/WSJT-X_Users_Guide.pdf
+
+2. Double-click on waterfall now sets Tol to a reduced
+(mode-dependent) value.
+
+3. Tol is saved and restored on program restart.
+
+4. A "digital gain" slider was added next to the green-bar audio level
+indicator.  With the slider at mid-range, the scale reads correctly in
+dB above the least significant bit of 16-bit audio data.
+
+5. There is now a test that rejects at least one type of data that is
+sufficiently corrupt to cause Eddie's best friend, the message
+"15P6715P67WCV".
+
+6. Several minor tweaks to improve decoder performance.
+
+7. The program now starts with Monitor OFF.  You must click Monitor to
+start accepting audio.  For some types of testing, this may be an
+advantage.  This startup condition may be changed again, in the
+future.
+
+October 31, 2012: v0.2, r2711
+-----------------------------
+
+Three significant changes since r2706:
+
+1. Three options are now provided on the "Decode" menu, controlling
+the "depth" of the decoding process.  For most purposes I suggest you
+should use "Normal", but feel free to experiment with the others.
+
+2. Decoding of multiple signals in one Rx interval has been improved.
+
+3. Handling of strong signals has been improved. 
+
+October 309, 2012: v0.2, r2706
+------------------------------
+
+Changes since r2702 include the following:
+
+1. The problem with "ghost" signals is fixed.
+
+2. A problem causing very long decode times under certain
+circumstances has been fixed.  Please note: decode times on any recent
+PC should no more than a few seconds!
+
+3. I have re-directed the program's fatal error messages so they will
+be sent to the command-prompt window from which you started the
+program. Please send me full reports on any such messages you observe,
+preferably with details on how to reproduce the problem.
+
+#########################################################################
+
+Some additional information ...
+
+1. Yes, the JT9 modes require good stability in all system
+oscillators.  The present JT9 bdecoder does not attempt to track
+frequency drifts. Such capability will be added, however.  We have
+been using digital modes for EME for nearly ten years now, at 144 MHz
+and higher.  There are more than 1000 WSJT users on EME, using all
+kinds of rige.  We have learned how to deal with reasonable rates of
+drift.  Surely if we can do these things at VHF, we can do them much
+more easily at MF and LF.
+
+2. If you're sure that you have seen degraded JT9 performance because
+of frequency stability issues, don't just complain on the LF
+reflector. Document your case and send me an example file with a
+drifting JT9 signal.  Making WSJT-X and JT9 better is partly YOUR
+responsibility!
+
+3. In other ways as well, test files are needed.  I can make many
+tests myself, but I can't foresee all the problems others will have.
+That's what the "Save All" function is for!  In these early tests,
+always run with "Save All" checked, just in case you will want to
+refer back to something that happened.  You may want to send me the
+file in question.  You can always clean out your "Save" directory by
+using "File | Delete all *.wav files in SaveDir".  I need good
+examples of signals that fail to decode for any unknown reason.  Also
+some good examples of atmospheric or other impulsive noise, for
+testing the noise blanker.
+
+4. I have added a page of "Hints for New Users" to the online WSJT-X
+User's Guide,
+http://www.physics.princeton.edu/pulsar/K1JT/WSJT-X_Users_Guide.pdf .
+Please read it! ... and let me know if you find other operational
+details of WSJT-X that need explanation.  This will likely be
+especially true for those not already familiar with older versions of
+WSJT.
+
+5. An operational suggestion: In many ways the different JT9 submodes
+are treated as distinct modes.  If you receive a JT9-x signal in a
+different submode than the one you have selected, you won't decode
+it. For this reason, if JT9 is to become popular we'll probably need
+to choose one or two of the submodes for general use, and perhaps
+assign a narrow slice of the band to each one.  Note that "message
+averaging" in the Rx software can make two or three JT9-2
+transmissions as good as one JT9-5 transmission, with the advantage
+that you will copy sooner if signals are better than required for
+JT9-5.  Message averaging is not yet present in the JT9 decoder... but
+in future it can be.  Again, we have dealt with such issues very
+effectively on EME -- and can do so at MF/LF, for sure.
+
+6. On the topic of CW, Beacons, WSPR, JT9, etc.  I really don't
+understand what all the fuss is about.  Surely there is room for
+everybody?  Maybe I'm just too new here to understand?  (Mal, is this
+mostly just a matter of "Mal being Mal"???)
+
+On the HF bands, the WSPR sub-band is just 200 Hz wide.  If we did the
+same on 630 m, the WSPR sub-band would take up less than 3% of the 7
+kHz band.  If that's too much, we could cut it in half, or even less,
+and still have enough WSPR space.  Moreover, a "slow WSPR", if
+warranted, would require even less bandwidth.  Similar comments apply
+to JT9.  The bandwidth of JT9 signals is significantly less than that
+of CW, for comparable information rates.  There should be enough
+spectrum for both, even in our narrow MF and LF bands.
+
+7. As for performance comparisons between JT9 and WSPR: WSPR is a
+mature program, and its decoder has been optimized and tweaked over a
+period approaching five years.  You are playing with JT9 in infancy.
+With help (as opposed to simple complaints) from users, it will
+improve rapidly.
+
+October 29, 2012: v0.2, r2702
+-----------------------------
+Changes since version 0.1, r2696 include the following:
+
+1. Sample rate for audio output has been changed from 12000 to 48000
+Hz.  Tx audio may now be generated at any frequency from 500 to 20000
+Hz.
+
+2. The Decoder now tries to decode all synchronizable signals in the
+"green zone", that is, within "Tol" Hz of the selected QSO
+frequency. (Before, by default it decoded only the signal producing
+the highest "sync" value.  Other signals could be decoded by manually
+setting the QSO frequency and reducing Tol as needed.)
+
+3. The user's selected QSO Frequency is now saved and restored on
+program restart.
+
+4. The problem with re-initialization after changing sub-modes has
+been fixed.
+
+5. The problem (for some users) of not releasing PTT after end of a
+transmission has been fixed.
+
+6. The program now writes a log of all decodes to a file wsjtx_rx.log
+in the wsjtx directory.
+
+
+October 25, 2012: v0.1, r2695
+-----------------------------
+Initial version of WSJT-X (experimental WSJT) released for testing.
diff --git a/NetworkMessage.cpp b/NetworkMessage.cpp
new file mode 100644
index 0000000..5c7e0f1
--- /dev/null
+++ b/NetworkMessage.cpp
@@ -0,0 +1,100 @@
+#include "NetworkMessage.hpp"
+
+#include <exception>
+
+#include <QString>
+#include <QByteArray>
+
+#include "pimpl_impl.hpp"
+
+namespace NetworkMessage
+{
+  Builder::Builder (QIODevice * device, Type type, QString const& id)
+    : QDataStream {device}
+  {
+    common_initialization (type, id);
+  }
+
+  Builder::Builder (QByteArray * a, Type type, QString const& id)
+    : QDataStream {a, QIODevice::WriteOnly}
+  {
+    common_initialization (type, id);
+  }
+
+  void Builder::common_initialization (Type type, QString const& id)
+  {
+    *this << magic;
+    *this << schema_number;
+    setVersion (QDataStream::Qt_5_2); // Qt schema version
+    *this << static_cast<quint32> (type) << id.toUtf8 ();
+  }
+
+  class Reader::impl
+  {
+  public:
+    void common_initialization (Reader * parent)
+    {
+      quint32 magic;
+      *parent >> magic;
+      if (magic != Builder::magic)
+        {
+          throw std::runtime_error {"Invalid message format"};
+        }
+      *parent >> schema_;
+      if (schema_ > Builder::schema_number)
+        {
+          throw std::runtime_error {"Unrecognized message schema"};
+        }
+      if (schema_ <= 1)
+        {
+          parent->setVersion (QDataStream::Qt_5_0);
+        }
+      else if (schema_ <= 2)
+        {
+          parent->setVersion (QDataStream::Qt_5_2);
+        }
+      quint32 type;
+      *parent >> type >> id_;
+      if (type >= maximum_message_type_)
+        {
+          throw std::runtime_error {"Unrecognized message type"};
+        }
+      type_ = static_cast<Type> (type);
+    }
+
+    quint32 schema_;
+    Type type_;
+    QByteArray id_;
+  };
+
+  Reader::Reader (QIODevice * device)
+    : QDataStream {device}
+  {
+    m_->common_initialization (this);
+  }
+
+  Reader::Reader (QByteArray const& a)
+    : QDataStream {a}
+  {
+    m_->common_initialization (this);
+  }
+
+  Reader::~Reader ()
+  {
+  }
+
+  quint32 Reader::schema () const
+  {
+    return m_->schema_;
+  }
+
+  Type Reader::type () const
+  {
+    return static_cast<Type> (m_->type_);
+  }
+
+  QString Reader::id () const
+  {
+    return QString::fromUtf8 (m_->id_);
+  }
+}
diff --git a/NetworkMessage.hpp b/NetworkMessage.hpp
new file mode 100644
index 0000000..cce1380
--- /dev/null
+++ b/NetworkMessage.hpp
@@ -0,0 +1,290 @@
+#ifndef NETWORK_MESSAGE_HPP__
+#define NETWORK_MESSAGE_HPP__
+
+/*
+ * WSJT-X Message Formats
+ * ======================
+ *
+ * All messages are written or  read using the QDataStream derivatives
+ * defined below, note that we are using the default for floating
+ * point precision which means all are double precision i.e. 64-bit
+ * IEEE format.
+ *
+ *  Message is big endian format
+ *
+ *   Header format:
+ *
+ *      32-bit unsigned integer magic number 0xadbccbda
+ *      32-bit unsigned integer schema number
+ *
+ *   Payload format:
+ *
+ *      As per  the QDataStream format,  see below for version  used and
+ *      here:
+ *
+ *        http://doc.qt.io/qt-5/datastreamformat.html
+ *
+ *      for the serialization details for each type, at the time of
+ *      writing the above document is for Qt_5_0 format which is buggy
+ *      so we use Qt_5_2 format, differences are:
+ *
+ *      QDateTime:
+ *           QDate      qint64    Julian day number
+ *           QTime      quint32   Milli-seconds since midnight
+ *           timespec   quint8    0=local, 1=UTC, 2=Offset from UTC
+ *                                                 (seconds)
+ *                                3=time zone
+ *           offset     qint32    only present if timespec=2
+ *           timezone   several-fields only present if timespec=3
+ *
+ *      we will avoid using QDateTime fields with time zones for simplicity.
+ *
+ * Type utf8  is a  utf-8 byte  string formatted  as a  QByteArray for
+ * serialization purposes  (currently a quint32 size  followed by size
+ * bytes, no terminator is present or counted).
+ *
+ * The QDataStream format document linked above is not complete for
+ * the QByteArray serialization format, it is similar to the QString
+ * serialization format in that it differentiates between empty
+ * strings and null strings. Empty strings have a length of zero
+ * whereas null strings have a length field of 0xffffffff.
+ *
+ * Schema Version 1:
+ * -----------------
+ *
+ * Message       Direction Value                  Type
+ * ------------- --------- ---------------------- -----------
+ * Heartbeat     Out       0                      quint32
+ *                         Id (unique key)        utf8
+ *
+ *		The  heartbeat  message  is  sent  on  a  periodic  basis  every
+ *		NetworkMessage::pulse  seconds  (see  below).  This  message  is
+ *		intended to be used by server to detect the presence of a client
+ *		and  also   the  unexpected  disappearance  of   a  client.  The
+ *		message_aggregator reference server does just that.
+ *
+ *
+ * Status        Out       1                      quint32
+ *                         Id (unique key)        utf8
+ *                         Dial Frequency (Hz)    quint64
+ *                         Mode                   utf8
+ *                         DX call                utf8
+ *                         Report                 utf8
+ *                         Tx Mode                utf8
+ *                         Tx Enabled             bool
+ *                         Transmitting           bool
+ *
+ *		WSJT-X  sends this  status message  when various  internal state
+ *		changes to allow the server to  track the relevant state of each
+ *		client without the need for  polling commands. The current state
+ *		changes that generate status messages are:
+ *
+ *			Application start up,
+ *			"Enable Tx" button status changes,
+ *			Dial frequency changes,
+ *			Changes to the "DX Call" field,
+ *			Operating mode changes,
+ *			Transmit mode changed (in dual JT9+JT65 mode),
+ *			Changes to the "Rpt" spinner,
+ *			After an old decodes replay sequence (see Replay below),
+ *			When switching between Tx and Rx mode.
+ *
+ *
+ * Decode        Out       2                      quint32
+ *                         Id (unique key)        utf8
+ *                         New                    bool
+ *                         Time                   QTime
+ *                         snr                    qint32
+ *                         Delta time (S)         float (serialized as double)
+ *                         Delta frequency (Hz)   quint32
+ *                         Mode                   utf8
+ *                         Message                utf8
+ *
+ *			The decode message is send when  a new decode is completed, in
+ *			this case the 'New' field is true. It is also used in response
+ *			to  a "Replay"  message where  each  old decode  in the  "Band
+ *			activity" window, that  has not been erased, is  sent in order
+ *			as  a one  of  these  messages with  the  'New'  field set  to
+ *			false. See the "Replay" message below for details of usage.
+ *
+ *
+ * Clear         Out       3                      quint32
+ *                         Id (unique key)        utf8
+ *
+ *			This message is  send when all prior "Decode"  messages in the
+ *			"Band activity"  window have been discarded  and therefore are
+ *			no long available for actioning  with a "Reply" message. It is
+ *			sent when the user erases  the "Band activity" window and when
+ *			WSJT-X  closes down  normally. The  server should  discard all
+ *			decode messages upon receipt of this message.
+ *
+ *
+ * Reply         In        4                      quint32
+ *                         Id (target unique key) utf8
+ *                         Time                   QTime
+ *                         snr                    qint32
+ *                         Delta time (S)         float (serialized as double)
+ *                         Delta frequency (Hz)   quint32
+ *                         Mode                   utf8
+ *                         Message                utf8
+ *
+ *			In order for a server  to provide a useful cooperative service
+ *			to WSJT-X it  is possible for it to initiate  a QSO by sending
+ *			this message to a client. WSJT-X filters this message and only
+ *			acts upon it  if the message exactly describes  a prior decode
+ *			and that decode  is a CQ or QRZ message.   The action taken is
+ *			exactly equivalent to the user  double clicking the message in
+ *			the "Band activity" window. The  intent of this message is for
+ *			servers to be able to provide an advanced look up of potential
+ *			QSO partners, for example determining if they have been worked
+ *			before  or if  working them  may advance  some objective  like
+ *			award progress.  The  intention is not to  provide a secondary
+ *			user  interface for  WSJT-X,  it is  expected  that after  QSO
+ *			initiation the rest  of the QSO is carried  out manually using
+ *			the normal WSJT-X user interface.
+ *
+ *
+ * QSO Logged    Out       5                      quint32
+ *                         Id (unique key)        utf8
+ *                         Date & Time            QDateTime
+ *                         DX call                utf8
+ *                         DX grid                utf8
+ *                         Dial frequency (Hz)    quint64
+ *                         Mode                   utf8
+ *                         Report send            utf8
+ *                         Report received        utf8
+ *                         Tx power               utf8
+ *                         Comments               utf8
+ *                         Name                   utf8
+ *
+ *			The  QSO logged  message is  sent  to the  server(s) when  the
+ *			WSJT-X user accepts the "Log  QSO" dialog by clicking the "OK"
+ *			button.
+ *
+ *
+ * Close         Out       6                      quint32
+ *                         Id (unique key)        utf8
+ *
+ *			Close is sent by a client immediately prior to it shutting
+ *			down gracefully.
+ *
+ *
+ * Replay        In        7                      quint32
+ *                         Id (unique key)        utf8
+ *
+ *			When a server starts it may  be useful for it to determine the
+ *			state  of preexisting  clients. Sending  this message  to each
+ *			client as it is discovered  will cause that client (WSJT-X) to
+ *			send a "Decode" message for each decode currently in its "Band
+ *			activity"  window. Each  "Decode" message  sent will  have the
+ *			"New" flag set to false so that they can be distinguished from
+ *			new decodes. After  all the old decodes have  been broadcast a
+ *			"Status" message  is also broadcast.  If the server  wishes to
+ *			determine  the  status  of  a newly  discovered  client;  this
+ *			message should be used.
+ *
+ *
+ * Halt Tx       In        8
+ *                         Id (unique key)        utf8
+ *                         Auto Tx Only           bool
+ *
+ *			The server may stop a client from transmitting messages either
+ * 			immediately or at  the end of the  current transmission period
+ * 			using this message.
+ *
+ *
+ * Free Text     In        9
+ *                         Id (unique key)        utf8
+ *                         Text                   utf8
+ *                         Send                   bool
+ *
+ *			This message  allows the server  to set the current  free text
+ *			message content. Sending this  message is equivalent to typing
+ *			a new  message (old contents  are discarded) in to  the WSJT-X
+ *			free text message field or  "Tx5" field (both are updated) and
+ *			if the Send  flag is set then clicking the  "Now" radio button
+ *			for the  "Tx5" field  if tab  one is  current or  clicking the
+ *			"Free msg"  radio button  if tab  two is  current.  It  is the
+ *			responsibility  of  the sender  to  limit  the length  of  the
+ *			message text and to limit it to legal message characters.
+ */
+
+#include <QDataStream>
+
+#include "pimpl_h.hpp"
+
+class QIODevice;
+class QByteArray;
+class QString;
+
+namespace NetworkMessage
+{
+  // NEVER DELETE MESSAGE TYPES
+  enum Type
+    {
+      Heartbeat,
+      Status,
+      Decode,
+      Clear,
+      Reply,
+      QSOLogged,
+      Close,
+      Replay,
+      HaltTx,
+      FreeText,
+      maximum_message_type_     // ONLY add new message types
+                                // immediately before here
+    };
+
+  quint32 constexpr pulse {15}; // seconds
+
+  //
+  // NetworkMessage::Build - build a message containing serialized Qt types
+  //
+  class Builder
+    : public QDataStream
+  {
+  public:
+    static quint32 constexpr magic {0xadbccbda}; // never change this
+
+    // increment this if a newer Qt schema is required and add decode
+    // logic to InputMessageStream below
+    static quint32 constexpr schema_number {2};
+
+    explicit Builder (QIODevice *, Type, QString const& id);
+    explicit Builder (QByteArray *, Type, QString const& id);
+    Builder (Builder const&) = delete;
+    Builder& operator = (Builder const&) = delete;
+
+  private:
+    void common_initialization (Type type, QString const& id);
+  };
+
+  //
+  // NetworkMessage::Reader - read a message containing serialized Qt types
+  //
+  // Message  is as  per NetworkMessage::Builder  above, the  schema()
+  // member  may be  used  to  determine the  schema  of the  original
+  // message.
+  //
+  class Reader
+    : public QDataStream
+  {
+  public:
+    explicit Reader (QIODevice *);
+    explicit Reader (QByteArray const&);
+    Reader (Reader const&) = delete;
+    Reader& operator = (Reader const&) = delete;
+    ~Reader ();
+
+    quint32 schema () const;
+    Type type () const;
+    QString id () const;
+
+  private:
+    class impl;
+    pimpl<impl> m_;
+  };
+}
+
+#endif
diff --git a/NetworkServerLookup.cpp b/NetworkServerLookup.cpp
new file mode 100644
index 0000000..3e0ec34
--- /dev/null
+++ b/NetworkServerLookup.cpp
@@ -0,0 +1,86 @@
+#include "NetworkServerLookup.hpp"
+
+#include <stdexcept>
+
+#include <QHostInfo>
+#include <QString>
+
+std::tuple<QHostAddress, quint16>
+network_server_lookup (QString query
+		       , quint16 default_service_port
+		       , QHostAddress default_host_address
+		       , QAbstractSocket::NetworkLayerProtocol required_protocol)
+{
+  query = query.trimmed ();
+
+  QHostAddress host_address {default_host_address};
+  quint16 service_port {default_service_port};
+
+  QString host_name;
+  if (!query.isEmpty ())
+    {
+      int port_colon_index {-1};
+
+      if ('[' == query[0])
+        {
+          // assume IPv6 combined address/port syntax [<address>]:<port>
+          auto close_bracket_index = query.lastIndexOf (']');
+          host_name = query.mid (1, close_bracket_index - 1);
+          port_colon_index = query.indexOf (':', close_bracket_index);
+        }
+      else
+        {
+          port_colon_index = query.lastIndexOf (':');
+          host_name = query.left (port_colon_index);
+        }
+      host_name = host_name.trimmed ();
+
+      if (port_colon_index >= 0)
+        {
+          bool ok;
+          service_port = query.mid (port_colon_index + 1).trimmed ().toUShort (&ok);
+          if (!ok)
+            {
+              throw std::runtime_error {"network server lookup error: invalid port"};
+            }
+        }
+    }
+
+  if (!host_name.isEmpty ())
+    {
+      auto host_info = QHostInfo::fromName (host_name);
+      if (host_info.addresses ().isEmpty ())
+        {
+          throw std::runtime_error {"network server lookup error: host name lookup failed"};
+        }
+
+      bool found {false};
+      for (int i {0}; i < host_info.addresses ().size () && !found; ++i)
+        {
+          host_address = host_info.addresses ().at (i);
+          switch (required_protocol)
+            {
+            case QAbstractSocket::IPv4Protocol:
+            case QAbstractSocket::IPv6Protocol:
+              if (required_protocol != host_address.protocol ())
+                {
+                  break;
+                }
+              // drop through
+
+            case QAbstractSocket::AnyIPProtocol:
+              found = true;
+              break;
+
+            default:
+              throw std::runtime_error {"network server lookup error: invalid required protocol"};
+            }
+        }
+      if (!found)
+        {
+          throw std::runtime_error {"network server lookup error: no suitable host address found"};
+        }
+    }
+
+  return std::make_tuple (host_address, service_port);
+}
diff --git a/NetworkServerLookup.hpp b/NetworkServerLookup.hpp
new file mode 100644
index 0000000..7c7c9d1
--- /dev/null
+++ b/NetworkServerLookup.hpp
@@ -0,0 +1,38 @@
+#ifndef NETWORK_SERVER_LOOKUP_HPP__
+#define NETWORK_SERVER_LOOKUP_HPP__
+
+#include <tuple>
+
+#include <QHostAddress>
+#include <QAbstractSocket>
+
+class QString;
+
+//
+// Do a blocking DNS lookup using query as a destination host address
+// and port.
+//
+// query can be one of:
+//
+// 1) "" (empty string) - use defaults
+// 2) ":nnnnn" - override default service port with port nnnnn
+// 3) "<valid-host-name>" - override default host address with DNS lookup
+// 4) "nnn.nnn.nnn.nnn" - override default host address with the IPv4 address given by nnn.nnn.nnn.nnn
+// 5) "[<valid-IPv6-address]" - override default host address with the given IPv6 address
+// 6) "<valid-host-name>:nnnnn" - use as per (3) & (2)
+// 7) "nnn.nnn.nnn.nnn:nnnnn" - use as per (4) & (2)
+// 8) "[<valid-IPv6-address]:nnnnn" - use as per (5) & (2)
+//
+// The first host address matching the protocol and the service port
+// number are returned.
+//
+// If no suitable host address is found QHostAddress::Null will be
+// returned in the first member of the result tuple.
+//
+std::tuple<QHostAddress, quint16>
+network_server_lookup (QString query
+		       , quint16 default_service_port
+		       , QHostAddress default_host_address = QHostAddress::LocalHost
+		       , QAbstractSocket::NetworkLayerProtocol protocol = QAbstractSocket::AnyIPProtocol);
+
+#endif
diff --git a/OmniRigTransceiver.cpp b/OmniRigTransceiver.cpp
new file mode 100644
index 0000000..4621d5f
--- /dev/null
+++ b/OmniRigTransceiver.cpp
@@ -0,0 +1,620 @@
+#include "OmniRigTransceiver.hpp"
+
+#include <QTimer>
+#include <QDebug>
+#include <objbase.h>
+
+#include "qt_helpers.hpP"
+
+#include "moc_OmniRigTransceiver.cpp"
+
+namespace
+{
+  auto constexpr OmniRig_transceiver_one_name = "OmniRig Rig 1";
+  auto constexpr OmniRig_transceiver_two_name = "OmniRig Rig 2";
+}
+
+auto OmniRigTransceiver::map_mode (OmniRig::RigParamX param) -> MODE
+{
+  if (param & OmniRig::PM_CW_U)
+    {
+      return CW_R;
+    }
+  else if (param & OmniRig::PM_CW_L)
+    {
+      return CW;
+    }
+  else if (param & OmniRig::PM_SSB_U)
+    {
+      return USB;
+    }
+  else if (param & OmniRig::PM_SSB_L)
+    {
+      return LSB;
+    }
+  else if (param & OmniRig::PM_DIG_U)
+    {
+      return DIG_U;
+    }
+  else if (param & OmniRig::PM_DIG_L)
+    {
+      return DIG_L;
+    }
+  else if (param & OmniRig::PM_AM)
+    {
+      return AM;
+    }
+  else if (param & OmniRig::PM_FM)
+    {
+      return FM;
+    }
+  TRACE_CAT ("unrecognized mode");
+  throw_qstring (tr ("OmniRig: unrecognized mode"));
+  return UNK;
+}
+
+OmniRig::RigParamX OmniRigTransceiver::map_mode (MODE mode)
+{
+  switch (mode)
+    {
+    case AM: return OmniRig::PM_AM;
+    case CW: return OmniRig::PM_CW_L;
+    case CW_R: return OmniRig::PM_CW_U;
+    case USB: return OmniRig::PM_SSB_U;
+    case LSB: return OmniRig::PM_SSB_L;
+    case FSK: return OmniRig::PM_DIG_L;
+    case FSK_R: return OmniRig::PM_DIG_U;
+    case DIG_L: return OmniRig::PM_DIG_L;
+    case DIG_U: return OmniRig::PM_DIG_U;
+    case FM: return OmniRig::PM_FM;
+    case DIG_FM: return OmniRig::PM_FM;
+    default: break;
+    }
+  return OmniRig::PM_SSB_U;	// quieten compiler grumble
+}
+
+void OmniRigTransceiver::register_transceivers (TransceiverFactory::Transceivers * registry, int id1, int id2)
+{
+  (*registry)[OmniRig_transceiver_one_name] = TransceiverFactory::Capabilities {
+    id1
+    , TransceiverFactory::Capabilities::none // COM isn't serial or network
+    , true				     // does PTT
+    , false				     // doesn't select mic/data (use OmniRig config file)
+    , true				     // can remote control RTS nd DTR
+    , true				     // asynchronous interface
+  };
+  (*registry)[OmniRig_transceiver_two_name] = TransceiverFactory::Capabilities {
+    id2
+    , TransceiverFactory::Capabilities::none // COM isn't serial or network
+    , true				     // does PTT
+    , false				     // doesn't select mic/data (use OmniRig config file)
+    , true				     // can remote control RTS nd DTR
+    , true				     // asynchronous interface
+  };
+}
+
+OmniRigTransceiver::OmniRigTransceiver (std::unique_ptr<TransceiverBase> wrapped, RigNumber n, TransceiverFactory::PTTMethod ptt_type, QString const& ptt_port)
+  : wrapped_ {std::move (wrapped)}
+  , use_for_ptt_ {TransceiverFactory::PTT_method_CAT == ptt_type || ("CAT" == ptt_port && (TransceiverFactory::PTT_method_RTS == ptt_type || TransceiverFactory::PTT_method_DTR == ptt_type))}
+  , ptt_type_ {ptt_type}
+  , rig_number_ {n}
+  , readable_params_ {0}
+  , writable_params_ {0}
+  , send_update_signal_ {false}
+  , reversed_ {false}
+{
+}
+
+OmniRigTransceiver::~OmniRigTransceiver ()
+{
+}
+
+void OmniRigTransceiver::do_start ()
+{
+  TRACE_CAT ("starting");
+  wrapped_->start ();
+
+  CoInitializeEx (nullptr, 0 /*COINIT_APARTMENTTHREADED*/); // required because Qt only does this for GUI thread
+
+  omni_rig_.reset (new OmniRig::OmniRigX {this});
+  if (omni_rig_->isNull ())
+    {
+      TRACE_CAT ("failed to start COM server");
+      throw_qstring (tr ("Failed to start OmniRig COM server"));
+    }
+
+  // COM/OLE exceptions get signalled
+  connect (&*omni_rig_, SIGNAL (exception (int, QString, QString, QString)), this, SLOT (handle_COM_exception (int, QString, QString, QString)));
+
+  // IOmniRigXEvent interface signals
+  connect (&*omni_rig_, SIGNAL (VisibleChange ()), this, SLOT (handle_visible_change ()));
+  connect (&*omni_rig_, SIGNAL (RigTypeChange (int)), this, SLOT (handle_rig_type_change (int)));
+  connect (&*omni_rig_, SIGNAL (StatusChange (int)), this, SLOT (handle_status_change (int)));
+  connect (&*omni_rig_, SIGNAL (ParamsChange (int, int)), this, SLOT (handle_params_change (int, int)));
+  connect (&*omni_rig_
+           , SIGNAL (CustomReply (int, QVariant const&, QVariant const&))
+           , this, SLOT (handle_custom_reply (int, QVariant const&, QVariant const&)));
+
+  TRACE_CAT ("OmniRig s/w version:" << QString::number (omni_rig_->SoftwareVersion ()).toLocal8Bit ()
+             << "i/f version:" << QString::number (omni_rig_->InterfaceVersion ()).toLocal8Bit ());
+
+  // fetch the interface of the RigX CoClass and instantiate a proxy object
+  switch (rig_number_)
+    {
+    case One: rig_.reset (new OmniRig::RigX (omni_rig_->Rig1 ())); break;
+    case Two: rig_.reset (new OmniRig::RigX (omni_rig_->Rig2 ())); break;
+    }
+
+  Q_ASSERT (rig_);
+  Q_ASSERT (!rig_->isNull ());
+
+  if (use_for_ptt_ && (TransceiverFactory::PTT_method_DTR == ptt_type_ || TransceiverFactory::PTT_method_RTS == ptt_type_))
+    {
+      // fetch the interface for the serial port if we need it for PTT
+      port_.reset (new OmniRig::PortBits (rig_->PortBits ()));
+
+      Q_ASSERT (port_);
+      Q_ASSERT (!port_->isNull ());
+
+      // if (!port_->Lock ()) // try to take exclusive use of the OmniRig serial port for PTT
+      // 	{
+      // 	  throw_qstring (tr ("Failed to get exclusive use of %1" from OmniRig").arg (ptt_type));
+      // 	}
+
+      // start off so we don't accidentally key the radio
+      if (TransceiverFactory::PTT_method_DTR == ptt_type_)
+        {
+          port_->SetDtr (false);
+        }
+      else			// RTS
+        {
+          port_->SetRts (false);
+        }
+    }
+
+  readable_params_ = rig_->ReadableParams ();
+  writable_params_ = rig_->WriteableParams ();
+
+  TRACE_CAT (QString {"OmniRig initial rig type: %1 readable params = 0x%2 writable params = 0x%3 for rig %4"}
+    .arg (rig_->RigType ())
+    .arg (readable_params_, 8, 16, QChar ('0'))
+    .arg (writable_params_, 8, 16, QChar ('0'))
+    .arg (rig_number_).toLocal8Bit ());
+
+  TRACE_CAT ("OmniRig status:" << rig_->StatusStr ());
+
+  init_rig ();
+}
+
+void OmniRigTransceiver::do_stop ()
+{
+  if (port_)
+    {
+      // port_->Unlock ();		// release serial port
+      port_->clear ();
+    }
+  rig_->clear ();
+  omni_rig_->clear ();
+  CoUninitialize ();
+  wrapped_->stop ();
+  TRACE_CAT ("stopped");
+}
+
+void OmniRigTransceiver::online_check ()
+{
+  if (OmniRig::ST_ONLINE != rig_->Status ())
+    {
+      offline ("OmniRig rig went offline for more than 5 seconds");
+    }
+  else
+    {
+      init_rig ();
+    }
+}
+
+void OmniRigTransceiver::init_rig ()
+{
+  if (OmniRig::ST_ONLINE != rig_->Status ())
+    {
+      QTimer::singleShot (5000, this, SLOT (online_check ()));
+    }
+  else
+    {
+      update_rx_frequency (rig_->GetRxFrequency ());
+      if (state ().split ())
+        {
+          TRACE_CAT ("set split");
+          rig_->SetSplitMode (state ().frequency (), state ().tx_frequency ());
+        }
+      else
+        {
+          TRACE_CAT ("set simplex");
+          rig_->SetSimplexMode (state ().frequency ());
+        }
+    }
+}
+
+void OmniRigTransceiver::do_sync (bool force_signal)
+{
+  // nothing much we can do here, we just have to let OmniRig do its
+  // stuff and its first poll should send us and update that will
+  // trigger a update signal from us. Any attempt to query OmniRig
+  // leads to a whole mess of trouble since its internal state is
+  // garbage until it has done its first rig poll.
+  send_update_signal_ = force_signal;
+  update_complete ();
+}
+
+void OmniRigTransceiver::handle_COM_exception (int code, QString source, QString desc, QString help)
+{
+  TRACE_CAT (QString::number (code) + " at " + source + ": " + desc + " (" + help + ')');
+  throw_qstring (tr ("OmniRig COM/OLE error: %1 at %2: %3 (%4)").arg (QString::number (code)).arg (source). arg (desc). arg (help));
+}
+
+void OmniRigTransceiver::handle_visible_change ()
+{
+  TRACE_CAT ("visibility change: visibility =" << omni_rig_->DialogVisible ());
+}
+
+void OmniRigTransceiver::handle_rig_type_change (int rig_number)
+{
+  if (rig_number_ == rig_number)
+    {
+      readable_params_ = rig_->ReadableParams ();
+      writable_params_ = rig_->WriteableParams ();
+      TRACE_CAT (QString {"OmniRig rig type change to: %1 readable params = 0x%2 writable params = 0x%3 for rig %4"}
+        .arg (rig_->RigType ())
+        .arg (readable_params_, 8, 16, QChar ('0'))
+        .arg (writable_params_, 8, 16, QChar ('0'))
+        .arg (rig_number).toLocal8Bit ());
+      offline ("OmniRig rig changed");
+    }
+}
+
+void OmniRigTransceiver::handle_status_change (int rig_number)
+{
+  if (rig_number_ == rig_number)
+    {
+      TRACE_CAT (QString {"OmniRig status change: new status for rig %1 = "}.arg (rig_number).toLocal8Bit () << rig_->StatusStr ().toLocal8Bit ());
+      if (OmniRig::ST_ONLINE != rig_->Status ())
+        {
+          QTimer::singleShot (5000, this, SLOT (online_check ()));
+        }
+    }
+}
+
+void OmniRigTransceiver::handle_params_change (int rig_number, int params)
+{
+  if (rig_number_ == rig_number)
+    {
+      TRACE_CAT (QString {"OmniRig params change: params = 0x%1 for rig %2"}
+        .arg (params, 8, 16, QChar ('0'))
+        .arg (rig_number).toLocal8Bit ()
+        << "state before:" << state ());
+      //      starting_ = false;
+      TransceiverState old_state {state ()};
+      auto need_frequency = false;
+      // state_.online = true;	// sometimes we don't get an initial
+      // 				// OmniRig::ST_ONLINE status change
+      // 				// event
+      if (params & OmniRig::PM_VFOAA)
+        {
+          update_split (false);
+          reversed_ = false;
+          update_rx_frequency (rig_->FreqA ());
+          update_other_frequency (rig_->FreqB ());
+        }
+      if (params & OmniRig::PM_VFOAB)
+        {
+          update_split (true);
+          reversed_ = false;
+          update_rx_frequency (rig_->FreqA ());
+          update_other_frequency (rig_->FreqB ());
+        }
+      if (params & OmniRig::PM_VFOBA)
+        {
+          update_split (true);
+          reversed_ = true;
+          update_other_frequency (rig_->FreqA ());
+          update_rx_frequency (rig_->FreqB ());
+        }
+      if (params & OmniRig::PM_VFOBB)
+        {
+          update_split (false);
+          reversed_ = true;
+          update_other_frequency (rig_->FreqA ());
+          update_rx_frequency (rig_->FreqB ());
+        }
+      if (params & OmniRig::PM_VFOA)
+        {
+          reversed_ = false;
+          need_frequency = true;
+        }
+      if (params & OmniRig::PM_VFOB)
+        {
+          reversed_ = true;
+          need_frequency = true;
+        }
+
+      if (params & OmniRig::PM_FREQ)
+        {
+          need_frequency = true;
+        }
+      if (params & OmniRig::PM_FREQA)
+        {
+          if (reversed_)
+            {
+              update_other_frequency (rig_->FreqA ());
+            }
+          else
+            {
+              update_rx_frequency (rig_->FreqA ());
+            }
+        }
+      if (params & OmniRig::PM_FREQB)
+        {
+          if (reversed_)
+            {
+              update_rx_frequency (rig_->FreqB ());
+            }
+          else
+            {
+              update_other_frequency (rig_->FreqB ());
+            }
+        }
+      if (need_frequency)
+        {
+          if (readable_params_ & OmniRig::PM_FREQA)
+            {
+              if (reversed_)
+                {
+                  update_other_frequency (rig_->FreqA ());
+                }
+              else
+                {
+                  update_rx_frequency (rig_->FreqA ());
+                }
+              need_frequency = false;
+            }
+          if (readable_params_ & OmniRig::PM_FREQB)
+            {
+              if (reversed_)
+                {
+                  update_rx_frequency (rig_->FreqB ());
+                }
+              else
+                {
+                  update_other_frequency (rig_->FreqB ());
+                }
+            }
+        }
+      if (need_frequency && (readable_params_ & OmniRig::PM_FREQ))
+        {
+          update_rx_frequency (rig_->Freq ());
+        }
+      if (params & OmniRig::PM_PITCH)
+        {
+        }
+      if (params & OmniRig::PM_RITOFFSET)
+        {
+        }
+      if (params & OmniRig::PM_RIT0)
+        {
+        }
+      if (params & OmniRig::PM_VFOEQUAL)
+        {
+          auto f = readable_params_ & OmniRig::PM_FREQA ? rig_->FreqA () : rig_->Freq ();
+          update_rx_frequency (f);
+          update_other_frequency (f);
+          update_mode (map_mode (rig_->Mode ()));
+        }
+      if (params & OmniRig::PM_VFOSWAP)
+        {
+          auto temp = state ().tx_frequency ();
+          update_other_frequency (state ().frequency ());
+          update_rx_frequency (temp);
+          update_mode (map_mode (rig_->Mode ()));
+        }
+      if (params & OmniRig::PM_SPLITON)
+        {
+          update_split (true);
+        }
+      if (params & OmniRig::PM_SPLITOFF)
+        {
+          update_split (false);
+        }
+      if (params & OmniRig::PM_RITON)
+        {
+        }
+      if (params & OmniRig::PM_RITOFF)
+        {
+        }
+      if (params & OmniRig::PM_XITON)
+        {
+        }
+      if (params & OmniRig::PM_XITOFF)
+        {
+        }
+      if (params & OmniRig::PM_RX)
+        {
+          update_PTT (false);
+        }
+      if (params & OmniRig::PM_TX)
+        {
+          update_PTT ();
+        }
+      if (params & OmniRig::PM_CW_U)
+        {
+          update_mode (CW_R);
+        }
+      if (params & OmniRig::PM_CW_L)
+        {
+          update_mode (CW);
+        }
+      if (params & OmniRig::PM_SSB_U)
+        {
+          update_mode (USB);
+        }
+      if (params & OmniRig::PM_SSB_L)
+        {
+          update_mode (LSB);
+        }
+      if (params & OmniRig::PM_DIG_U)
+        {
+          update_mode (DIG_U);
+        }
+      if (params & OmniRig::PM_DIG_L)
+        {
+          update_mode (DIG_L);
+        }
+      if (params & OmniRig::PM_AM)
+        {
+          update_mode (AM);
+        }
+      if (params & OmniRig::PM_FM)
+        {
+          update_mode (FM);
+        }
+
+      if (old_state != state () || send_update_signal_)
+        {
+          update_complete ();
+          send_update_signal_ = false;
+        }
+      TRACE_CAT ("OmniRig params change: state after:" << state ());
+    }
+}
+
+void OmniRigTransceiver::handle_custom_reply (int rig_number, QVariant const& command, QVariant const& reply)
+{
+  (void)command;
+  (void)reply;
+
+  if (rig_number_ == rig_number)
+    {
+      TRACE_CAT ("OmniRig custom command" << command.toString ().toLocal8Bit ()
+                 << "with reply" << reply.toString ().toLocal8Bit ()
+                 << QString ("for rig %1").arg (rig_number).toLocal8Bit ());
+      TRACE_CAT ("OmniRig rig number:" << rig_number_ << ':' << state ());
+    }
+}
+
+void OmniRigTransceiver::do_ptt (bool on)
+{
+  TRACE_CAT (on << state ());
+  if (use_for_ptt_ && TransceiverFactory::PTT_method_CAT == ptt_type_)
+    {
+      TRACE_CAT ("set PTT");
+      rig_->SetTx (on ? OmniRig::PM_TX : OmniRig::PM_RX);
+    }
+  else
+    {
+      if (port_)
+        {
+          if (TransceiverFactory::PTT_method_RTS == ptt_type_)
+            {
+              TRACE_CAT ("set RTS");
+              port_->SetRts (on);
+            }
+          else			// "DTR"
+            {
+              TRACE_CAT  ("set DTR");
+              port_->SetDtr (on);
+            }
+        }
+      else
+        {
+          TRACE_CAT ("set PTT using basic transceiver");
+          wrapped_->ptt (on);
+        }
+      if (state ().ptt () != on)
+        {
+          update_PTT (on);
+          // no need for this as currently update_PTT() does it for us
+          // update_complete ();
+        }
+    }
+}
+
+void OmniRigTransceiver::do_frequency (Frequency f, MODE m)
+{
+  TRACE_CAT (f << state ());
+  if (UNK != m)
+    {
+      do_mode (m, false);
+    }
+  if (OmniRig::PM_FREQ & writable_params_)
+    {
+      rig_->SetFreq (f);
+      update_rx_frequency (f);
+    }
+  else if (reversed_ && (OmniRig::PM_FREQB & writable_params_))
+    {
+      rig_->SetFreqB (f);
+      update_rx_frequency (f);
+    }
+  else if (!reversed_ && (OmniRig::PM_FREQA & writable_params_))
+    {
+      rig_->SetFreqA (f);
+      update_rx_frequency (f);
+    }
+  else
+    {
+      throw_qstring (tr ("OmniRig: don't know how to set rig frequency"));
+    }
+}
+
+void OmniRigTransceiver::do_tx_frequency (Frequency tx, bool /* rationalise_mode */)
+{
+  TRACE_CAT (tx << state ());
+  bool split {tx != 0};
+  if (split)
+    {
+      TRACE_CAT ("set SPLIT mode on");
+      rig_->SetSplitMode (state ().frequency (), tx);
+      update_other_frequency (tx);
+      update_split (true);
+    }
+  else
+    {
+      TRACE_CAT ("set SPLIT mode off");
+      rig_->SetSimplexMode (state ().frequency ());
+      update_split (false);
+    }
+  bool notify {false};
+  if (readable_params_ & OmniRig::PM_FREQ || !(readable_params_ & (OmniRig::PM_FREQA | OmniRig::PM_FREQB)))
+    {
+      update_other_frequency (tx); // async updates won't return this
+      // so just store it and hope
+      // operator doesn't change the
+      // "back" VFO on rig
+      notify = true;
+    }
+  if (!((OmniRig::PM_VFOAB | OmniRig::PM_VFOBA | OmniRig::PM_SPLITON) & readable_params_))
+    {
+      TRACE_CAT ("setting SPLIT manually");
+      update_split (split);	// we can't read it so just set and
+      // hope op doesn't change it
+      notify = true;
+    }
+  if (notify)
+    {
+      update_complete ();
+    }
+}
+
+void OmniRigTransceiver::do_mode (MODE mode, bool /* rationalise */)
+{
+  TRACE_CAT (mode << state ());
+  // TODO: G4WJS OmniRig doesn't seem to have any capability of tracking/setting VFO B mode
+  auto mapped = map_mode (mode);
+  if (mapped & writable_params_)
+    {
+      rig_->SetMode (mapped);
+      update_mode (mode);
+    }
+  else
+    {
+      offline ("OmniRig invalid mode");
+    }
+}
diff --git a/OmniRigTransceiver.hpp b/OmniRigTransceiver.hpp
new file mode 100644
index 0000000..d5c41a9
--- /dev/null
+++ b/OmniRigTransceiver.hpp
@@ -0,0 +1,71 @@
+#ifndef OMNI_RIG_TRANSCEIVER_HPP__
+#define OMNI_RIG_TRANSCEIVER_HPP__
+
+#include <memory>
+
+#include <QScopedPointer>
+#include <QString>
+
+#include "TransceiverFactory.hpp"
+#include "TransceiverBase.hpp"
+
+#include "OmniRig.h"
+
+//
+// OmniRig Transceiver Interface
+//
+// Implemented as a Transceiver decorator  because we may want the PTT
+// services of another Transceiver  type such as the HamlibTransceiver
+// which can  be enabled by wrapping  a HamlibTransceiver instantiated
+// as a "Hamlib Dummy" transceiver in the Transceiver factory method.
+//
+class OmniRigTransceiver final
+  : public TransceiverBase
+{
+  Q_OBJECT;
+
+public:
+  static void register_transceivers (TransceiverFactory::Transceivers *, int id1, int id2);
+
+  enum RigNumber {One = 1, Two};
+
+  // takes ownership of wrapped Transceiver
+  explicit OmniRigTransceiver (std::unique_ptr<TransceiverBase> wrapped, RigNumber, TransceiverFactory::PTTMethod ptt_type, QString const& ptt_port);
+  ~OmniRigTransceiver ();
+
+  void do_start () override;
+  void do_stop () override;
+  void do_frequency (Frequency, MODE) override;
+  void do_tx_frequency (Frequency, bool rationalise_mode) override;
+  void do_mode (MODE, bool rationalise) override;
+  void do_ptt (bool on) override;
+  void do_sync (bool force_signal) override;
+
+private:
+  Q_SLOT void online_check ();
+  Q_SLOT void handle_COM_exception (int,  QString, QString, QString);
+  Q_SLOT void handle_visible_change ();
+  Q_SLOT void handle_rig_type_change (int rig_number);
+  Q_SLOT void handle_status_change (int rig_number);
+  Q_SLOT void handle_params_change (int rig_number, int params);
+  Q_SLOT void handle_custom_reply (int, QVariant const& command, QVariant const& reply);
+
+  void init_rig ();
+
+  static MODE map_mode (OmniRig::RigParamX param);
+  static OmniRig::RigParamX map_mode (MODE mode);
+
+  std::unique_ptr<TransceiverBase> wrapped_;
+  bool use_for_ptt_;
+  TransceiverFactory::PTTMethod ptt_type_;
+  QScopedPointer<OmniRig::OmniRigX> omni_rig_;
+  RigNumber rig_number_;
+  QScopedPointer<OmniRig::RigX> rig_;
+  QScopedPointer<OmniRig::PortBits> port_;
+  int readable_params_;
+  int writable_params_;
+  bool send_update_signal_;
+  bool reversed_;   // some rigs can reverse VFOs
+};
+
+#endif
diff --git a/PSKReporter.h b/PSKReporter.h
deleted file mode 100644
index a6c52c4..0000000
--- a/PSKReporter.h
+++ /dev/null
@@ -1,127 +0,0 @@
-#pragma once
-
-// Main header file for the external interface to the PSK Reporter API
-// For documentation see http://psk.gladstonefamily.net/PSKReporterAPI.pdf
-
-/*
-
-Copyright (c) 2008 Philip Gladstone
-
-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.
-
- */
-
-
-#ifdef _DLL_OPTION_PSKREPORTER_EXPORT
-#define DllImportExport __declspec ( dllexport )
-#else
-#define DllImportExport __declspec ( dllimport )
-#endif
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif 
-
-#define REPORTER_SOURCE_MASK		0x07
-#define REPORTER_SOURCE_AUTOMATIC	0x01
-#define REPORTER_SOURCE_LOG			0x02
-#define REPORTER_SOURCE_MANUAL		0x03
-#define REPORTER_SOURCE_TENTATIVE	0x40 
-#define REPORTER_SOURCE_TEST		0x80 
-
-typedef struct {
-	wchar_t 	  hostname[256];
-	wchar_t 	  port[32];
-	bool	  	  connected;
-	unsigned int  callsigns_sent;
-	unsigned int  callsigns_buffered;
-	unsigned int  callsigns_discarded;
-	unsigned int  last_send_time;
-	unsigned int  next_send_time;
-	wchar_t	      last_callsign_queued[24];
-	unsigned int  bytes_sent;
-	unsigned int  bytes_sent_total;
-	unsigned int  packets_sent;
-	unsigned int  packets_sent_total;
-} REPORTER_STATISTICS;
-
-
-
-
-unsigned long DllImportExport __cdecl ReporterInitialize(
-	const wchar_t *hostname,
-	const wchar_t *port
-);
-
-unsigned long DllImportExport __cdecl ReporterSeenCallsign(
-	const wchar_t *remoteInformation,
-	const wchar_t *localInformation,
-	unsigned long flags
-);
-
-unsigned long DllImportExport __cdecl ReporterTickle(
-);
-
-unsigned long DllImportExport __cdecl ReporterGetInformation(
-	wchar_t *buffer,
-	unsigned long maxlen
-);
-
-unsigned long DllImportExport __cdecl ReporterGetStatistics(
-	REPORTER_STATISTICS *buffer,
-	unsigned long maxlen
-);
-
-unsigned long DllImportExport __cdecl ReporterUninitialize(
-);
-
-
-unsigned long DllImportExport __stdcall ReporterInitializeSTD(
-	const char *hostname,
-	const char *port
-);
-
-unsigned long DllImportExport __stdcall ReporterSeenCallsignSTD(
-	const char *remoteInformation,
-	const char *localInformation,
-	unsigned long flags
-);
-
-unsigned long DllImportExport __stdcall ReporterTickleSTD(
-);
-
-unsigned long DllImportExport __stdcall ReporterGetInformationSTD(
-	char *buffer,
-	unsigned long maxlen
-);
-
-unsigned long DllImportExport __stdcall ReporterGetStatisticsSTD(
-	REPORTER_STATISTICS *buffer,
-	unsigned long maxlen
-);
-
-unsigned long DllImportExport __stdcall ReporterUninitializeSTD(
-);
-
-#ifdef __cplusplus
-}
-#endif 
-
-
diff --git a/Palettes/Banana.pal b/Palettes/Banana.pal
new file mode 100644
index 0000000..f0d60cf
--- /dev/null
+++ b/Palettes/Banana.pal
@@ -0,0 +1,9 @@
+  0;  0;  0
+ 59; 59; 27
+119;119; 59
+179;179; 91
+227;227;123
+235;235;151
+239;239;183
+247;247;219
+255;255;255
diff --git a/Palettes/Blue1.pal b/Palettes/Blue1.pal
new file mode 100644
index 0000000..5798365
--- /dev/null
+++ b/Palettes/Blue1.pal
@@ -0,0 +1,9 @@
+  0;  0;  2
+  0;  0; 64
+  7; 11;128
+ 39; 47;192
+ 95;115;217
+151;179;231
+187;203;239
+219;227;247
+255;255;255
diff --git a/Palettes/Blue2.pal b/Palettes/Blue2.pal
new file mode 100644
index 0000000..c08f1e3
--- /dev/null
+++ b/Palettes/Blue2.pal
@@ -0,0 +1,9 @@
+  3;  3; 64
+  7; 11;128
+ 39; 47;192
+ 95;115;217
+151;179;231
+187;203;239
+219;227;247
+255;255;255
+255;253;108
diff --git a/Palettes/Blue3.pal b/Palettes/Blue3.pal
new file mode 100644
index 0000000..a7e43d8
--- /dev/null
+++ b/Palettes/Blue3.pal
@@ -0,0 +1,9 @@
+  0;  0;  0
+ 31; 31; 31
+ 63; 63; 63
+ 91; 91;167
+119;119;191
+155;155;219
+191;191;191
+223;223;223
+255;255;255
diff --git a/Palettes/Brown.pal b/Palettes/Brown.pal
new file mode 100644
index 0000000..68027df
--- /dev/null
+++ b/Palettes/Brown.pal
@@ -0,0 +1,9 @@
+  0;  0;  0
+107; 63; 11
+175; 95; 31
+199;119; 43
+215;163; 63
+231;211; 87
+243;247;111
+247;251;179
+255;255;255
diff --git a/Palettes/Cyan1.pal b/Palettes/Cyan1.pal
new file mode 100644
index 0000000..91e3278
--- /dev/null
+++ b/Palettes/Cyan1.pal
@@ -0,0 +1,9 @@
+  0;  0;  0
+  5; 10; 10
+ 22; 42; 42
+ 52; 99; 99
+ 94;175;175
+131;209;209
+162;224;224
+202;239;239
+255;255;255
diff --git a/Palettes/Cyan2.pal b/Palettes/Cyan2.pal
new file mode 100644
index 0000000..01b96e6
--- /dev/null
+++ b/Palettes/Cyan2.pal
@@ -0,0 +1,9 @@
+  0;  0;  0
+ 35; 51; 51
+ 75;103;103
+115;159;159
+155;211;211
+183;231;231
+203;239;239
+227;247;247
+255;255;255
diff --git a/Palettes/Cyan3.pal b/Palettes/Cyan3.pal
new file mode 100644
index 0000000..793949e
--- /dev/null
+++ b/Palettes/Cyan3.pal
@@ -0,0 +1,9 @@
+  0;  0;  0
+ 94;114;114
+138;162;162
+171;201;201
+199;232;232
+216;243;243
+228;247;247
+241;251;251
+255;255;255
diff --git a/Palettes/Default.pal b/Palettes/Default.pal
new file mode 100644
index 0000000..6816123
--- /dev/null
+++ b/Palettes/Default.pal
@@ -0,0 +1,9 @@
+  0;  0;  0
+  0;  6;136
+  0; 19;198
+  0; 32;239
+172;167;105
+194;198; 49
+225;228;107
+255;255;  0
+255; 51;  0
diff --git a/Palettes/Digipan.pal b/Palettes/Digipan.pal
new file mode 100644
index 0000000..d077642
--- /dev/null
+++ b/Palettes/Digipan.pal
@@ -0,0 +1,9 @@
+  0;  0;  0
+  0;  0; 64
+  0;  0;128
+  0;  0;217
+150;147; 92
+183;186; 46
+225;228;107
+255;255;  0
+255; 51;  0
diff --git a/Palettes/Fldigi.pal b/Palettes/Fldigi.pal
new file mode 100644
index 0000000..74732fd
--- /dev/null
+++ b/Palettes/Fldigi.pal
@@ -0,0 +1,9 @@
+  0;  0;  0
+  0;  0;177
+  3;110;227
+  0;204;204
+223;223;223
+  0;234;  0
+244;244;  0
+250;126;  0
+244;  0;  0
diff --git a/Palettes/Gmfsk.pal b/Palettes/Gmfsk.pal
new file mode 100644
index 0000000..1d103bd
--- /dev/null
+++ b/Palettes/Gmfsk.pal
@@ -0,0 +1,9 @@
+  0;  0;255
+  0; 62;194
+  0;126;130
+  0;190; 66
+  0;254;  2
+ 62;194;  0
+126;130;  0
+190; 66;  0
+254;  2;  0
diff --git a/Palettes/Gray1.pal b/Palettes/Gray1.pal
new file mode 100644
index 0000000..8b87ff2
--- /dev/null
+++ b/Palettes/Gray1.pal
@@ -0,0 +1,9 @@
+  0;  0;  0
+ 69; 69; 69
+ 99; 99; 99
+121;121;121
+140;140;140
+157;157;157
+172;172;172
+186;186;186
+199;199;199
diff --git a/Palettes/Gray2.pal b/Palettes/Gray2.pal
new file mode 100644
index 0000000..b300749
--- /dev/null
+++ b/Palettes/Gray2.pal
@@ -0,0 +1,9 @@
+  0;  0;  0
+ 88; 88; 88
+126;126;126
+155;155;155
+179;179;179
+200;200;200
+220;220;220
+237;237;237
+254;254;254
diff --git a/Palettes/Green1.pal b/Palettes/Green1.pal
new file mode 100644
index 0000000..194e390
--- /dev/null
+++ b/Palettes/Green1.pal
@@ -0,0 +1,9 @@
+  0;  0;  0
+  0; 32;  0
+  0; 64;  0
+  0; 96;  0
+  0;128;  0
+  0;160;  0
+  0;192;  0
+  0;224;  0
+255;255;255
diff --git a/Palettes/Green2.pal b/Palettes/Green2.pal
new file mode 100644
index 0000000..9fa4b85
--- /dev/null
+++ b/Palettes/Green2.pal
@@ -0,0 +1,9 @@
+  0;  0;  0
+  0; 60;  0
+  0;102;  0
+  0;151;  0
+  0;242;  0
+255;255; 89
+240;120;  0
+255;148; 40
+255;  0;  0
diff --git a/Palettes/Jungle.pal b/Palettes/Jungle.pal
new file mode 100644
index 0000000..48cfe06
--- /dev/null
+++ b/Palettes/Jungle.pal
@@ -0,0 +1,9 @@
+  0;  0;  0
+107; 67;  0
+223;143;  0
+255;123; 27
+255; 91; 71
+255;195; 95
+195;255;111
+151;255;151
+255;255;255
diff --git a/Palettes/Linrad.pal b/Palettes/Linrad.pal
new file mode 100644
index 0000000..4ec346f
--- /dev/null
+++ b/Palettes/Linrad.pal
@@ -0,0 +1,9 @@
+  0;  0;  0
+  0;  0; 87
+  0; 79;114
+  0;141; 61
+ 96;158;  0
+204;124;  0
+253; 50; 17
+255;138;138
+255;255;255
diff --git a/Palettes/Negative.pal b/Palettes/Negative.pal
new file mode 100644
index 0000000..e3d726f
--- /dev/null
+++ b/Palettes/Negative.pal
@@ -0,0 +1,9 @@
+255;255;255
+223;223;223
+191;191;191
+159;159;159
+127;127;127
+ 95; 95; 95
+ 63; 63; 63
+ 31; 31; 31
+  0;  0;  0
diff --git a/Palettes/Orange.pal b/Palettes/Orange.pal
new file mode 100644
index 0000000..23e683e
--- /dev/null
+++ b/Palettes/Orange.pal
@@ -0,0 +1,9 @@
+  0;  0;  0
+ 63; 27;  0
+131; 63;  0
+199; 95;  0
+251;127; 11
+251;155; 71
+251;187;131
+251;219;191
+255;255;255
diff --git a/Palettes/Pink.pal b/Palettes/Pink.pal
new file mode 100644
index 0000000..a19cb23
--- /dev/null
+++ b/Palettes/Pink.pal
@@ -0,0 +1,9 @@
+  0;  0;  0
+ 63; 35; 35
+135; 75; 75
+203;111;111
+255;147;147
+255;175;175
+255;199;199
+255;227;227
+255;255;255
diff --git a/Palettes/Rainbow.pal b/Palettes/Rainbow.pal
new file mode 100644
index 0000000..7ca4734
--- /dev/null
+++ b/Palettes/Rainbow.pal
@@ -0,0 +1,9 @@
+  0;  0;163
+  0; 87;191
+  0;207;219
+  0;247;139
+  0;255; 23
+ 95;255;  0
+219;255;  0
+255;171;155
+255;255;255
diff --git a/Palettes/Scope.pal b/Palettes/Scope.pal
new file mode 100644
index 0000000..5c2ef78
--- /dev/null
+++ b/Palettes/Scope.pal
@@ -0,0 +1,9 @@
+  0;  0;  0
+  0;  0;167
+  0; 79;255
+  0;239;255
+  0;255; 75
+ 95;255;  0
+255;255;  0
+255;127;  0
+255;  0;  0
diff --git a/Palettes/Sunburst.pal b/Palettes/Sunburst.pal
new file mode 100644
index 0000000..e286d77
--- /dev/null
+++ b/Palettes/Sunburst.pal
@@ -0,0 +1,9 @@
+  0;  0;  0
+  0;  0; 59
+  0;  0;123
+131;  0;179
+235;  0; 75
+255; 43; 43
+255;215;111
+255;255;183
+255;255;255
diff --git a/Palettes/VK4BDJ.pal b/Palettes/VK4BDJ.pal
new file mode 100644
index 0000000..9d6f09c
--- /dev/null
+++ b/Palettes/VK4BDJ.pal
@@ -0,0 +1,9 @@
+  0;  0;  0
+  0; 32;  0
+  0;154;  0
+  0;161;  0
+  0;177;  0
+156;209;144
+192;185;183
+214;222;224
+255;255;255
diff --git a/Palettes/YL2KF.pal b/Palettes/YL2KF.pal
new file mode 100644
index 0000000..a911679
--- /dev/null
+++ b/Palettes/YL2KF.pal
@@ -0,0 +1,9 @@
+  0;  0;  0
+  0;  0;119
+  7; 11;195
+ 39; 47;159
+ 95;115;203
+151;179;255
+187;203;255
+219;227;255
+255;255;  5
diff --git a/Palettes/Yellow1.pal b/Palettes/Yellow1.pal
new file mode 100644
index 0000000..ce6f30f
--- /dev/null
+++ b/Palettes/Yellow1.pal
@@ -0,0 +1,9 @@
+  0;  0;  0
+ 31; 31;  0
+ 63; 63;  0
+ 95; 95;  0
+127;127;  0
+159;159;  0
+191;191;  0
+223;223;  0
+255;255;  0
diff --git a/Palettes/Yellow2.pal b/Palettes/Yellow2.pal
new file mode 100644
index 0000000..e55bd0d
--- /dev/null
+++ b/Palettes/Yellow2.pal
@@ -0,0 +1,9 @@
+  0;  0;  0
+ 39; 39;  0
+ 75; 75;  0
+111;111;  0
+147;147;  0
+183;183;  0
+219;219;  0
+255;255;  0
+255;255;255
diff --git a/Palettes/ZL1FZ.pal b/Palettes/ZL1FZ.pal
new file mode 100644
index 0000000..07f1110
--- /dev/null
+++ b/Palettes/ZL1FZ.pal
@@ -0,0 +1,9 @@
+  0;  0;  0
+  0;  0;  0
+  0;  0;  0
+  0;  0;  0
+  0;255;  0
+255;255;  0
+255;255;  0
+255;255;  0
+255;  0;  0
diff --git a/PollingTransceiver.cpp b/PollingTransceiver.cpp
new file mode 100644
index 0000000..0f16bb8
--- /dev/null
+++ b/PollingTransceiver.cpp
@@ -0,0 +1,181 @@
+#include "PollingTransceiver.hpp"
+
+#include <exception>
+
+#include <QObject>
+#include <QString>
+#include <QTimer>
+
+namespace
+{
+  unsigned const polls_to_stabilize {3};
+}
+
+PollingTransceiver::PollingTransceiver (int poll_interval)
+  : interval_ {poll_interval * 1000}
+  , poll_timer_ {nullptr}
+  , retries_ {0}
+{
+}
+
+void PollingTransceiver::start_timer ()
+{
+  if (interval_)
+    {
+      if (!poll_timer_)
+        {
+          poll_timer_ = new QTimer {this}; // pass ownership to QObject which handles destruction for us
+
+          connect (poll_timer_, &QTimer::timeout, this, &PollingTransceiver::handle_timeout);
+        }
+      poll_timer_->start (interval_);
+    }
+}
+
+void PollingTransceiver::stop_timer ()
+{
+  if (poll_timer_)
+    {
+      poll_timer_->stop ();
+    }
+}
+
+void PollingTransceiver::do_post_start ()
+{
+  start_timer ();
+  if (!next_state_.online ())
+    {
+      // remember that we are expecting to go online
+      next_state_.online (true);
+      retries_ = polls_to_stabilize;
+    }
+}
+
+void PollingTransceiver::do_post_stop ()
+{
+  // not much point waiting for rig to go offline since we are ceasing
+  // polls
+  stop_timer ();
+}
+
+void PollingTransceiver::do_post_frequency (Frequency f, MODE m)
+{
+  // take care not to set the expected next mode to unknown since some
+  // callers use mode == unknown to signify that they do not know the
+  // mode and don't care
+  if (next_state_.frequency () != f || (m != UNK && next_state_.mode () != m))
+    {
+      // update expected state with new frequency and set poll count
+      next_state_.frequency (f);
+      if (m != UNK)
+        {
+          next_state_.mode (m);
+        }
+      retries_ = polls_to_stabilize;
+    }
+}
+
+void PollingTransceiver::do_post_tx_frequency (Frequency f, bool /* rationalize */)
+{
+  if (next_state_.tx_frequency () != f)
+    {
+      // update expected state with new TX frequency and set poll
+      // count
+      next_state_.tx_frequency (f);
+      next_state_.split (f); // setting non-zero TX frequency means split
+      retries_ = polls_to_stabilize;
+    }
+}
+
+void PollingTransceiver::do_post_mode (MODE m, bool /*rationalize_mode*/)
+{
+  // we don't ever expect mode to goto to unknown
+  if (m != UNK && next_state_.mode () != m)
+    {
+      // update expected state with new mode and set poll count
+      next_state_.mode (m);
+      retries_ = polls_to_stabilize;
+    }
+}
+
+void PollingTransceiver::do_post_ptt (bool p)
+{
+  if (next_state_.ptt () != p)
+    {
+      // update expected state with new PTT and set poll count
+      next_state_.ptt (p);
+      retries_ = 0;             // fast feedback on PTT
+    }
+}
+
+bool PollingTransceiver::do_pre_update ()
+{
+  // if we are holding off a change then withhold the signal
+  if (retries_ && state () != next_state_)
+    {
+      return false;
+    }
+  return true;
+}
+
+void PollingTransceiver::do_sync (bool force_signal)
+{
+  poll ();                      // tell sub-classes to update our
+                                // state
+
+  // Signal new state if it is directly requested or, what we expected
+  // or, hasn't become what we expected after polls_to_stabilize
+  // polls. Unsolicited changes will be signalled immediately unless
+  // they intervene in a expected sequence where they will be delayed.
+  if (retries_)
+    {
+      --retries_;
+      if (force_signal || state () == next_state_ || !retries_)
+        {
+          // our client wants a signal regardless
+          // or the expected state has arrived
+          // or there are no more retries
+          force_signal = true;
+        }
+    }
+  else if (force_signal || state () != last_signalled_state_)
+    {
+      // here is the normal passive polling path
+      // either our client has requested a state update regardless of change
+      // or sate has changed asynchronously
+      force_signal = true;
+    }
+
+  if (force_signal)
+    {
+      // reset everything, record and signal the current state
+      retries_ = 0;
+      next_state_ = state ();
+      last_signalled_state_ = state ();
+      update_complete ();
+    }
+}
+
+void PollingTransceiver::handle_timeout ()
+{
+  QString message;
+
+  // we must catch all exceptions here since we are called by Qt and
+  // inform our parent of the failure via the offline() message
+  try
+    {
+      do_sync (false);
+    }
+  catch (std::exception const& e)
+    {
+      message = e.what ();
+    }
+  catch (...)
+    {
+      message = tr ("Unexpected rig error");
+    }
+  if (!message.isEmpty ())
+    {
+      offline (message);
+    }
+}
diff --git a/PollingTransceiver.hpp b/PollingTransceiver.hpp
new file mode 100644
index 0000000..2ae523d
--- /dev/null
+++ b/PollingTransceiver.hpp
@@ -0,0 +1,75 @@
+#ifndef POLLING_TRANSCEIVER_HPP__
+#define POLLING_TRANSCEIVER_HPP__
+
+#include <QObject>
+
+#include "TransceiverBase.hpp"
+
+class QTimer;
+
+//
+// Polling Transceiver
+//
+//  Helper base  class that  encapsulates the emulation  of continuous
+//  update and caching of a transceiver state.
+//
+// Collaborations
+//
+//  Implements the TransceiverBase post  action interface and provides
+//  the abstract  poll() operation  for sub-classes to  implement. The
+//  poll operation is invoked every poll_interval seconds.
+//
+// Responsibilities
+//
+//  Because some rig interfaces don't immediately update after a state
+//  change request; this  class allows a rig a few  polls to stabilise
+//  to the  requested state before  signalling the change.  This means
+//  that  clients don't  see  intermediate states  that are  sometimes
+//  inaccurate,  e.g. changing  the split  TX frequency  on Icom  rigs
+//  requires a  VFO switch  and polls while  switched will  return the
+//  wrong current frequency.
+//
+class PollingTransceiver
+  : public TransceiverBase
+{
+  Q_OBJECT;                     // for translation context
+
+protected:
+  explicit PollingTransceiver (int poll_interval); // in seconds
+
+protected:
+  void do_sync (bool force_signal) override final;
+
+  // Sub-classes implement this and fetch what they can from the rig
+  // in a non-intrusive manner.
+  virtual void poll () = 0;
+
+  void do_post_start () override final;
+  void do_post_stop () override final;
+  void do_post_frequency (Frequency, MODE = UNK) override final;
+  void do_post_tx_frequency (Frequency, bool rationalize = true) override final;
+  void do_post_mode (MODE, bool rationalize = true) override final;
+  void do_post_ptt (bool = true) override final;
+  bool do_pre_update () override final;
+
+private:
+  void start_timer ();
+  void stop_timer ();
+
+  Q_SLOT void handle_timeout ();
+
+  int interval_;    // polling interval in milliseconds
+  QTimer * poll_timer_;
+
+  // keep a record of the last state signalled so we can elide
+  // duplicate updates
+  Transceiver::TransceiverState last_signalled_state_;
+
+  // keep a record of expected state so we can compare with actual
+  // updates to determine when state changes have bubbled through
+  Transceiver::TransceiverState next_state_;
+
+  unsigned retries_;            // number of incorrect polls left
+};
+
+#endif
diff --git a/QtSupport.iss b/QtSupport.iss
deleted file mode 100644
index a7144c2..0000000
--- a/QtSupport.iss
+++ /dev/null
@@ -1,10 +0,0 @@
-[Setup]
-AppName="QtSupport for MAP65"
-AppVerName=QtSupport
-DefaultDirName=C:\MAP65
-
-[Files]
-Source: "c:\Users\joe\map65\QtSupport\*.dll";           DestDir: "{app}";  Flags: onlyifdoesntexist
-
-
-
diff --git a/README b/README
new file mode 100644
index 0000000..0e0e17e
--- /dev/null
+++ b/README
@@ -0,0 +1,46 @@
+
+ __       __   ______      _____  ________      __    __ 
+|  \  _  |  \ /      \    |     \|        \    |  \  |  \
+| $$ / \ | $$|  $$$$$$\    \$$$$$ \$$$$$$$$    | $$  | $$
+| $$/  $\| $$| $$___\$$      | $$   | $$ ______ \$$\/  $$
+| $$  $$$\ $$ \$$    \  __   | $$   | $$|      \ >$$  $$ 
+| $$ $$\$$\$$ _\$$$$$$\|  \  | $$   | $$ \$$$$$$/  $$$$\ 
+| $$$$  \$$$$|  \__| $$| $$__| $$   | $$       |  $$ \$$\
+| $$$    \$$$ \$$    $$ \$$    $$   | $$       | $$  | $$
+ \$$      \$$  \$$$$$$   \$$$$$$     \$$        \$$   \$$
+                                                         
+                                                         
+                                                         
+Copyright (C) 2001 - 2014 by Joe Taylor, K1JT.
+
+WSJT-X implements JT9, a new mode  designed especially for the LF, MF,
+and  HF bands,  as well  as  the popular  mode JT65.  Both modes  were
+designed for making reliable, confirmed QSOs under extreme weak-signal
+conditions.  They  use nearly  identical message structure  and source
+encoding.  JT65 was  designed for  EME (“moonbounce”)  on the  VHF/UHF
+bands  and   has  also  proved   very  effective  for   worldwide  QRP
+communication at  HF; in contrast, JT9  is optimized for HF  and lower
+frequencies. JT9 is  about 2 dB more sensitive than  JT65A while using
+less  than 10%  of the  bandwidth. World-wide  QSOs are  possible with
+power levels of a few watts and  compromise antennas. A 2 kHz slice of
+spectrum is  essentially full when  occupied by ten JT65  signals.  As
+many as 100 JT9 signals can fit into the same space, without overlap.
+
+WSJT-X offers a “bi-lingual” operating  mode in which you can transmit
+and   receive  JT65   and   JT9  signals,   switching  between   modes
+automatically as  needed.  Displayed  bandwidth can be  as large  as 5
+kHz. If  your receiver  has as  upper-sideband filter  at least  4 kHz
+wide, you can have all the typical  JT65 and JT9 activity on screen at
+once, available for  making QSOs with a click of  the mouse. Even with
+standard SSB-width IF filters, switching between JT65 and JT9 modes is
+quick and convenient. Be sure to read the online WSJT-X User's Guide.
+
+Project web site:
+
+http://www.physics.princeton.edu/pulsar/K1JT/wsjtx.html
+
+Project mailing  list (shared  with other  applications from  the same
+team):
+
+https://groups.yahoo.com/neo/groups/wsjtgroup
+
diff --git a/Radio.cpp b/Radio.cpp
new file mode 100644
index 0000000..961fc1d
--- /dev/null
+++ b/Radio.cpp
@@ -0,0 +1,107 @@
+#include "Radio.hpp"
+
+#include <cmath>
+
+#include <QMetaType>
+#include <QString>
+#include <QChar>
+#include <QDebug>
+#include <QRegExpValidator>
+#include <QDataStream>
+#include <QRegularExpression>
+
+namespace Radio
+{
+  namespace
+  {
+    struct init
+    {
+      init ()
+      {
+        qRegisterMetaType<Frequency> ("Frequency");
+
+        qRegisterMetaType<Frequencies> ("Frequencies");
+        qRegisterMetaTypeStreamOperators<Frequencies> ("Frequencies");
+
+        qRegisterMetaType<FrequencyDelta> ("FrequencyDelta");
+      }
+    } static_initaializer;
+
+    double constexpr MHz_factor {1.e6};
+    int constexpr frequency_precsion {6};
+
+    // very loose validation - callsign must contain a letter next to
+    // a number
+    QRegularExpression valid_callsign_regexp {R"(\d[[:alpha:]]|[[:alpha:]]\d)"};
+  }
+
+
+  Frequency frequency (QVariant const& v, int scale)
+  {
+    return std::llround (v.toDouble () * std::pow (10., scale));
+  }
+
+  FrequencyDelta frequency_delta (QVariant const& v, int scale)
+  {
+    return std::llround (v.toDouble () * std::pow (10., scale));
+  }
+
+
+  QString frequency_MHz_string (Frequency f, QLocale const& locale)
+  {
+    return locale.toString (f / MHz_factor, 'f', frequency_precsion);
+  }
+
+  QString frequency_MHz_string (FrequencyDelta d, QLocale const& locale)
+  {
+    return locale.toString (d / MHz_factor, 'f', frequency_precsion);
+  }
+
+  QString pretty_frequency_MHz_string (Frequency f, QLocale const& locale)
+  {
+    auto f_string = locale.toString (f / MHz_factor, 'f', frequency_precsion);
+    return f_string.insert (f_string.size () - 3, QChar::Nbsp);
+  }
+
+  QString pretty_frequency_MHz_string (double f, int scale, QLocale const& locale)
+  {
+    auto f_string = locale.toString (f / std::pow (10., scale - 6), 'f', frequency_precsion);
+    return f_string.insert (f_string.size () - 3, QChar::Nbsp);
+  }
+
+  QString pretty_frequency_MHz_string (FrequencyDelta d, QLocale const& locale)
+  {
+    auto d_string = locale.toString (d / MHz_factor, 'f', frequency_precsion);
+    return d_string.insert (d_string.size () - 3, QChar::Nbsp);
+  }
+
+  bool is_callsign (QString const& callsign)
+  {
+    return callsign.contains (valid_callsign_regexp);
+  }
+
+  bool is_compound_callsign (QString const& callsign)
+  {
+    return callsign.contains ('/');
+  }
+
+  // split on first '/' and return the larger portion or the whole if
+  // there is no '/'
+  QString base_callsign (QString callsign)
+  {
+    auto slash_pos = callsign.indexOf ('/');
+    if (slash_pos >= 0)
+      {
+        auto right_size = callsign.size () - slash_pos - 1;
+        if (right_size>= slash_pos)
+          {
+            callsign = callsign.mid (slash_pos + 1);
+          }
+        else
+          {
+            callsign = callsign.left (slash_pos);
+          }
+      }
+    return callsign;
+  }
+}
diff --git a/Radio.hpp b/Radio.hpp
new file mode 100644
index 0000000..3d3211b
--- /dev/null
+++ b/Radio.hpp
@@ -0,0 +1,54 @@
+#ifndef RADIO_HPP_
+#define RADIO_HPP_
+
+#include <QObject>
+#include <QLocale>
+#include <QList>
+
+class QVariant;
+class QString;
+
+//
+// Declarations common to radio software.
+//
+
+namespace Radio
+{
+  //
+  // Frequency types
+  //
+  using Frequency = quint64;
+  using Frequencies = QList<Frequency>;
+  using FrequencyDelta = qint64;
+
+  //
+  // Frequency type conversion.
+  //
+  //	QVariant argument is convertible to double and is assumed to
+  //	be scaled by (10 ** -scale).
+  //
+  Frequency frequency (QVariant const&, int scale);
+  FrequencyDelta frequency_delta (QVariant const&, int scale);
+
+  //
+  // Frequency type formatting
+  //
+  QString frequency_MHz_string (Frequency, QLocale const& = QLocale ());
+  QString frequency_MHz_string (FrequencyDelta, QLocale const& = QLocale ());
+  QString pretty_frequency_MHz_string (Frequency, QLocale const& = QLocale ());
+  QString pretty_frequency_MHz_string (double, int scale, QLocale const& = QLocale ());
+  QString pretty_frequency_MHz_string (FrequencyDelta, QLocale const& = QLocale ());
+
+  //
+  // Callsigns
+  //
+  bool is_callsign (QString const&);
+  bool is_compound_callsign (QString const&);
+  QString base_callsign (QString);
+}
+
+Q_DECLARE_METATYPE (Radio::Frequency);
+Q_DECLARE_METATYPE (Radio::Frequencies);
+Q_DECLARE_METATYPE (Radio::FrequencyDelta);
+
+#endif
diff --git a/SettingsGroup.hpp b/SettingsGroup.hpp
new file mode 100644
index 0000000..e728e6c
--- /dev/null
+++ b/SettingsGroup.hpp
@@ -0,0 +1,34 @@
+#ifndef SETTINGS_GROUP_HPP_
+#define SETTINGS_GROUP_HPP_
+
+#include <QSettings>
+#include <QString>
+
+//
+// Class SettingsGroup
+//
+//	Simple RAII type class to apply a QSettings group witin a
+//	scope.
+//
+class SettingsGroup
+{
+public:
+  SettingsGroup (QSettings * settings, QString const& group)
+    : settings_ {settings}
+  {
+    settings_->beginGroup (group);
+  }
+
+  SettingsGroup (SettingsGroup const&) = delete;
+  SettingsGroup& operator = (SettingsGroup const&) = delete;
+
+  ~SettingsGroup ()
+  {
+    settings_->endGroup ();
+  }
+
+private:
+  QSettings * settings_;
+};
+
+#endif
diff --git a/StationList.cpp b/StationList.cpp
new file mode 100644
index 0000000..94c09d6
--- /dev/null
+++ b/StationList.cpp
@@ -0,0 +1,550 @@
+#include "StationList.hpp"
+
+#include <utility>
+#include <algorithm>
+#include <cmath>
+
+#include <QMetaType>
+#include <QAbstractTableModel>
+#include <QObject>
+#include <QString>
+#include <QVector>
+#include <QStringList>
+#include <QMimeData>
+#include <QDataStream>
+#include <QByteArray>
+#include <QDebug>
+
+#include "pimpl_impl.hpp"
+
+#include "Bands.hpp"
+
+namespace
+{
+  struct init
+  {
+    init ()
+    {
+      qRegisterMetaType<StationList::Station> ("Station");
+      qRegisterMetaTypeStreamOperators<StationList::Station> ("Station");
+      qRegisterMetaType<StationList::Stations> ("Stations");
+      qRegisterMetaTypeStreamOperators<StationList::Stations> ("Stations");
+    }
+  } static_initializer;
+}
+
+#if !defined (QT_NO_DEBUG_STREAM)
+QDebug operator << (QDebug debug, StationList::Station const& station)
+{
+  debug.nospace () << "Station("
+                   << station.band_name_ << ", "
+                   << station.offset_ << ", "
+                   << station.antenna_description_ << ')';
+  return debug.space ();
+}
+#endif
+
+QDataStream& operator << (QDataStream& os, StationList::Station const& station)
+{
+  return os << station.band_name_
+            << station.offset_
+            << station.antenna_description_;
+}
+
+QDataStream& operator >> (QDataStream& is, StationList::Station& station)
+{
+  return is >> station.band_name_
+            >> station.offset_
+            >> station.antenna_description_;
+}
+
+
+class StationList::impl final
+  : public QAbstractTableModel
+{
+public:
+  impl (Bands const * bands, Stations stations, QObject * parent)
+    : QAbstractTableModel {parent}
+    , bands_ {bands}
+    , stations_ {stations}
+  {
+  }
+
+  Stations const& stations () const {return stations_;}
+  void assign (Stations);
+  QModelIndex add (Station);
+  FrequencyDelta offset (Frequency) const;
+
+protected:
+  // Implement the QAbstractTableModel interface.
+  int rowCount (QModelIndex const& parent = QModelIndex {}) const override;
+  int columnCount (QModelIndex const& parent = QModelIndex {}) const override;
+  Qt::ItemFlags flags (QModelIndex const& = QModelIndex {}) const override;
+  QVariant data (QModelIndex const&, int role) const override;
+  QVariant headerData (int section, Qt::Orientation, int = Qt::DisplayRole) const override;
+  bool setData (QModelIndex const&, QVariant const& value, int role = Qt::EditRole) override;
+  bool removeRows (int row, int count, QModelIndex const& parent = QModelIndex {}) override;
+  bool insertRows (int row, int count, QModelIndex const& parent = QModelIndex {}) override;
+  Qt::DropActions supportedDropActions () const override;
+  QStringList mimeTypes () const override;
+  QMimeData * mimeData (QModelIndexList const&) const override;
+  bool dropMimeData (QMimeData const *, Qt::DropAction, int row, int column, QModelIndex const& parent) override;
+
+private:
+  // Helper method for band validation.
+  QModelIndex first_matching_band (QString const& band_name) const
+  {
+    // find first exact match in bands
+    auto matches = bands_->match (bands_->index (0, 0)
+                                  , Qt::DisplayRole
+                                  , band_name
+                                  , 1
+                                  , Qt::MatchExactly);
+    return matches.isEmpty () ? QModelIndex {} : matches.first ();
+  }
+
+  static int constexpr num_columns {3};
+  static auto constexpr mime_type = "application/wsjt.antenna-descriptions";
+
+  Bands const * bands_;
+  Stations stations_;
+};
+
+StationList::StationList (Bands const * bands, QObject * parent)
+  : StationList {bands, {}, parent}
+{
+}
+
+StationList::StationList (Bands const * bands, Stations stations, QObject * parent)
+  : QSortFilterProxyModel {parent}
+  , m_ {bands, stations, parent}
+{
+  setSourceModel (&*m_);
+  setSortRole (SortRole);
+}
+
+StationList::~StationList ()
+{
+}
+
+StationList& StationList::operator = (Stations stations)
+{
+  m_->assign (stations);
+  return *this;
+}
+
+auto StationList::stations () const -> Stations
+{
+  return m_->stations ();
+}
+
+QModelIndex StationList::add (Station s)
+{
+  return mapFromSource (m_->add (s));
+}
+
+bool StationList::remove (Station s)
+{
+  auto row = m_->stations ().indexOf (s);
+
+  if (0 > row)
+    {
+      return false;
+    }
+
+  return removeRow (row);
+}
+
+namespace
+{
+  bool row_is_higher (QModelIndex const& lhs, QModelIndex const& rhs)
+  {
+    return lhs.row () > rhs.row ();
+  }
+}
+
+bool StationList::removeDisjointRows (QModelIndexList rows)
+{
+  bool result {true};
+
+  // We must work with source model indexes because we don't want row
+  // removes to invalidate model indexes we haven't yet processed. We
+  // achieve that by processing them in decending row order.
+  for (int r = 0; r < rows.size (); ++r)
+    {
+      rows[r] = mapToSource (rows[r]);
+    }
+
+  // reverse sort by row
+  qSort (rows.begin (), rows.end (), row_is_higher);
+  Q_FOREACH (auto index, rows)
+    {
+      if (result && !m_->removeRow (index.row ()))
+        {
+          result = false;
+        }
+    }
+
+  return result;
+}
+
+auto StationList::offset (Frequency f) const -> FrequencyDelta
+{
+  return m_->offset (f);
+}
+
+
+void StationList::impl::assign (Stations stations)
+{
+  beginResetModel ();
+  std::swap (stations_, stations);
+  endResetModel ();
+}
+
+QModelIndex StationList::impl::add (Station s)
+{
+  // Any band that isn't in the list may be added
+  if (!stations_.contains (s))
+    {
+      auto row = stations_.size ();
+
+      beginInsertRows (QModelIndex {}, row, row);
+      stations_.append (s);
+      endInsertRows ();
+
+      return index (row, 0);
+    }
+
+  return QModelIndex {};
+}
+
+auto StationList::impl::offset (Frequency f) const -> FrequencyDelta
+{
+  // Lookup band for frequency
+  auto band_index = bands_->find (f);
+  if (band_index.isValid ())
+    {
+      auto band_name = band_index.data ().toString ();
+
+      // Lookup station for band
+      for (int i = 0; i < stations ().size (); ++i)
+        {
+          if (stations_[i].band_name_ == band_name)
+            {
+              return stations_[i].offset_;
+            }
+        }
+    }
+
+  return 0;			// no offset
+}
+
+int StationList::impl::rowCount (QModelIndex const& parent) const
+{
+  return parent.isValid () ? 0 : stations_.size ();
+}
+
+int StationList::impl::columnCount (QModelIndex const& parent) const
+{
+  return parent.isValid () ? 0 : num_columns;
+}
+
+Qt::ItemFlags StationList::impl::flags (QModelIndex const& index) const
+{
+  auto result = QAbstractTableModel::flags (index);
+
+  auto row = index.row ();
+  auto column = index.column ();
+
+  if (index.isValid ()
+      && row < stations_.size ()
+      && column < num_columns)
+    {
+      if (2 == column)
+        {
+          result |= Qt::ItemIsEditable | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled;
+        }
+      else
+        {
+          result |= Qt::ItemIsEditable | Qt::ItemIsDropEnabled;
+        }
+    }
+  else
+    {
+      result |= Qt::ItemIsDropEnabled;
+    }
+
+  return result;
+}
+
+QVariant StationList::impl::data (QModelIndex const& index, int role) const
+{
+  QVariant item;
+
+  auto row = index.row ();
+  auto column = index.column ();
+
+  if (index.isValid ()
+      && row < stations_.size ())
+    {
+      switch (column)
+        {
+        case 0:			// band name
+          switch (role)
+            {
+            case SortRole:
+              {
+                // Lookup band.
+                auto band_index = first_matching_band (stations_.at (row).band_name_);
+                // Use the sort role value of the band.
+                item = band_index.data (Bands::SortRole);
+              }
+              break;
+
+            case Qt::DisplayRole:
+            case Qt::EditRole:
+            case Qt::AccessibleTextRole:
+              item = stations_.at (row).band_name_;
+              break;
+
+            case Qt::ToolTipRole:
+            case Qt::AccessibleDescriptionRole:
+              item = tr ("Band name");
+              break;
+
+            case Qt::TextAlignmentRole:
+              item = Qt::AlignHCenter + Qt::AlignVCenter;
+              break;
+            }
+          break;
+
+        case 1:			// frequency offset
+          {
+            auto frequency_offset = stations_.at (row).offset_;
+            switch (role)
+              {
+              case Qt::AccessibleTextRole:
+                item = frequency_offset;
+                break;
+
+              case SortRole:
+              case Qt::DisplayRole:
+              case Qt::EditRole:
+                item = frequency_offset;
+                break;
+
+              case Qt::ToolTipRole:
+              case Qt::AccessibleDescriptionRole:
+                item = tr ("Frequency offset");
+                break;
+
+              case Qt::TextAlignmentRole:
+                item = Qt::AlignRight + Qt::AlignVCenter;
+                break;
+              }
+          }
+          break;
+
+        case 2:			// antenna description
+          switch (role)
+            {
+            case SortRole:
+            case Qt::EditRole:
+            case Qt::DisplayRole:
+            case Qt::AccessibleTextRole:
+              item = stations_.at (row).antenna_description_;
+              break;
+
+            case Qt::ToolTipRole:
+            case Qt::AccessibleDescriptionRole:
+              item = tr ("Antenna description");
+              break;
+
+            case Qt::TextAlignmentRole:
+              item = Qt::AlignLeft + Qt::AlignVCenter;
+              break;
+            }
+          break;
+        }
+    }
+
+  return item;
+}
+
+QVariant StationList::impl::headerData (int section, Qt::Orientation orientation, int role) const
+{
+  QVariant header;
+
+  if (Qt::DisplayRole == role && Qt::Horizontal == orientation)
+    {
+      switch (section)
+        {
+        case 0: header = tr ("Band"); break;
+        case 1: header = tr ("Offset"); break;
+        case 2: header = tr ("Antenna Description"); break;
+        }
+    }
+  else
+    {
+      header = QAbstractTableModel::headerData (section, orientation, role);
+    }
+
+  return header;
+}
+
+bool StationList::impl::setData (QModelIndex const& model_index, QVariant const& value, int role)
+{
+  bool changed {false};
+
+  auto row = model_index.row ();
+  auto size = stations_.size ();
+  if (model_index.isValid ()
+      && Qt::EditRole == role
+      && row < size)
+    {
+      QVector<int> roles;
+      roles << role;
+
+      switch (model_index.column ())
+        {
+        case 0:
+          {
+            // Check if band name is valid.
+            auto band_index = first_matching_band (value.toString ());
+            if (band_index.isValid ())
+              {
+                stations_[row].band_name_ = band_index.data ().toString ();
+                Q_EMIT dataChanged (model_index, model_index, roles);
+                changed = true;
+              }
+          }
+          break;
+
+        case 1:
+          {
+            stations_[row].offset_ = value.value<FrequencyDelta> ();
+            Q_EMIT dataChanged (model_index, model_index, roles);
+            changed = true;
+          }
+          break;
+
+        case 2:
+          stations_[row].antenna_description_ = value.toString ();
+          Q_EMIT dataChanged (model_index, model_index, roles);
+          changed = true;
+          break;
+        }
+    }
+
+  return changed;
+}
+
+bool StationList::impl::removeRows (int row, int count, QModelIndex const& parent)
+{
+  if (0 < count && (row + count) <= rowCount (parent))
+    {
+      beginRemoveRows (parent, row, row + count - 1);
+      for (auto r = 0; r < count; ++r)
+        {
+          stations_.removeAt (row);
+        }
+      endRemoveRows ();
+      return true;
+    }
+
+  return false;
+}
+
+bool StationList::impl::insertRows (int row, int count, QModelIndex const& parent)
+{
+  if (0 < count)
+    {
+      beginInsertRows (parent, row, row + count - 1);
+      for (auto r = 0; r < count; ++r)
+        {
+          stations_.insert (row, Station ());
+        }
+      endInsertRows ();
+      return true;
+    }
+
+  return false;
+}
+
+Qt::DropActions StationList::impl::supportedDropActions () const
+{
+  return Qt::CopyAction | Qt::MoveAction;
+}
+
+QStringList StationList::impl::mimeTypes () const
+{
+  QStringList types;
+  types << mime_type;
+  types << "application/wsjt.Frequencies";
+  return types;
+}
+
+QMimeData * StationList::impl::mimeData (QModelIndexList const& items) const
+{
+  QMimeData * mime_data = new QMimeData {};
+  QByteArray encoded_data;
+  QDataStream stream {&encoded_data, QIODevice::WriteOnly};
+
+  Q_FOREACH (auto const& item, items)
+    {
+      if (item.isValid ())
+        {
+          stream << QString {data (item, Qt::DisplayRole).toString ()};
+        }
+    }
+
+  mime_data->setData (mime_type, encoded_data);
+  return mime_data;
+}
+
+bool StationList::impl::dropMimeData (QMimeData const * data, Qt::DropAction action, int /* row */, int /* column */, QModelIndex const& parent)
+{
+  if (Qt::IgnoreAction == action)
+    {
+      return true;
+    }
+
+  if (parent.isValid ()
+      && 2 == parent.column ()
+      && data->hasFormat (mime_type))
+    {
+      QByteArray encoded_data {data->data (mime_type)};
+      QDataStream stream {&encoded_data, QIODevice::ReadOnly};
+      auto dest_index = parent;
+      while (!stream.atEnd ())
+        {
+          QString text;
+          stream >> text;
+          setData (dest_index, text);
+          dest_index = index (dest_index.row () + 1, dest_index.column (), QModelIndex {});
+        }
+      return true;
+    }
+  else if (data->hasFormat ("application/wsjt.Frequencies"))
+    {
+      QByteArray encoded_data {data->data ("application/wsjt.Frequencies")};
+      QDataStream stream {&encoded_data, QIODevice::ReadOnly};
+      while (!stream.atEnd ())
+        {
+          QString frequency_string;
+          stream >> frequency_string;
+          auto frequency = Radio::frequency (frequency_string, 0);
+          auto band_index = bands_->find (frequency);
+          if (stations_.cend () == std::find_if (stations_.cbegin ()
+                                                 , stations_.cend ()
+                                                 , [&band_index] (Station const& s) {return s.band_name_ == band_index.data ().toString ();}))
+            {
+              add (Station {band_index.data ().toString (), 0, QString {}});
+            }
+        }
+
+      return true;
+    }
+
+  return false;
+}
diff --git a/StationList.hpp b/StationList.hpp
new file mode 100644
index 0000000..75f6412
--- /dev/null
+++ b/StationList.hpp
@@ -0,0 +1,102 @@
+#ifndef STATION_LIST_HPP__
+#define STATION_LIST_HPP__
+
+#include <QSortFilterProxyModel>
+#include <QString>
+#include <QList>
+
+#include "pimpl_h.hpp"
+
+#include "Radio.hpp"
+
+class Bands;
+
+//
+// Class StationList
+//
+//  Encapsulates information  about a  collection of  unique operating
+//  stations per  band. The implementation  is a table model  with the
+//  first column  being the unique  (within the table rows)  band name
+//  and, the  second the frequency  offset for transverter  usage and,
+//  the third the antenna description. All are editable.
+//
+// Responsibilities
+//
+//  Stores internally an unordered table of bands.
+//
+//  If  an ordered  representaion is  required then  wrapping with  an
+//  appropriate        proxy         model        is        sufficient
+//  e.g. QSortFilterProxyModel. A custom SortRole role is provided for
+//  the band  name column which  returns a numeric value  (Bands lower
+//  frequency limit) which gives a strict frequency ordering by band.
+//
+// Collaborations
+//
+//  Implements the  QAbstractTableModel interface for a  grid of bands
+//  with offset frequencies and antenna descriptions.
+//
+//  Uses the QAbstractItemModel interface of the bands model to lookup
+//  band information.
+//
+class StationList final
+  : public QSortFilterProxyModel
+{
+public:
+  using Frequency = Radio::Frequency;
+  using FrequencyDelta = Radio::FrequencyDelta;
+
+  //
+  // Struct Station
+  //
+  //  Aggregation of fields that describe a radio station on a band.
+  //
+  struct Station
+  {
+    QString band_name_;
+    FrequencyDelta offset_;
+    QString antenna_description_;
+  };
+
+  using Stations = QList<Station>;
+
+  explicit StationList (Bands const * bands, QObject * parent = nullptr);
+  explicit StationList (Bands const * bands, Stations, QObject * parent = nullptr);
+  ~StationList ();
+
+  // Load and store contents.
+  StationList& operator = (Stations);
+  Stations stations () const;
+
+  //
+  // Model API
+  //
+  QModelIndex add (Station);                 // Add a new Station
+  bool remove (Station);                     // Remove a Station
+  bool removeDisjointRows (QModelIndexList); // Remove one or more stations
+  FrequencyDelta offset (Frequency) const;   // Return the offset to be used for a Frequency
+
+  // Custom sort role.
+  static int constexpr SortRole = Qt::UserRole;
+
+private:
+  class impl;
+  pimpl<impl> m_;
+};
+
+#if !defined (QT_NO_DEBUG_STREAM)
+QDebug operator << (QDebug debug, StationList::Station const&);
+#endif
+
+// Station equivalence
+inline
+bool operator == (StationList::Station const& lhs, StationList::Station const& rhs)
+{
+  return lhs.band_name_ == rhs.band_name_
+    && lhs.offset_ == rhs.offset_
+    && lhs.antenna_description_ == rhs.antenna_description_;
+}
+
+Q_DECLARE_METATYPE (StationList::Station);
+Q_DECLARE_METATYPE (StationList::Stations);
+
+#endif
diff --git a/THANKS b/THANKS
new file mode 100644
index 0000000..1da9c20
--- /dev/null
+++ b/THANKS
@@ -0,0 +1,58 @@
+
+ __       __   ______      _____  ________      __    __ 
+|  \  _  |  \ /      \    |     \|        \    |  \  |  \
+| $$ / \ | $$|  $$$$$$\    \$$$$$ \$$$$$$$$    | $$  | $$
+| $$/  $\| $$| $$___\$$      | $$   | $$ ______ \$$\/  $$
+| $$  $$$\ $$ \$$    \  __   | $$   | $$|      \ >$$  $$ 
+| $$ $$\$$\$$ _\$$$$$$\|  \  | $$   | $$ \$$$$$$/  $$$$\ 
+| $$$$  \$$$$|  \__| $$| $$__| $$   | $$       |  $$ \$$\
+| $$$    \$$$ \$$    $$ \$$    $$   | $$       | $$  | $$
+ \$$      \$$  \$$$$$$   \$$$$$$     \$$        \$$   \$$
+                                                         
+                                                         
+                                                         
+Thanks to:
+
+    The FFTW library (http://www.fftw.org) without which the efficient
+generation of  discrete fast Fourier transformations  essential to the
+decoding DSP algorithms of WSJT-X would  be a considerable part of the
+project.
+
+    The Qt project (http://qt-project.org) that allows us to deliver a
+rich  industrial strength  cross platform  GUI application  written in
+C++.
+
+    Nate  Bargmann, N0NB,  and  the Hamlib  developer  team for  their
+excellent library  and for  prompt review and  acceptance of  the many
+pull requests for upstream patches to Hamlib.
+
+    Dave  Bernstein,  AA6YQ, for  being  so  receptive to  suggestions
+allowing WSJT-X to  cooperate with his excellent Amateur  Radio DX and
+award chasing suite (http://www.dxlabsuite.com).
+
+    Laurie Cowcher,  VK3AMA, for  developing the  partner applications
+JTAlertX and  JTMacrosX (http://www.hamapps.com) that make  DX chasing
+with WSJT-X such an efficient and pleasurable experience.
+
+    The  CMake build  and packaging  tools (http://www.cmake.org)  for
+their comprehensive  scripting tools that make  automation of building
+and packaging on all supported platforms possible.
+
+    The  NSIS  MS  Windows  installer scripting  and  generator  tools
+(http://nsis.sourceforge.net) that, through  the CPack NSIS generator,
+allows us to build a comprehensive Windows installer package.
+
+    The GNU Compiler Collection (http://gcc.gnu.org) that allows us to
+compile and link  C++, Fortran and C code to  the latest Standards and
+with high quality optimization.
+
+     The clang C++ & C compiler  front ends and LLVM compiler back end
+tools  (http://clang.llvm.org)  that  provide  us  with  another,  gcc
+compatible, high quality C++ and C compiler and Standard Library suite
+which, particularly on Apple Mac, allows  our code to be ported to the
+maximum number of platforms.
+
+    The  MinGW  project  (http://www.mingw.org)  that  ports  the  gcc
+compilers and related GNU tools to the MS Windows environment allowing
+a high quality  C++, Fortran and C application to  be portable between
+native MS Windows and other platforms such as Linux and Apple Mac.
\ No newline at end of file
diff --git a/TraceFile.cpp b/TraceFile.cpp
new file mode 100644
index 0000000..022a020
--- /dev/null
+++ b/TraceFile.cpp
@@ -0,0 +1,118 @@
+#include "TraceFile.hpp"
+
+#include <stdexcept>
+
+#include <QDebug>
+#include <QString>
+#include <QFile>
+#include <QTextStream>
+#include <QMessageLogContext>
+#include <QDateTime>
+#include <QMutex>
+#include <QMutexLocker>
+
+#include "pimpl_impl.hpp"
+
+namespace
+{
+  QMutex lock;
+}
+
+class TraceFile::impl
+{
+public:
+  impl (QString const& trace_file_path);
+  ~impl ();
+
+  // no copying
+  impl (impl const&) = delete;
+  impl& operator = (impl const&) = delete;
+
+private:
+  // write Qt messages to the diagnostic log file
+  static void message_handler (QtMsgType type, QMessageLogContext const& context, QString const& msg);
+
+  QFile file_;
+  QTextStream stream_;
+  QTextStream * original_stream_;
+  QtMessageHandler original_handler_;
+  static QTextStream * current_stream_;
+};
+
+QTextStream * TraceFile::impl::current_stream_;
+
+
+// delegate to implementation class
+TraceFile::TraceFile (QString const& trace_file_path)
+  : m_ {trace_file_path}
+{
+}
+
+TraceFile::~TraceFile ()
+{
+}
+
+
+TraceFile::impl::impl (QString const& trace_file_path)
+  : file_ {trace_file_path}
+  , original_stream_ {current_stream_}
+  , original_handler_ {nullptr}
+{
+  // if the log file is writeable; initialise diagnostic logging to it
+  // for append and hook up the Qt global message handler
+  if (file_.open (QFile::WriteOnly | QFile::Append | QFile::Text))
+    {
+      stream_.setDevice (&file_);
+      current_stream_ = &stream_;
+      original_handler_ = qInstallMessageHandler (message_handler);
+    }
+}
+
+TraceFile::impl::~impl ()
+{
+  // unhook our message handler before the stream and file are destroyed
+  if (original_handler_)
+    {
+      qInstallMessageHandler (original_handler_);
+    }
+  current_stream_ = original_stream_; // revert to prior stream
+}
+
+// write Qt messages to the diagnostic log file
+void TraceFile::impl::message_handler (QtMsgType type, QMessageLogContext const& context, QString const& msg)
+{
+  char const * severity;
+  switch (type)
+    {
+    case QtDebugMsg:
+      severity = "Debug";
+      break;
+
+    case QtWarningMsg:
+      severity = "Warning";
+      break;
+
+    case QtFatalMsg:
+      severity = "Fatal";
+      break;
+
+    default:
+      severity = "Critical";
+      break;
+    }
+
+  {
+    // guard against multiple threads with overlapping messages
+    QMutexLocker guard (&lock);
+    Q_ASSERT_X (current_stream_, "TraceFile:message_handler", "no stream to write to");
+    *current_stream_
+      << QDateTime::currentDateTimeUtc ().toString ()
+      << '(' << context.file << ':' << context.line /* << ", " << context.function */ << ')'
+      << severity << ": " << msg.trimmed () << endl;
+  }
+
+  if (QtFatalMsg == type)
+    {
+      throw std::runtime_error {"Fatal Qt Error"};
+    }
+}
diff --git a/TraceFile.hpp b/TraceFile.hpp
new file mode 100644
index 0000000..6a27b84
--- /dev/null
+++ b/TraceFile.hpp
@@ -0,0 +1,23 @@
+#ifndef TRACE_FILE_HPP_
+#define TRACE_FILE_HPP_
+
+#include "pimpl_h.hpp"
+
+class QString;
+
+class TraceFile final
+{
+public:
+  explicit TraceFile (QString const& TraceFile_file_path);
+  ~TraceFile ();
+
+  // copying not allowed
+  TraceFile (TraceFile const&) = delete;
+  TraceFile& operator = (TraceFile const&) = delete;
+
+private:
+  class impl;
+  pimpl<impl> m_;
+};
+
+#endif
diff --git a/Transceiver.cpp b/Transceiver.cpp
new file mode 100644
index 0000000..2665a27
--- /dev/null
+++ b/Transceiver.cpp
@@ -0,0 +1,51 @@
+#include "Transceiver.hpp"
+
+#include "moc_Transceiver.cpp"
+
+namespace
+{
+  struct init
+  {
+    init ()
+    {
+      qRegisterMetaType<Transceiver::TransceiverState> ("Transceiver::TransceiverState");
+      qRegisterMetaType<Transceiver::MODE> ("Transceiver::MODE");
+    }
+  } static_initialization;
+}
+
+#if !defined (QT_NO_DEBUG_STREAM)
+
+ENUM_QDEBUG_OPS_IMPL (Transceiver, MODE);
+
+QDebug operator << (QDebug d, Transceiver::TransceiverState const& s)
+{
+  d.nospace ()
+    << "Transceiver::TransceiverState(online: " << (s.online_ ? "yes" : "no")
+    << " Frequency {" << s.frequency_[0] << "Hz, " << s.frequency_[1] << "Hz} " << s.mode_
+    << "; SPLIT: " << (Transceiver::TransceiverState::on == s.split_ ? "on" : Transceiver::TransceiverState::off == s.split_ ? "off" : "unknown")
+    << "; PTT: " << (s.ptt_ ? "on" : "off")
+    << ')';
+  return d.space (); 
+}
+
+#endif
+
+ENUM_QDATASTREAM_OPS_IMPL (Transceiver, MODE);
+
+ENUM_CONVERSION_OPS_IMPL (Transceiver, MODE);
+
+bool operator != (Transceiver::TransceiverState const& lhs, Transceiver::TransceiverState const& rhs)
+{
+  return lhs.online_ != rhs.online_
+    || lhs.frequency_[0] != rhs.frequency_[0]
+    || lhs.frequency_[1] != rhs.frequency_[1]
+    || lhs.mode_ != rhs.mode_
+    || lhs.split_ != rhs.split_
+    || lhs.ptt_ != rhs.ptt_;
+}
+
+bool operator == (Transceiver::TransceiverState const& lhs, Transceiver::TransceiverState const& rhs)
+{
+  return !(lhs != rhs);
+}
diff --git a/Transceiver.hpp b/Transceiver.hpp
new file mode 100644
index 0000000..c0e91ae
--- /dev/null
+++ b/Transceiver.hpp
@@ -0,0 +1,169 @@
+#ifndef TRANSCEIVER_HPP__
+#define TRANSCEIVER_HPP__
+
+#include <QObject>
+
+#include "qt_helpers.hpp"
+#include "Radio.hpp"
+
+class QString;
+
+//
+// Abstract Transceiver Interface
+//
+//  This is  the minimal  generic interface  to a  rig as  required by
+//  wsjtx.
+//
+// Responsibilities
+//
+//  Provides  Qt slots  to set  the frequency,  mode and  PTT of  some
+//  transceiver. They are Qt slots so  that they may be invoked across
+//  a thread boundary.
+//
+//  Provides a synchronisation Qt slot  which should be implemented in
+//  sub-classes in such a way that  normal operation of the rig is not
+//  disturbed.  This  is  intended  to   be  use  to  poll  rig  state
+//  periodically and changing  VFO to read the other  VFO frequency or
+//  mode for  example should  not be  done since  the operator  may be
+//  tuning the VFO at the time and would be surprised by an unprompted
+//  VFO change.
+//
+//  Provides a control interface using Qt  slots to start and stop the
+//  rig control and PTT connections.
+//
+//  These  are Qt  slots rather  than the  constructor and  destructor
+//  because   it   is   expected   that   the   concrete   Transceiver
+//  implementations will run in a  separate thread from where they are
+//  constructed.
+//
+//  Qt signals are defined to notify clients of asynchronous rig state
+//  changes and failures.  These can and are expected  to cross thread
+//  boundaries.
+//
+//  A  signal   finished()  is   defined  that   concrete  Transceiver
+//  implementations must emit when they are ripe for destruction. This
+//  is  intended to  be  used  by clients  that  move the  Transceiver
+//  instance to  a thread  and need  to use  QObject::deleteLater() to
+//  safely dispose of the Transceiver instance. Implementations should
+//  expect Qt  slot calls  after emitting  finished, it  is up  to the
+//  implementation whether these slot invocations are ignored.
+//
+class Transceiver
+  : public QObject
+{
+  Q_OBJECT;
+  Q_ENUMS (MODE);
+
+public:
+  using Frequency = Radio::Frequency;
+
+protected:
+  Transceiver ()
+  {
+  }
+
+public:
+  virtual ~Transceiver ()
+  {
+  }
+
+  enum MODE {UNK, CW, CW_R, USB, LSB, FSK, FSK_R, DIG_U, DIG_L, AM, FM, DIG_FM};
+
+  //
+  // Aggregation of all of the rig and PTT state accessible via this
+  // interface.
+  class TransceiverState
+  {
+  public:
+    TransceiverState ()
+      : online_ {false}
+      , frequency_ {0, 0}
+      , mode_ {UNK}
+      , split_ {unknown}
+      , ptt_ {false}
+    {
+    }
+
+    bool online () const {return online_;}
+    Frequency frequency () const {return frequency_[0];}
+    Frequency tx_frequency () const {return frequency_[1];}
+    bool split () const {return on == split_;}
+    MODE mode () const {return mode_;}
+    bool ptt () const {return ptt_;}
+
+    void online (bool state) {online_ = state;}
+    void frequency (Frequency f) {frequency_[0] = f;}
+    void tx_frequency (Frequency f) {frequency_[1] = f;}
+    void split (bool state) {split_ = state ? on : off;}
+    void mode (MODE m) {mode_ = m;}
+    void ptt (bool state) {ptt_ = state;}
+
+  private:
+    bool online_;
+    Frequency frequency_[2];  // [0] -> Rx; [1] -> Other
+    MODE mode_;
+    enum {unknown, off, on} split_;
+    bool ptt_;
+    // Don't forget to update the debug print and != operator if you
+    // add more members here
+
+    friend QDebug operator << (QDebug, TransceiverState const&);
+    friend bool operator != (TransceiverState const&, TransceiverState const&);
+  };
+
+  //
+  // The following slots and signals are expected to all run in the
+  // same thread which is not necessarily the main GUI thread. It is
+  // up to the client of the Transceiver class to organise the
+  // allocation to a thread and the lifetime of the object instances.
+  //
+
+  // Connect and disconnect.
+  Q_SLOT virtual void start () noexcept = 0;
+  Q_SLOT virtual void stop () noexcept = 0;
+
+  // Set frequency in Hertz.
+  Q_SLOT virtual void frequency (Frequency, MODE = UNK) noexcept = 0;
+
+  // Setting a non-zero TX frequency means split operation, the value
+  // zero means simplex operation.
+  //
+  // Rationalise_mode means ensure TX uses same mode as RX.
+  Q_SLOT virtual void tx_frequency (Frequency tx = 0, bool rationalise_mode = true) noexcept = 0;
+
+  // Set mode.
+  // Rationalise means ensure TX uses same mode as RX.
+  Q_SLOT virtual void mode (MODE, bool rationalise = true) noexcept = 0;
+
+  // Set/unset PTT.
+  Q_SLOT virtual void ptt (bool = true) noexcept = 0;
+
+  // Attempt to re-synchronise or query state.
+  // Force_signal guarantees a update or failure signal.
+  Q_SLOT virtual void sync (bool force_signal = false) noexcept = 0;
+
+  // asynchronous status updates
+  Q_SIGNAL void update (Transceiver::TransceiverState) const;
+  Q_SIGNAL void failure (QString reason) const;
+
+  // Ready to be destroyed.
+  Q_SIGNAL void finished () const;
+};
+
+Q_DECLARE_METATYPE (Transceiver::TransceiverState);
+Q_DECLARE_METATYPE (Transceiver::MODE);
+
+#if !defined (QT_NO_DEBUG_STREAM)
+ENUM_QDEBUG_OPS_DECL (Transceiver, MODE);
+
+QDebug operator << (QDebug, Transceiver::TransceiverState const&);
+#endif
+
+ENUM_QDATASTREAM_OPS_DECL (Transceiver, MODE);
+
+ENUM_CONVERSION_OPS_DECL (Transceiver, MODE);
+
+bool operator != (Transceiver::TransceiverState const&, Transceiver::TransceiverState const&);
+bool operator == (Transceiver::TransceiverState const&, Transceiver::TransceiverState const&);
+
+#endif
diff --git a/TransceiverBase.cpp b/TransceiverBase.cpp
new file mode 100644
index 0000000..af4624f
--- /dev/null
+++ b/TransceiverBase.cpp
@@ -0,0 +1,295 @@
+#include "TransceiverBase.hpp"
+
+#include <exception>
+
+#include <QString>
+#include <QTimer>
+#include <QThread>
+#include <QDebug>
+
+namespace
+{
+  auto const unexpected = TransceiverBase::tr ("Unexpected rig error");
+}
+
+void TransceiverBase::start () noexcept
+{
+  QString message;
+  try
+    {
+      if (state_.online ())
+        {
+          try
+            {
+              // try and ensure PTT isn't left set
+              do_ptt (false);
+              do_post_ptt (false);
+            }
+          catch (...)
+            {
+              // don't care about exceptions
+            }
+          do_stop ();
+          do_post_stop ();
+        }
+      do_start ();
+      do_post_start ();
+      state_.online (true);
+    }
+  catch (std::exception const& e)
+    {
+      message = e.what ();
+    }
+  catch (...)
+    {
+      message = unexpected;
+    }
+  if (!message.isEmpty ())
+    {
+      offline (message);
+    }
+}
+
+void TransceiverBase::stop () noexcept
+{
+  QString message;
+  try
+    {
+      if (state_.online ())
+        {
+          try
+            {
+              // try and ensure PTT isn't left set
+              do_ptt (false);
+              do_post_ptt (false);
+            }
+          catch (...)
+            {
+              // don't care about exceptions
+            }
+        }
+      do_stop ();
+      do_post_stop ();
+      state_.online (false);
+    }
+  catch (std::exception const& e)
+    {
+      message = e.what ();
+    }
+  catch (...)
+    {
+      message = unexpected;
+    }
+  if (!message.isEmpty ())
+    {
+      offline (message);
+    }
+  else
+    {
+      Q_EMIT finished ();
+    }
+}
+
+void TransceiverBase::frequency (Frequency f, MODE m) noexcept
+{
+  QString message;
+  try
+    {
+      if (state_.online ())
+        {
+          do_frequency (f, m);
+          do_post_frequency (f, m);
+        }
+    }
+  catch (std::exception const& e)
+    {
+      message = e.what ();
+    }
+  catch (...)
+    {
+      message = unexpected;
+    }
+  if (!message.isEmpty ())
+    {
+      offline (message);
+    }
+}
+
+void TransceiverBase::tx_frequency (Frequency tx, bool rationalise_mode) noexcept
+{
+  QString message;
+  try
+    {
+      if (state_.online ())
+        {
+          do_tx_frequency (tx, rationalise_mode);
+          do_post_tx_frequency (tx, rationalise_mode);
+        }
+    }
+  catch (std::exception const& e)
+    {
+      message = e.what ();
+    }
+  catch (...)
+    {
+      message = unexpected;
+    }
+  if (!message.isEmpty ())
+    {
+      offline (message);
+    }
+}
+
+void TransceiverBase::mode (MODE m, bool rationalise) noexcept
+{
+  QString message;
+  try
+    {
+      if (state_.online ())
+        {
+          do_mode (m, rationalise);
+          do_post_mode (m, rationalise);
+        }
+    }
+  catch (std::exception const& e)
+    {
+      message = e.what ();
+    }
+  catch (...)
+    {
+      message = unexpected;
+    }
+  if (!message.isEmpty ())
+    {
+      offline (message);
+    }
+}
+
+void TransceiverBase::ptt (bool on) noexcept
+{
+  QString message;
+  try
+    {
+      if (state_.online ())
+        {
+          do_ptt (on);
+          do_post_ptt (on);
+        }
+    }
+  catch (std::exception const& e)
+    {
+      message = e.what ();
+    }
+  catch (...)
+    {
+      message = unexpected;
+    }
+  if (!message.isEmpty ())
+    {
+      offline (message);
+    }
+}
+
+void TransceiverBase::sync (bool force_signal) noexcept
+{
+  QString message;
+  try
+    {
+      if (state_.online ())
+        {
+          do_sync (force_signal);
+        }
+    }
+  catch (std::exception const& e)
+    {
+      message = e.what ();
+    }
+  catch (...)
+    {
+      message = unexpected;
+    }
+  if (!message.isEmpty ())
+    {
+      offline (message);
+    }
+}
+
+void TransceiverBase::update_rx_frequency (Frequency rx)
+{
+  state_.frequency (rx);
+}
+
+void TransceiverBase::update_other_frequency (Frequency tx)
+{
+  state_.tx_frequency (tx);
+}
+
+void TransceiverBase::update_split (bool state)
+{
+  state_.split (state);
+}
+
+void TransceiverBase::update_mode (MODE m)
+{
+  state_.mode (m);
+}
+
+void TransceiverBase::update_PTT (bool state)
+{
+  auto prior = state_.ptt ();
+  state_.ptt (state);
+  if (state != prior)
+    {
+      // always signal PTT changes because some MainWindow logic
+      // depends on it
+      update_complete ();
+    }
+}
+
+void TransceiverBase::updated ()
+  {
+    if (do_pre_update ())
+      {
+        Q_EMIT update (state_);
+      }
+  }
+
+void TransceiverBase::update_complete ()
+{
+  // Use a timer to ensure that the calling function completes before
+  // the Transceiver::update signal is triggered.
+  QTimer::singleShot (0, this, SLOT (updated ()));
+}
+
+void TransceiverBase::offline (QString const& reason)
+{
+  QString message;
+  try
+    {
+      if (state_.online ())
+        {
+          try
+            {
+              // try and ensure PTT isn't left set
+              do_ptt (false);
+              do_post_ptt (false);
+            }
+          catch (...)
+            {
+              // don't care about exceptions
+            }
+        }
+      do_stop ();
+      do_post_stop ();
+      state_.online (false);
+    }
+  catch (std::exception const& e)
+    {
+      message = e.what ();
+    }
+  catch (...)
+    {
+      message = unexpected;
+    }
+  Q_EMIT failure (reason + '\n' + message);
+}
diff --git a/TransceiverBase.hpp b/TransceiverBase.hpp
new file mode 100644
index 0000000..6737363
--- /dev/null
+++ b/TransceiverBase.hpp
@@ -0,0 +1,149 @@
+#ifndef TRANSCEIVER_BASE_HPP__
+#define TRANSCEIVER_BASE_HPP__
+
+#include <stdexcept>
+
+#include <QString>
+
+#include "Transceiver.hpp"
+
+//
+// Base Transceiver Implementation
+//
+//  Behaviour common to all Transceiver implementations.
+//
+// Collaborations
+//
+//  Implements the Transceiver abstract  interface as template methods
+//  and provides  a new abstract interface  with similar functionality
+//  (do_XXXXX operations). Provides and  calls abstract interface that
+//  gets  called post  the above  operations (do_post_XXXXX)  to allow
+//  caching implementation etc.
+//
+//  A  key factor  is  to  catch all  exceptions  thrown by  sub-class
+//  implementations where  the template method  is a Qt slot  which is
+//  therefore  likely  to  be  called   by  Qt  which  doesn't  handle
+//  exceptions. Any exceptions are converted to Transceiver::failure()
+//  signals.
+//
+//  Sub-classes update the stored state via a protected interface.
+//
+// Responsibilities:
+//
+//  Wrap incoming  Transceiver messages catching all  exceptions in Qt
+//  slot driven  messages and converting  them to Qt signals.  This is
+//  done because exceptions  make concrete Transceiver implementations
+//  simpler  to   write,  but  exceptions  cannot   cross  signal/slot
+//  boundaries  (especially across  threads).  This  also removes  any
+//  requirement for the client code to handle exceptions.
+//
+//  Maintain the  state of the  concrete Transceiver instance  that is
+//  passed back via  the Transceiver::update(TransceiverState) signal,
+//  it   is  still   the   responsibility   of  concrete   Transceiver
+//  implementations to emit  the state_change signal when  they have a
+//  status update.
+//
+//  Maintain    a   go/no-go    status   for    concrete   Transceiver
+//  implementations  ensuring only  a valid  sequence of  messages are
+//  passed. A concrete Transceiver instance  must be started before it
+//  can receive  messages, any exception thrown  takes the Transceiver
+//  offline.
+//
+//  Implements methods  that concrete Transceiver  implementations use
+//  to update the Transceiver state.  These do not signal state change
+//  to  clients  as  this  is   the  responsibility  of  the  concrete
+//  Transceiver implementation, thus allowing multiple state component
+//  updates to be signalled together if required.
+//
+class TransceiverBase
+  : public Transceiver
+{
+  Q_OBJECT;
+
+protected:
+  TransceiverBase () = default;
+
+public:
+  //
+  // Implement the Transceiver abstract interface.
+  //
+  void start () noexcept override final;
+  void stop () noexcept override final;
+  void frequency (Frequency rx, MODE = UNK) noexcept override final;
+  void tx_frequency (Frequency tx, bool rationalise_mode) noexcept override final;
+  void mode (MODE, bool rationalise) noexcept override final;
+  void ptt (bool) noexcept override final;
+  void sync (bool force_signal) noexcept override final;
+
+protected:
+  //
+  // Error exception which is thrown to signal unexpected errors.
+  //
+  struct error
+    : public std::runtime_error
+  {
+    error (char const * const msg) : std::runtime_error (msg) {}
+    error (QString const& msg) : std::runtime_error (msg.toStdString ()) {}
+  };
+
+  // Template methods that sub classes implement to do what they need to do.
+  //
+  // These methods may throw exceptions to signal errors.
+  virtual void do_start () = 0;
+  virtual void do_post_start () {}
+
+  virtual void do_stop () = 0;
+  virtual void do_post_stop () {}
+
+  virtual void do_frequency (Frequency rx, MODE = UNK) = 0;
+  virtual void do_post_frequency (Frequency, MODE = UNK) {}
+
+  virtual void do_tx_frequency (Frequency tx = 0u, bool rationalise_mode = false) = 0;
+  virtual void do_post_tx_frequency (Frequency = 0u, bool /* rationalise_mode */ = false) {}
+
+  virtual void do_mode (MODE, bool rationalise = true) = 0;
+  virtual void do_post_mode (MODE, bool /* rationalise */ = true) {}
+
+  virtual void do_ptt (bool = true) = 0;
+  virtual void do_post_ptt (bool = true) {}
+
+  virtual void do_sync (bool force_signal = false) = 0;
+
+  virtual bool do_pre_update () {return true;}
+
+  // sub classes report rig state changes with these methods
+  void update_rx_frequency (Frequency);
+  void update_other_frequency (Frequency = 0);
+  void update_split (bool);
+  void update_mode (MODE);
+  void update_PTT (bool = true);
+
+  // Calling this eventually triggers the Transceiver::update(State) signal.
+  void update_complete ();
+
+  // sub class may asynchronously take the rig offline by calling this
+  void offline (QString const& reason);
+
+  // and query state with this one
+  TransceiverState const& state () const {return state_;}
+
+private:
+  Q_SLOT void updated ();
+
+  TransceiverState state_;
+};
+
+// some trace macros
+#if WSJT_TRACE_CAT
+#define TRACE_CAT(MSG) qDebug () << __PRETTY_FUNCTION__ << MSG
+#else
+#define TRACE_CAT(MSG)
+#endif
+
+#if WSJT_TRACE_CAT && WSJT_TRACE_CAT_POLLS
+#define TRACE_CAT_POLL(MSG) qDebug () << __PRETTY_FUNCTION__ << MSG
+#else
+#define TRACE_CAT_POLL(MSG)
+#endif
+
+#endif
diff --git a/TransceiverFactory.cpp b/TransceiverFactory.cpp
new file mode 100644
index 0000000..cfe5848
--- /dev/null
+++ b/TransceiverFactory.cpp
@@ -0,0 +1,219 @@
+#include "TransceiverFactory.hpp"
+
+#include <QMetaType>
+
+#include "HamlibTransceiver.hpp"
+#include "DXLabSuiteCommanderTransceiver.hpp"
+#include "HRDTransceiver.hpp"
+#include "EmulateSplitTransceiver.hpp"
+
+#if defined (WIN32)
+#include "OmniRigTransceiver.hpp"
+#endif
+
+#include "moc_TransceiverFactory.cpp"
+
+// we use the hamlib "Hamlib Dummy" transceiver for non-CAT radios,
+// this allows us to still use the hamlib PTT control features for a
+// unified PTT control solution
+
+char const * const TransceiverFactory::basic_transceiver_name_ = "None";
+
+namespace
+{
+  struct init
+  {
+    init ()
+    {
+      qRegisterMetaType<TransceiverFactory::DataBits> ("TransceiverFactory::DataBits");
+      qRegisterMetaTypeStreamOperators<TransceiverFactory::DataBits> ("TransceiverFactory::DataBits");
+      qRegisterMetaType<TransceiverFactory::StopBits> ("TransceiverFactory::StopBits");
+      qRegisterMetaTypeStreamOperators<TransceiverFactory::StopBits> ("TransceiverFactory::StopBits");
+      qRegisterMetaType<TransceiverFactory::Handshake> ("TransceiverFactory::Handshake");
+      qRegisterMetaTypeStreamOperators<TransceiverFactory::Handshake> ("TransceiverFactory::Handshake");
+      qRegisterMetaType<TransceiverFactory::PTTMethod> ("TransceiverFactory::PTTMethod");
+      qRegisterMetaTypeStreamOperators<TransceiverFactory::PTTMethod> ("TransceiverFactory::PTTMethod");
+      qRegisterMetaType<TransceiverFactory::TXAudioSource> ("TransceiverFactory::TXAudioSource");
+      qRegisterMetaTypeStreamOperators<TransceiverFactory::TXAudioSource> ("TransceiverFactory::TXAudioSource");
+      qRegisterMetaType<TransceiverFactory::SplitMode> ("TransceiverFactory::SplitMode");
+      qRegisterMetaTypeStreamOperators<TransceiverFactory::SplitMode> ("TransceiverFactory::SplitMode");
+    }
+  } static_initializer;
+
+  enum				// supported non-hamlib radio interfaces
+    {
+      NonHamlibBaseId = 9899
+      , CommanderId
+      , HRDId
+      , OmniRigOneId
+      , OmniRigTwoId
+    };
+}
+
+TransceiverFactory::TransceiverFactory ()
+{
+  HamlibTransceiver::register_transceivers (&transceivers_);
+  DXLabSuiteCommanderTransceiver::register_transceivers (&transceivers_, CommanderId);
+  HRDTransceiver::register_transceivers (&transceivers_, HRDId);
+  
+#if defined (WIN32)
+  // OmniRig is ActiveX/COM server so only on Windows
+  OmniRigTransceiver::register_transceivers (&transceivers_, OmniRigOneId, OmniRigTwoId);
+#endif
+}
+
+auto TransceiverFactory::supported_transceivers () const -> Transceivers const&
+{
+  return transceivers_;
+}
+
+auto TransceiverFactory::CAT_port_type (QString const& name) const -> Capabilities::PortType
+{
+  return supported_transceivers ()[name].port_type_;
+}
+
+bool TransceiverFactory::has_CAT_PTT (QString const& name) const
+{
+  return
+    supported_transceivers ()[name].has_CAT_PTT_
+    || supported_transceivers ()[name].model_number_ > NonHamlibBaseId;
+}
+
+bool TransceiverFactory::has_CAT_PTT_mic_data (QString const& name) const
+{
+  return supported_transceivers ()[name].has_CAT_PTT_mic_data_;
+}
+
+bool TransceiverFactory::has_CAT_indirect_serial_PTT (QString const& name) const
+{
+  return supported_transceivers ()[name].has_CAT_indirect_serial_PTT_;
+}
+
+bool TransceiverFactory::has_asynchronous_CAT (QString const& name) const
+{
+  return supported_transceivers ()[name].asynchronous_;
+}
+
+std::unique_ptr<Transceiver> TransceiverFactory::create (ParameterPack const& params, QThread * target_thread)
+{
+  std::unique_ptr<Transceiver> result;
+  switch (supported_transceivers ()[params.rig_name].model_number_)
+    {
+    case CommanderId:
+      {
+        // we start with a dummy HamlibTransceiver object instance that can support direct PTT
+        std::unique_ptr<TransceiverBase> basic_transceiver {new HamlibTransceiver {params.ptt_type, params.ptt_port}};
+        if (target_thread)
+          {
+            basic_transceiver.get ()->moveToThread (target_thread);
+          }
+
+        // wrap the basic Transceiver object instance with a decorator object that talks to DX Lab Suite Commander
+        result.reset (new DXLabSuiteCommanderTransceiver {std::move (basic_transceiver), params.network_port, PTT_method_CAT == params.ptt_type, params.poll_interval});
+        if (target_thread)
+          {
+            result.get ()->moveToThread (target_thread);
+          }
+      }
+      break;
+
+    case HRDId:
+      {
+        // we start with a dummy HamlibTransceiver object instance that can support direct PTT
+        std::unique_ptr<TransceiverBase> basic_transceiver {new HamlibTransceiver {params.ptt_type, params.ptt_port}};
+        if (target_thread)
+          {
+            basic_transceiver.get ()->moveToThread (target_thread);
+          }
+
+        // wrap the basic Transceiver object instance with a decorator object that talks to ham Radio Deluxe
+        result.reset (new HRDTransceiver {std::move (basic_transceiver), params.network_port, PTT_method_CAT == params.ptt_type, params.poll_interval});
+        if (target_thread)
+          {
+            result.get ()->moveToThread (target_thread);
+          }
+      }
+      break;
+
+#if defined (WIN32)
+    case OmniRigOneId:
+      {
+        // we start with a dummy HamlibTransceiver object instance that can support direct PTT
+        std::unique_ptr<TransceiverBase> basic_transceiver {new HamlibTransceiver {params.ptt_type, params.ptt_port}};
+        if (target_thread)
+          {
+            basic_transceiver.get ()->moveToThread (target_thread);
+          }
+
+        // wrap the basic Transceiver object instance with a decorator object that talks to OmniRig rig one
+        result.reset (new OmniRigTransceiver {std::move (basic_transceiver), OmniRigTransceiver::One, params.ptt_type, params.ptt_port});
+        if (target_thread)
+          {
+            result.get ()->moveToThread (target_thread);
+          }
+      }
+      break;
+
+    case OmniRigTwoId:
+      {
+        // we start with a dummy HamlibTransceiver object instance that can support direct PTT
+        std::unique_ptr<TransceiverBase> basic_transceiver {new HamlibTransceiver {params.ptt_type, params.ptt_port}};
+        if (target_thread)
+          {
+            basic_transceiver.get ()->moveToThread (target_thread);
+          }
+
+        // wrap the basic Transceiver object instance with a decorator object that talks to OmniRig rig two
+        result.reset (new OmniRigTransceiver {std::move (basic_transceiver), OmniRigTransceiver::Two, params.ptt_type, params.ptt_port});
+        if (target_thread)
+          {
+            result.get ()->moveToThread (target_thread);
+          }
+      }
+      break;
+#endif
+
+    default:
+      result.reset (new HamlibTransceiver {supported_transceivers ()[params.rig_name].model_number_, params});
+      if (target_thread)
+        {
+          result.get ()->moveToThread (target_thread);
+        }
+      break;
+    }
+
+  if (split_mode_emulate == params.split_mode)
+    {
+      // wrap the Transceiver object instance with a decorator that emulates split mode
+      result.reset (new EmulateSplitTransceiver {std::move (result)});
+      if (target_thread)
+        {
+          result.get ()->moveToThread (target_thread);
+        }
+    }
+
+  return std::move (result);
+}
+
+#if !defined (QT_NO_DEBUG_STREAM)
+ENUM_QDEBUG_OPS_IMPL (TransceiverFactory, DataBits);
+ENUM_QDEBUG_OPS_IMPL (TransceiverFactory, StopBits);
+ENUM_QDEBUG_OPS_IMPL (TransceiverFactory, Handshake);
+ENUM_QDEBUG_OPS_IMPL (TransceiverFactory, PTTMethod);
+ENUM_QDEBUG_OPS_IMPL (TransceiverFactory, TXAudioSource);
+ENUM_QDEBUG_OPS_IMPL (TransceiverFactory, SplitMode);
+#endif
+
+ENUM_QDATASTREAM_OPS_IMPL (TransceiverFactory, DataBits);
+ENUM_QDATASTREAM_OPS_IMPL (TransceiverFactory, StopBits);
+ENUM_QDATASTREAM_OPS_IMPL (TransceiverFactory, Handshake);
+ENUM_QDATASTREAM_OPS_IMPL (TransceiverFactory, PTTMethod);
+ENUM_QDATASTREAM_OPS_IMPL (TransceiverFactory, TXAudioSource);
+ENUM_QDATASTREAM_OPS_IMPL (TransceiverFactory, SplitMode);
+
+ENUM_CONVERSION_OPS_IMPL (TransceiverFactory, DataBits);
+ENUM_CONVERSION_OPS_IMPL (TransceiverFactory, StopBits);
+ENUM_CONVERSION_OPS_IMPL (TransceiverFactory, Handshake);
+ENUM_CONVERSION_OPS_IMPL (TransceiverFactory, PTTMethod);
+ENUM_CONVERSION_OPS_IMPL (TransceiverFactory, TXAudioSource);
+ENUM_CONVERSION_OPS_IMPL (TransceiverFactory, SplitMode);
diff --git a/TransceiverFactory.hpp b/TransceiverFactory.hpp
new file mode 100644
index 0000000..7d0ad18
--- /dev/null
+++ b/TransceiverFactory.hpp
@@ -0,0 +1,186 @@
+#ifndef TRANSCEIVER_FACTORY_HPP__
+#define TRANSCEIVER_FACTORY_HPP__
+
+#include <memory>
+
+#include <QObject>
+#include <QMap>
+
+#include "Transceiver.hpp"
+
+#include "qt_helpers.hpp"
+
+class QString;
+class QThread;
+class QDir;
+
+//
+// Transceiver Factory
+//
+class TransceiverFactory
+  : public QObject
+{
+  Q_OBJECT;
+  Q_ENUMS (DataBits StopBits Handshake PTTMethod TXAudioSource SplitMode);
+
+public:
+  //
+  // Capabilities of a Transceiver that can be determined without
+  // actually instantiating one, these are for use in Configuration
+  // GUI behaviour determination
+  //
+  struct Capabilities
+  {
+    enum PortType {none, serial, network};
+
+    explicit Capabilities (int model_number = 0
+                           , PortType port_type = none
+                           , bool has_CAT_PTT = false
+                           , bool has_CAT_PTT_mic_data = false
+                           , bool has_CAT_indirect_serial_PTT = false
+                           , bool asynchronous = false)
+      : model_number_ {model_number}
+      , port_type_ {port_type}
+      , has_CAT_PTT_ {has_CAT_PTT}
+      , has_CAT_PTT_mic_data_ {has_CAT_PTT_mic_data}
+      , has_CAT_indirect_serial_PTT_ {has_CAT_indirect_serial_PTT}
+      , asynchronous_ {asynchronous}
+    {
+    }
+
+    int model_number_;
+    PortType port_type_;
+    bool has_CAT_PTT_;
+    bool has_CAT_PTT_mic_data_;
+    bool has_CAT_indirect_serial_PTT_; // OmniRig controls RTS/DTR via COM interface
+    bool asynchronous_;
+  };
+
+  //
+  // Dictionary of Transceiver types Capabilities
+  //
+  typedef QMap<QString, Capabilities> Transceivers;
+
+  //
+  // various Transceiver parameters
+  //
+  enum DataBits {seven_data_bits = 7, eight_data_bits};
+  enum StopBits {one_stop_bit = 1, two_stop_bits};
+  enum Handshake {handshake_none, handshake_XonXoff, handshake_hardware};
+  enum PTTMethod {PTT_method_VOX, PTT_method_CAT, PTT_method_DTR, PTT_method_RTS};
+  enum TXAudioSource {TX_audio_source_front, TX_audio_source_rear};
+  enum SplitMode {split_mode_none, split_mode_rig, split_mode_emulate};
+
+  TransceiverFactory ();
+
+  static char const * const basic_transceiver_name_; // dummy transceiver is basic model
+
+  //
+  // fetch all supported rigs as a list of name and model id
+  //
+  Transceivers const& supported_transceivers () const;
+
+  // supported model queries
+  Capabilities::PortType CAT_port_type (QString const& name) const; // how to talk to CAT
+  bool has_CAT_PTT (QString const& name) const;	// can be keyed via CAT
+  bool has_CAT_PTT_mic_data (QString const& name) const; // Tx audio port is switchable via CAT
+  bool has_CAT_indirect_serial_PTT (QString const& name) const; // Can PTT via CAT port use DTR or RTS (OmniRig for example)
+  bool has_asynchronous_CAT (QString const& name) const; // CAT asynchronous rather than polled
+
+  struct ParameterPack
+  {
+    QString rig_name;           // from supported_transceivers () key
+    QString serial_port;        // serial port device name or empty
+    QString network_port;       // hostname:port or empty
+    int baud;
+    DataBits data_bits;
+    StopBits stop_bits;
+    Handshake handshake;
+    bool force_line_control;
+    bool dtr_high;                  // to power interface
+    bool rts_high;                  // to power interface
+    PTTMethod ptt_type;             // "CAT" | "DTR" | "RTS" | "VOX"
+    TXAudioSource audio_source;     // some rigs allow audio routing
+                                    // to Mic/Data connector
+    SplitMode split_mode;           // how to support split TX mode
+    QString ptt_port;         // serial port device name or special
+                              // value "CAT"
+    int poll_interval;        // in seconds for interfaces that
+                              // require polling for state changes
+
+    bool operator == (ParameterPack const& rhs) const
+    {
+      return rhs.rig_name == rig_name
+        && rhs.serial_port == serial_port
+        && rhs.network_port == network_port
+        && rhs.baud == baud
+        && rhs.data_bits == data_bits
+        && rhs.stop_bits == stop_bits
+        && rhs.handshake == handshake
+        && rhs.force_line_control == force_line_control
+        && rhs.dtr_high == dtr_high
+        && rhs.rts_high == rts_high
+        && rhs.ptt_type == ptt_type
+        && rhs.audio_source == audio_source
+        && rhs.split_mode == split_mode
+        && rhs.ptt_port == ptt_port
+        && rhs.poll_interval == poll_interval;
+    }
+  };
+
+  // make a new Transceiver instance
+  //
+  // cat_port, cat_baud, cat_data_bits, cat_stop_bits, cat_handshake,
+  // cat_dtr_control, cat_rts_control are only relevant to interfaces
+  // that are served by Hamlib
+  //
+  // PTT port and to some extent ptt_type are independent of interface
+  // type
+  //
+  std::unique_ptr<Transceiver> create (ParameterPack const&, QThread * target_thread = nullptr);
+  
+private:
+  Transceivers transceivers_;
+};
+
+inline
+bool operator != (TransceiverFactory::ParameterPack const& lhs, TransceiverFactory::ParameterPack const& rhs)
+{
+  return !(lhs == rhs);
+}
+
+//
+// boilerplate routines to make enum types useable and debuggable in
+// Qt
+//
+Q_DECLARE_METATYPE (TransceiverFactory::DataBits);
+Q_DECLARE_METATYPE (TransceiverFactory::StopBits);
+Q_DECLARE_METATYPE (TransceiverFactory::Handshake);
+Q_DECLARE_METATYPE (TransceiverFactory::PTTMethod);
+Q_DECLARE_METATYPE (TransceiverFactory::TXAudioSource);
+Q_DECLARE_METATYPE (TransceiverFactory::SplitMode);
+
+#if !defined (QT_NO_DEBUG_STREAM)
+ENUM_QDEBUG_OPS_DECL (TransceiverFactory, DataBits);
+ENUM_QDEBUG_OPS_DECL (TransceiverFactory, StopBits);
+ENUM_QDEBUG_OPS_DECL (TransceiverFactory, Handshake);
+ENUM_QDEBUG_OPS_DECL (TransceiverFactory, PTTMethod);
+ENUM_QDEBUG_OPS_DECL (TransceiverFactory, TXAudioSource);
+ENUM_QDEBUG_OPS_DECL (TransceiverFactory, SplitMode);
+#endif
+
+ENUM_QDATASTREAM_OPS_DECL (TransceiverFactory, DataBits);
+ENUM_QDATASTREAM_OPS_DECL (TransceiverFactory, StopBits);
+ENUM_QDATASTREAM_OPS_DECL (TransceiverFactory, Handshake);
+ENUM_QDATASTREAM_OPS_DECL (TransceiverFactory, PTTMethod);
+ENUM_QDATASTREAM_OPS_DECL (TransceiverFactory, TXAudioSource);
+ENUM_QDATASTREAM_OPS_DECL (TransceiverFactory, SplitMode);
+
+ENUM_CONVERSION_OPS_DECL (TransceiverFactory, DataBits);
+ENUM_CONVERSION_OPS_DECL (TransceiverFactory, StopBits);
+ENUM_CONVERSION_OPS_DECL (TransceiverFactory, Handshake);
+ENUM_CONVERSION_OPS_DECL (TransceiverFactory, PTTMethod);
+ENUM_CONVERSION_OPS_DECL (TransceiverFactory, TXAudioSource);
+ENUM_CONVERSION_OPS_DECL (TransceiverFactory, SplitMode);
+
+#endif
diff --git a/Versions.cmake b/Versions.cmake
new file mode 100644
index 0000000..019e18f
--- /dev/null
+++ b/Versions.cmake
@@ -0,0 +1,6 @@
+# Version number components
+set (WSJTX_VERSION_MAJOR 1)
+set (WSJTX_VERSION_MINOR 5)
+set (WSJTX_VERSION_PATCH 0)
+set (WSJTX_RC 0)		 # release candidate number, comment out or zero for development versions
+set (WSJTX_VERSION_IS_RELEASE 1) # set to 1 for final release build
diff --git a/WFPalette.cpp b/WFPalette.cpp
new file mode 100644
index 0000000..22dda7f
--- /dev/null
+++ b/WFPalette.cpp
@@ -0,0 +1,330 @@
+#include "WFPalette.hpp"
+
+#include <stdexcept>
+#include <memory>
+#include <algorithm>
+
+#include <QMetaType>
+#include <QObject>
+#include <QFile>
+#include <QTextStream>
+#include <QString>
+#include <QDialog>
+#include <QTableWidget>
+#include <QTableWidgetItem>
+#include <QColorDialog>
+#include <QColor>
+#include <QBrush>
+#include <QPoint>
+#include <QMenu>
+#include <QAction>
+#include <QPushButton>
+#include <QStandardPaths>
+#include <QFileDialog>
+#include <QFile>
+#include <QTextStream>
+#include <QDebug>
+
+#include "qt_helpers.hpp"
+
+#include "ui_wf_palette_design_dialog.h"
+
+namespace
+{
+  int constexpr points {256};
+
+  struct init
+  {
+    init ()
+    {
+      qRegisterMetaTypeStreamOperators<WFPalette::Colours> ("Colours");
+    }
+  } static_initaializer;
+
+  using Colours = WFPalette::Colours;
+
+  // ensure that palette colours are useable for interpolation
+  Colours make_valid (Colours colours)
+  {
+    if (colours.size () < 2)
+      {
+        // allow single element by starting at black
+        colours.prepend (QColor {0, 0, 0});
+      }
+
+    if (1 == colours.size ())
+      {
+        // allow empty list by using black to white
+        colours.append (QColor {255,255,255});
+      }
+
+    if (colours.size () > points)
+      {
+        throw_qstring (QObject::tr ("Too many colours in palette."));
+      }
+
+    return colours;
+  }
+
+  // load palette colours from a file
+  Colours load_palette (QString const& file_name)
+  {
+    Colours colours;
+    QFile file {file_name};
+    if (file.open (QIODevice::ReadOnly))
+      {
+        unsigned count {0};
+        QTextStream in (&file);
+        int line_counter {0};
+        while (!in.atEnd ())
+          {
+            auto line = in.readLine();
+            ++line_counter;
+
+            if (++count >= points)
+              {
+                throw_qstring (QObject::tr ("Error reading waterfall palette file \"%1:%2\" too many colors.")
+                               .arg (file.fileName ()).arg (line_counter));
+              }
+            auto items = line.split (';');
+            if (items.size () != 3)
+              {
+                throw_qstring (QObject::tr ("Error reading waterfall palette file \"%1:%2\" invalid triplet.")
+                               .arg (file.fileName ()).arg (line_counter));
+              }
+            bool r_ok, g_ok, b_ok;
+            auto r = items[0].toInt (&r_ok);
+            auto g = items[1].toInt (&g_ok);
+            auto b = items[2].toInt (&b_ok);
+            if (!r_ok || !g_ok || !b_ok
+                || r < 0 || r > 255
+                || g < 0 || g > 255
+                || b < 0 || b > 255)
+              {
+                throw_qstring (QObject::tr ("Error reading waterfall palette file \"%1:%2\" invalid color.")
+                               .arg (file.fileName ()).arg (line_counter));
+              }
+            colours.append (QColor {r, g, b});
+          }
+      }
+    else
+      {
+        throw_qstring (QObject::tr ("Error opening waterfall palette file \"%1\": %2.").arg (file.fileName ()).arg (file.errorString ()));
+      }
+
+    return colours;
+  }
+
+  // GUI to design and manage waterfall palettes
+  class Designer
+    : public QDialog
+  {
+    Q_OBJECT;
+
+  public:
+    explicit Designer (Colours const& current, QWidget * parent = nullptr)
+      : QDialog {parent}
+      , colours_ {current}
+    {
+      ui_.setupUi (this);
+
+      // context menu actions
+      auto import_button = ui_.button_box->addButton ("&Import...", QDialogButtonBox::ActionRole);
+      connect (import_button, &QPushButton::clicked, this, &Designer::import_palette);
+
+      auto export_button = ui_.button_box->addButton ("&Export...", QDialogButtonBox::ActionRole);
+      connect (export_button, &QPushButton::clicked, this, &Designer::export_palette);
+
+      // hookup the context menu handler
+      connect (ui_.colour_table_widget, &QWidget::customContextMenuRequested, this, &Designer::context_menu);
+
+      load_table ();
+    }
+
+    void load_table ()
+    {
+      // load the table items
+      ui_.colour_table_widget->clear ();
+      ui_.colour_table_widget->setRowCount (colours_.size ());
+      for (int i {0}; i < colours_.size (); ++i)
+        {
+          insert_item (i);
+        }
+    }
+
+    Colours colours () const
+    {
+      return colours_;
+    }
+
+    // invoke the colour editor
+    Q_SLOT void on_colour_table_widget_itemDoubleClicked (QTableWidgetItem * item)
+    {
+      auto new_colour = QColorDialog::getColor (item->background ().color (), this);
+      if (new_colour.isValid ())
+        {
+          item->setBackground (QBrush {new_colour});
+          colours_[item->row ()] = new_colour;
+        }
+    }
+
+  private:
+    void insert_item (int row)
+    {
+      std::unique_ptr<QTableWidgetItem> item {new QTableWidgetItem {""}};
+      item->setBackground (QBrush {colours_[row]});
+      item->setFlags (Qt::ItemIsEnabled);
+      ui_.colour_table_widget->setItem (row, 0, item.release ());
+    }
+
+    void insert_new_item (int row, QColor const& default_colour)
+    {
+      // use the prior row colour as default if available
+      auto new_colour = QColorDialog::getColor (row > 0 ? colours_[row - 1] : default_colour, this);
+      if (new_colour.isValid ())
+        {
+          ui_.colour_table_widget->insertRow (row);
+          colours_.insert (row, new_colour);
+          insert_item (row);
+        }
+    }
+
+    void context_menu (QPoint const& p)
+    {
+      context_menu_.clear ();
+      if (ui_.colour_table_widget->itemAt (p))
+        {
+          auto delete_action = context_menu_.addAction (tr ("&Delete"));
+          connect (delete_action, &QAction::triggered, [this] ()
+                   {
+                     auto row = ui_.colour_table_widget->currentRow ();
+                     ui_.colour_table_widget->removeRow (row);
+                     colours_.removeAt (row);
+                   });
+        }
+
+      auto insert_action = context_menu_.addAction (tr ("&Insert ..."));
+      connect (insert_action, &QAction::triggered, [this] ()
+               {
+                 auto item = ui_.colour_table_widget->itemAt (menu_pos_);
+                 int row = item ? item->row () : colours_.size ();
+                 insert_new_item (row, QColor {0, 0, 0});
+               });
+
+      auto insert_after_action = context_menu_.addAction (tr ("Insert &after ..."));
+      connect (insert_after_action, &QAction::triggered, [this] ()
+               {
+                 auto item = ui_.colour_table_widget->itemAt (menu_pos_);
+                 int row = item ? item->row () + 1 : colours_.size ();
+                 insert_new_item( row, QColor {255, 255, 255});
+               });
+
+      menu_pos_ = p;            // save for context menu action handlers
+      context_menu_.popup (ui_.colour_table_widget->mapToGlobal (p));
+    }
+
+    void import_palette ()
+    {
+      auto docs = QStandardPaths::writableLocation (QStandardPaths::DocumentsLocation);
+      auto file_name = QFileDialog::getOpenFileName (this, tr ("Import Palette"), docs, tr ("Palettes (*.pal)"));
+      if (!file_name.isEmpty ())
+        {
+          colours_ = load_palette (file_name);
+          load_table ();
+        }
+    }
+
+    void export_palette ()
+    {
+      auto docs = QStandardPaths::writableLocation (QStandardPaths::DocumentsLocation);
+      auto file_name = QFileDialog::getSaveFileName (this, tr ("Export Palette"), docs, tr ("Palettes (*.pal)"));
+      if (!file_name.isEmpty ())
+        {
+          if (!QFile::exists (file_name) && !file_name.contains ('.'))
+            {
+              file_name += ".pal";
+            }
+          QFile file {file_name};
+          if (file.open (QFile::WriteOnly | QFile::Truncate | QFile::Text))
+            {
+              QTextStream stream {&file};
+              Q_FOREACH (auto colour, colours_)
+                {
+                  stream << colour.red () << ';' << colour.green () << ';' << colour.blue () << endl;
+                }
+            }
+          else
+            {
+              throw_qstring (QObject::tr ("Error writing waterfall palette file \"%1\": %2.").arg (file.fileName ()).arg (file.errorString ()));
+            }
+        }
+    }
+
+    Ui::wf_palette_design_dialog ui_;
+    Colours colours_;
+    QMenu context_menu_;
+    QPoint menu_pos_;
+  };
+}
+
+#include "WFPalette.moc"
+
+WFPalette::WFPalette (QString const& file_path)
+  : colours_ {load_palette (file_path)}
+{
+}
+
+WFPalette::WFPalette (QList<QColor> const& colour_list)
+  : colours_ {colour_list}
+{
+}
+
+  // generate an array of colours suitable for the waterfall plotter
+QVector<QColor> WFPalette::interpolate () const
+{
+  Colours colours {make_valid (colours_)};
+  QVector<QColor> result;
+  result.reserve (points);
+
+  // do a linear-ish gradient between each supplied colour point
+  auto interval = qreal (points) / (colours.size () - 1);
+
+  for (int i {0}; i < points; ++i)
+    {
+      int prior = i / interval;
+
+      if (prior >= (colours.size () - 1))
+        {
+          --prior;
+        }
+      auto next = prior + 1;
+      if (next >= colours.size ())
+        {
+          --next;
+        }
+
+      // qDebug () << "WFPalette::interpolate: prior:" << prior << "total:" << colours.size ();
+
+      auto increment = i - qreal (interval) * prior;
+      qreal r {colours[prior].redF () + (increment * (colours[next].redF () - colours[prior].redF ()))/interval};
+      qreal g {colours[prior].greenF () + (increment * (colours[next].greenF () - colours[prior].greenF ()))/interval};
+      qreal b {colours[prior].blueF () + (increment * (colours[next].blueF () - colours[prior].blueF ()))/interval};
+      result.append (QColor::fromRgbF (r, g, b));
+
+      // qDebug () << "Palette colour[" << (result.size () - 1) << "] =" << result[result.size () - 1] << "from: r:" << r << "g:" << g << "b:" << b;
+    }
+
+  return result;
+}
+
+  // invoke the palette designer
+bool WFPalette::design ()
+{
+  Designer designer {colours_};
+  if (QDialog::Accepted == designer.exec ())
+    {
+      colours_ = designer.colours ();
+      return true;
+    }
+  return false;
+}
diff --git a/WFPalette.hpp b/WFPalette.hpp
new file mode 100644
index 0000000..271ca53
--- /dev/null
+++ b/WFPalette.hpp
@@ -0,0 +1,55 @@
+#ifndef W_F_PALETTE_HPP__
+#define W_F_PALETTE_HPP__
+
+#include <QList>
+#include <QVector>
+#include <QColor>
+
+class QString;
+
+//
+// Class WFPalette
+//
+//	Encapulates  a waterfall palette  description.  A  colour gradient
+//	over 256 intervals is described  by a list of RGB colour triplets.
+//	The list of  colours are use to interpolate  the full 256 interval
+//	waterfall colour gradient.
+//
+// Responsibilities
+//
+//	Construction from  a string which is  a path to  a file containing
+//	colour  descriptions  in  the   form  rrr;ggg;bbb  on  up  to  256
+//	consecutive lines, where rrr, ggg and, bbb are integral numbers in
+//	the range 0<=n<256.
+//
+//	Construction from a list of QColor instances.  Up to the first 256
+//	list elements are used.
+//
+//	Includes a design GUI to create or adjust a WFPalette.
+//
+class WFPalette
+{
+public:
+  using Colours = QList<QColor>;
+
+  WFPalette () = default;
+  explicit WFPalette (Colours const&);
+  explicit WFPalette (QString const& file_path);
+  WFPalette (WFPalette const&) = default;
+  WFPalette& operator = (WFPalette const&) = default;
+
+  Colours colours () const {return colours_;}
+
+  // interpolate a gradient over 256 steps
+  QVector<QColor> interpolate () const;
+
+  // returns true if colours have been modified
+  bool design ();
+
+private:
+  Colours colours_;
+};
+
+Q_DECLARE_METATYPE (WFPalette::Colours);
+
+#endif
diff --git a/about.cpp b/about.cpp
index 5cab294..99f5194 100644
--- a/about.cpp
+++ b/about.cpp
@@ -1,23 +1,32 @@
 #include "about.h"
+
+#include <QCoreApplication>
+#include <QString>
+
+#include "revision_utils.hpp"
+
 #include "ui_about.h"
+#include "moc_about.cpp"
 
-CAboutDlg::CAboutDlg(QWidget *parent, QString Revision) :
+CAboutDlg::CAboutDlg(QWidget *parent) :
   QDialog(parent),
-  m_Revision(Revision),
   ui(new Ui::CAboutDlg)
 {
   ui->setupUi(this);
-  ui->labelTxt->clear();
-  m_Str  = "<html><h2>" + m_Revision + "</h2>\n\n";
-  m_Str += "WSJT-X implements experimental mode JT9 for <br>";
-  m_Str += "Amateur Radio communication at HF, MF, and LF.  <br><br>";
-  m_Str += "Copyright 2001-2013 by Joe Taylor, K1JT.   Additional <br>";
-  m_Str += "contributions from AC6SL, AE4JY, G4KLA, K3WYC, PY2SDR, <br>";
-  m_Str += "and VK4BDJ.<br>";
-  ui->labelTxt->setText(m_Str);
+
+  ui->labelTxt->setText ("<html><h2>"
+                         + QString {"WSJT-X v"
+                             + QCoreApplication::applicationVersion ()
+                             + " " + revision ()}.simplified ()
+                         + "</h2>\n\n"
+                         "WSJT-X implements digital modes JT9 and JT65 for <br>"
+                         "Amateur Radio communication.  <br><br>"
+                         "© 2001-2015 by Joe Taylor, K1JT, with grateful <br>"
+                         "acknowledgment for contributions from AC6SL, AE4JY, <br>"
+                         "DJ0OT, G4KLA, G4WJS, K3WYC, KA6MAL, KA9Q, KB1ZMX, <br>"
+                         "KI7MT, KK1D, PY2SDR, VK3ACF, VK4BDJ, W4TI, W4TV, and W9MDB.<br>");
 }
 
 CAboutDlg::~CAboutDlg()
 {
-  delete ui;
 }
diff --git a/about.h b/about.h
index ca45d19..c2ac75d 100644
--- a/about.h
+++ b/about.h
@@ -1,24 +1,24 @@
+// -*- Mode: C++ -*-
 #ifndef ABOUTDLG_H
 #define ABOUTDLG_H
 
 #include <QDialog>
+#include <QScopedPointer>
 
 namespace Ui {
-    class CAboutDlg;
+  class CAboutDlg;
 }
 
 class CAboutDlg : public QDialog
 {
-    Q_OBJECT
+  Q_OBJECT;
 
 public:
-	explicit CAboutDlg(QWidget *parent=0, QString Revision="");
-    ~CAboutDlg();
-
+	explicit CAboutDlg(QWidget *parent = nullptr);
+  ~CAboutDlg ();
+  
 private:
-	QString m_Revision;
-	Ui::CAboutDlg *ui;
-	QString m_Str;
+	QScopedPointer<Ui::CAboutDlg> ui;
 };
 
 #endif // ABOUTDLG_H
diff --git a/about.ui b/about.ui
index 3a86259..8e8b926 100644
--- a/about.ui
+++ b/about.ui
@@ -10,7 +10,7 @@
     <x>0</x>
     <y>0</y>
     <width>374</width>
-    <height>164</height>
+    <height>144</height>
    </rect>
   </property>
   <property name="sizePolicy">
@@ -24,17 +24,75 @@
   </property>
   <layout class="QVBoxLayout" name="verticalLayout">
    <item>
-    <widget class="QLabel" name="labelTxt">
-     <property name="text">
-      <string/>
+    <layout class="QHBoxLayout" name="horizontalLayout_2">
+     <item>
+      <widget class="QLabel" name="labelTxt">
+       <property name="text">
+        <string/>
+       </property>
+       <property name="alignment">
+        <set>Qt::AlignCenter</set>
+       </property>
+      </widget>
+     </item>
+    </layout>
+   </item>
+   <item>
+    <spacer name="verticalSpacer">
+     <property name="orientation">
+      <enum>Qt::Vertical</enum>
      </property>
-     <property name="alignment">
-      <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
+     <property name="sizeHint" stdset="0">
+      <size>
+       <width>20</width>
+       <height>40</height>
+      </size>
      </property>
-    </widget>
+    </spacer>
+   </item>
+   <item>
+    <layout class="QHBoxLayout" name="horizontalLayout">
+     <item>
+      <spacer name="horizontalSpacer">
+       <property name="orientation">
+        <enum>Qt::Horizontal</enum>
+       </property>
+       <property name="sizeHint" stdset="0">
+        <size>
+         <width>40</width>
+         <height>20</height>
+        </size>
+       </property>
+      </spacer>
+     </item>
+     <item>
+      <widget class="QPushButton" name="okButton">
+       <property name="text">
+        <string>OK</string>
+       </property>
+      </widget>
+     </item>
+    </layout>
    </item>
   </layout>
  </widget>
  <resources/>
- <connections/>
+ <connections>
+  <connection>
+   <sender>okButton</sender>
+   <signal>clicked()</signal>
+   <receiver>CAboutDlg</receiver>
+   <slot>accept()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>321</x>
+     <y>120</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>186</x>
+     <y>71</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
 </ui>
diff --git a/afmhot.dat b/afmhot.dat
deleted file mode 100644
index 8b312a1..0000000
--- a/afmhot.dat
+++ /dev/null
@@ -1,257 +0,0 @@
-     0      0.0000    0.0000    0.0000
-     1	    0.0000    0.0000    0.0000
-     2	    0.0078    0.0000    0.0000
-     3	    0.0157    0.0000    0.0000
-     4	    0.0235    0.0000    0.0000
-     5	    0.0314    0.0000    0.0000
-     6	    0.0392    0.0000    0.0000
-     7	    0.0471    0.0000    0.0000
-     8	    0.0549    0.0000    0.0000
-     9	    0.0627    0.0000    0.0000
-    10	    0.0706    0.0000    0.0000
-    11	    0.0784    0.0000    0.0000
-    12	    0.0863    0.0000    0.0000
-    13	    0.0941    0.0000    0.0000
-    14	    0.1020    0.0000    0.0000
-    15	    0.1098    0.0000    0.0000
-    16	    0.1176    0.0000    0.0000
-    17	    0.1255    0.0000    0.0000
-    18	    0.1333    0.0000    0.0000
-    19	    0.1412    0.0000    0.0000
-    20	    0.1490    0.0000    0.0000
-    21	    0.1569    0.0000    0.0000
-    22	    0.1647    0.0000    0.0000
-    23	    0.1725    0.0000    0.0000
-    24	    0.1804    0.0000    0.0000
-    25	    0.1882    0.0000    0.0000
-    26	    0.1961    0.0000    0.0000
-    27	    0.2039    0.0000    0.0000
-    28	    0.2118    0.0000    0.0000
-    29	    0.2196    0.0000    0.0000
-    30	    0.2275    0.0000    0.0000
-    31	    0.2353    0.0000    0.0000
-    32	    0.2431    0.0000    0.0000
-    33	    0.2510    0.0000    0.0000
-    34	    0.2588    0.0000    0.0000
-    35	    0.2667    0.0000    0.0000
-    36	    0.2745    0.0000    0.0000
-    37	    0.2824    0.0000    0.0000
-    38	    0.2902    0.0000    0.0000
-    39	    0.2980    0.0000    0.0000
-    40	    0.3059    0.0000    0.0000
-    41	    0.3137    0.0000    0.0000
-    42	    0.3216    0.0000    0.0000
-    43	    0.3294    0.0000    0.0000
-    44	    0.3373    0.0000    0.0000
-    45	    0.3451    0.0000    0.0000
-    46	    0.3529    0.0000    0.0000
-    47	    0.3608    0.0000    0.0000
-    48	    0.3686    0.0000    0.0000
-    49	    0.3765    0.0000    0.0000
-    50	    0.3843    0.0000    0.0000
-    51	    0.3922    0.0000    0.0000
-    52	    0.4000    0.0000    0.0000
-    53	    0.4078    0.0000    0.0000
-    54	    0.4157    0.0000    0.0000
-    55	    0.4235    0.0000    0.0000
-    56	    0.4314    0.0000    0.0000
-    57	    0.4392    0.0000    0.0000
-    58	    0.4471    0.0000    0.0000
-    59	    0.4549    0.0000    0.0000
-    60	    0.4627    0.0000    0.0000
-    61	    0.4706    0.0000    0.0000
-    62	    0.4784    0.0000    0.0000
-    63	    0.4863    0.0000    0.0000
-    64	    0.4941    0.0000    0.0000
-    65	    0.5020    0.0000    0.0000
-    66	    0.5098    0.0098    0.0000
-    67	    0.5176    0.0176    0.0000
-    68	    0.5255    0.0255    0.0000
-    69	    0.5333    0.0333    0.0000
-    70	    0.5412    0.0412    0.0000
-    71	    0.5490    0.0490    0.0000
-    72	    0.5569    0.0569    0.0000
-    73	    0.5647    0.0647    0.0000
-    74	    0.5725    0.0725    0.0000
-    75	    0.5804    0.0804    0.0000
-    76	    0.5882    0.0882    0.0000
-    77	    0.5961    0.0961    0.0000
-    78	    0.6039    0.1039    0.0000
-    79	    0.6118    0.1118    0.0000
-    80	    0.6196    0.1196    0.0000
-    81	    0.6275    0.1275    0.0000
-    82	    0.6353    0.1353    0.0000
-    83	    0.6431    0.1431    0.0000
-    84	    0.6510    0.1510    0.0000
-    85	    0.6588    0.1588    0.0000
-    86	    0.6667    0.1667    0.0000
-    87	    0.6745    0.1745    0.0000
-    88	    0.6824    0.1824    0.0000
-    89	    0.6902    0.1902    0.0000
-    90	    0.6980    0.1980    0.0000
-    91	    0.7059    0.2059    0.0000
-    92	    0.7137    0.2137    0.0000
-    93	    0.7216    0.2216    0.0000
-    94	    0.7294    0.2294    0.0000
-    95	    0.7373    0.2373    0.0000
-    96	    0.7451    0.2451    0.0000
-    97	    0.7529    0.2529    0.0000
-    98	    0.7608    0.2608    0.0000
-    99	    0.7686    0.2686    0.0000
-   100	    0.7765    0.2765    0.0000
-   101	    0.7843    0.2843    0.0000
-   102	    0.7922    0.2922    0.0000
-   103	    0.8000    0.3000    0.0000
-   104	    0.8078    0.3078    0.0000
-   105	    0.8157    0.3157    0.0000
-   106	    0.8235    0.3235    0.0000
-   107	    0.8314    0.3314    0.0000
-   108	    0.8392    0.3392    0.0000
-   109	    0.8471    0.3471    0.0000
-   110	    0.8549    0.3549    0.0000
-   111	    0.8627    0.3627    0.0000
-   112	    0.8706    0.3706    0.0000
-   113	    0.8784    0.3784    0.0000
-   114	    0.8863    0.3863    0.0000
-   115	    0.8941    0.3941    0.0000
-   116	    0.9020    0.4020    0.0000
-   117	    0.9098    0.4098    0.0000
-   118	    0.9176    0.4176    0.0000
-   119	    0.9255    0.4255    0.0000
-   120	    0.9333    0.4333    0.0000
-   121	    0.9412    0.4412    0.0000
-   122	    0.9490    0.4490    0.0000
-   123	    0.9569    0.4569    0.0000
-   124	    0.9647    0.4647    0.0000
-   125	    0.9725    0.4725    0.0000
-   126	    0.9804    0.4804    0.0000
-   127	    0.9882    0.4882    0.0000
-   128	    0.9961    0.4961    0.0000
-   129	    1.0000    0.5039    0.0000
-   130	    1.0000    0.5118    0.0118
-   131	    1.0000    0.5196    0.0196
-   132	    1.0000    0.5275    0.0275
-   133	    1.0000    0.5353    0.0353
-   134	    1.0000    0.5431    0.0431
-   135	    1.0000    0.5510    0.0510
-   136	    1.0000    0.5588    0.0588
-   137	    1.0000    0.5667    0.0667
-   138	    1.0000    0.5745    0.0745
-   139	    1.0000    0.5824    0.0824
-   140	    1.0000    0.5902    0.0902
-   141	    1.0000    0.5980    0.0980
-   142	    1.0000    0.6059    0.1059
-   143	    1.0000    0.6137    0.1137
-   144	    1.0000    0.6216    0.1216
-   145	    1.0000    0.6294    0.1294
-   146	    1.0000    0.6373    0.1373
-   147	    1.0000    0.6451    0.1451
-   148	    1.0000    0.6529    0.1529
-   149	    1.0000    0.6608    0.1608
-   150	    1.0000    0.6686    0.1686
-   151	    1.0000    0.6765    0.1765
-   152	    1.0000    0.6843    0.1843
-   153	    1.0000    0.6922    0.1922
-   154	    1.0000    0.7000    0.2000
-   155	    1.0000    0.7078    0.2078
-   156	    1.0000    0.7157    0.2157
-   157	    1.0000    0.7235    0.2235
-   158	    1.0000    0.7314    0.2314
-   159	    1.0000    0.7392    0.2392
-   160	    1.0000    0.7471    0.2471
-   161	    1.0000    0.7549    0.2549
-   162	    1.0000    0.7627    0.2627
-   163	    1.0000    0.7706    0.2706
-   164	    1.0000    0.7784    0.2784
-   165	    1.0000    0.7863    0.2863
-   166	    1.0000    0.7941    0.2941
-   167	    1.0000    0.8020    0.3020
-   168	    1.0000    0.8098    0.3098
-   169	    1.0000    0.8176    0.3176
-   170	    1.0000    0.8255    0.3255
-   171	    1.0000    0.8333    0.3333
-   172	    1.0000    0.8412    0.3412
-   173	    1.0000    0.8490    0.3490
-   174	    1.0000    0.8569    0.3569
-   175	    1.0000    0.8647    0.3647
-   176	    1.0000    0.8725    0.3725
-   177	    1.0000    0.8804    0.3804
-   178	    1.0000    0.8882    0.3882
-   179	    1.0000    0.8961    0.3961
-   180	    1.0000    0.9039    0.4039
-   181	    1.0000    0.9118    0.4118
-   182	    1.0000    0.9196    0.4196
-   183	    1.0000    0.9275    0.4275
-   184	    1.0000    0.9353    0.4353
-   185	    1.0000    0.9431    0.4431
-   186	    1.0000    0.9510    0.4510
-   187	    1.0000    0.9588    0.4588
-   188	    1.0000    0.9667    0.4667
-   189	    1.0000    0.9745    0.4745
-   190	    1.0000    0.9824    0.4824
-   191	    1.0000    0.9902    0.4902
-   192	    1.0000    0.9980    0.4980
-   193	    1.0000    1.0000    0.5059
-   194	    1.0000    1.0000    0.5137
-   195	    1.0000    1.0000    0.5216
-   196	    1.0000    1.0000    0.5294
-   197	    1.0000    1.0000    0.5373
-   198	    1.0000    1.0000    0.5451
-   199	    1.0000    1.0000    0.5529
-   200	    1.0000    1.0000    0.5608
-   201	    1.0000    1.0000    0.5686
-   202	    1.0000    1.0000    0.5765
-   203	    1.0000    1.0000    0.5843
-   204	    1.0000    1.0000    0.5922
-   205	    1.0000    1.0000    0.6000
-   206	    1.0000    1.0000    0.6078
-   207	    1.0000    1.0000    0.6157
-   208	    1.0000    1.0000    0.6235
-   209	    1.0000    1.0000    0.6314
-   210	    1.0000    1.0000    0.6392
-   211	    1.0000    1.0000    0.6471
-   212	    1.0000    1.0000    0.6549
-   213	    1.0000    1.0000    0.6627
-   214	    1.0000    1.0000    0.6706
-   215	    1.0000    1.0000    0.6784
-   216	    1.0000    1.0000    0.6863
-   217	    1.0000    1.0000    0.6941
-   218	    1.0000    1.0000    0.7020
-   219	    1.0000    1.0000    0.7098
-   220	    1.0000    1.0000    0.7176
-   221	    1.0000    1.0000    0.7255
-   222	    1.0000    1.0000    0.7333
-   223	    1.0000    1.0000    0.7412
-   224	    1.0000    1.0000    0.7490
-   225	    1.0000    1.0000    0.7569
-   226	    1.0000    1.0000    0.7647
-   227	    1.0000    1.0000    0.7725
-   228	    1.0000    1.0000    0.7804
-   229	    1.0000    1.0000    0.7882
-   230	    1.0000    1.0000    0.7961
-   231	    1.0000    1.0000    0.8039
-   232	    1.0000    1.0000    0.8118
-   233	    1.0000    1.0000    0.8196
-   234	    1.0000    1.0000    0.8275
-   235	    1.0000    1.0000    0.8353
-   236	    1.0000    1.0000    0.8431
-   237	    1.0000    1.0000    0.8510
-   238	    1.0000    1.0000    0.8588
-   239	    1.0000    1.0000    0.8667
-   240	    1.0000    1.0000    0.8745
-   241	    1.0000    1.0000    0.8824
-   242	    1.0000    1.0000    0.8902
-   243	    1.0000    1.0000    0.8980
-   244	    1.0000    1.0000    0.9059
-   245	    1.0000    1.0000    0.9137
-   246	    1.0000    1.0000    0.9216
-   247	    1.0000    1.0000    0.9294
-   248	    1.0000    1.0000    0.9373
-   249	    1.0000    1.0000    0.9451
-   250	    1.0000    1.0000    0.9529
-   251	    1.0000    1.0000    0.9608
-   252	    1.0000    1.0000    0.9686
-   253	    1.0000    1.0000    0.9765
-   254	    1.0       0.0       0.0
-   255	    1.0       1.0       0.0
-   256	    0.0       1.000     0.0
diff --git a/artwork/DragNDrop Background.svg b/artwork/DragNDrop Background.svg
new file mode 100644
index 0000000..fa325a7
--- /dev/null
+++ b/artwork/DragNDrop Background.svg	
@@ -0,0 +1,143 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   id="Layer_1"
+   space="preserve"
+   sodipodi:version="0.32"
+   viewBox="0 0 640 480"
+   version="1.1"
+   sodipodi:docname="tasto_5_architetto_franc_01.svg"
+   inkscape:version="0.48.4 r9939"
+   width="100%"
+   height="100%">
+  <defs
+     id="defs6110" />
+  <sodipodi:namedview
+     id="base"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     pagecolor="#ffffff"
+     showgrid="false"
+     inkscape:zoom="1.89375"
+     inkscape:cx="227.06271"
+     inkscape:cy="240"
+     inkscape:window-width="1855"
+     inkscape:window-height="1056"
+     inkscape:window-x="65"
+     inkscape:window-y="24"
+     inkscape:window-maximized="1"
+     inkscape:current-layer="g3" />
+  <g
+     id="g3"
+     transform="translate(0,342.62101)">
+    <radialGradient
+       id="XMLID_2_"
+       gradientUnits="userSpaceOnUse"
+       cy="42.188999"
+       cx="42.785999"
+       r="69.833"
+       gradientTransform="translate(237.98657,-269.79195)">
+      <stop
+         id="stop6"
+         stop-color="#D1F593"
+         offset="0" />
+      <stop
+         id="stop8"
+         stop-color="#81CE09"
+         offset="1" />
+    </radialGradient>
+    <path
+       id="path10"
+       d="m 294.86757,-261.31295 v 11.564 c 0,1.741 1.297,11.914 0,13.039 -1.02,0.886 -6.762,0 -8.05,0 h -18.478 c -7.957,0 -22.38,-2.722 -27.218,5.536 -3.929,6.711 -1.526,19.418 -1.526,26.711 0,8.382 -0.774,17.167 0,25.519 0,13.355 15.573,11.178 24.427,11.178 h 30.258 c 1.235,0 0.587,21.391 0.587,24.12 0,9.468 9.867,13.694 16.696,6.885 5.979,-5.956 11.956,-11.914 17.934,-17.874 12.723,-12.681 27.184,-24.79 38.705,-38.581 8.129,-8.157 -0.109,-15.919 -5.847,-21.664 -7.818,-7.824 -15.637,- [...]
+       inkscape:connector-curvature="0"
+       style="fill:url(#XMLID_2_)" />
+    <path
+       id="path12"
+       d="m 239.59557,-225.52895 v 25.519 c 0,7.292 -2.404,20 1.526,26.707 4.839,8.26 19.258,5.537 27.214,5.537 h 17.257 c 1.47,0 8.123,-1.016 9.274,0 1.14,1.006 0,9.882 0,11.396 v 14.252 c 0,10.854 12.136,9.904 17.771,4.287 15.045,-14.996 30.09,-29.993 45.136,-44.991 5.456,-5.438 15.865,-12.589 13.176,-21.487 -0.317,0.598 -3.726,2.826 -4.396,3.495 -3.066,3.059 -6.136,6.117 -9.201,9.174 -8.52,8.492 -17.037,16.985 -25.555,25.477 -5.672,5.654 -11.342,11.308 -17.012,16.961 -2.447,2.439 -6.5 [...]
+       inkscape:connector-curvature="0"
+       style="fill:#67ba06" />
+    <path
+       id="path14"
+       d="m 247.70757,-168.51195 c -2.771,-7.597 -0.677,-18.748 -0.677,-26.612 0,-8.349 -1.456,-18.099 0.173,-26.347 1.843,-9.349 18.409,-6.667 25.217,-6.667 h 29.23 c 0.768,0 -0.319,-21.606 0.808,-24.748 3.407,-9.491 12.963,0.134 16.668,3.857 15.269,15.341 30.538,30.681 45.805,46.022 1.224,1.231 5.246,3.916 6.019,5.379 2.872,-9.511 -10.045,-18.432 -15.802,-24.213 l -32.322,-32.461 c -5.208,-5.23 -12.42,-16.139 -21.006,-14.488 -11.102,2.133 -6.951,23.787 -6.951,31.819 -9.333,0 -18.663,-0 [...]
+       inkscape:connector-curvature="0"
+       style="fill:#b2ed21" />
+    <path
+       id="path16"
+       d="m 299.44057,-268.80395 c -9.2,3.806 -5.476,22.395 -5.476,30.261 0,1.951 -23.229,0.93 -26.087,0.93 -8.576,0 -23.012,-2.757 -27.835,6.535 -3.627,6.99 -1.35,19.146 -1.35,26.616 0,8.4 -0.709,17.143 0,25.519 0,13.884 15.395,12.081 24.75,12.081 h 30.326 c 0.616,0 -0.196,23.651 0.363,26.81 1.344,7.601 11.873,10.134 17.171,4.83 1.235,-0.97 2.304,-2.297 3.414,-3.404 6.86,-6.837 13.72,-13.676 20.579,-20.514 7.706,-7.681 15.41,-15.36 23.116,-23.042 4.011,-3.997 10.436,-8.579 12.863,-13.90 [...]
+       inkscape:connector-curvature="0"
+       style="fill:#739b07" />
+    <text
+       xml:space="preserve"
+       style="font-size:40px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#ff7400;fill-opacity:0.77254902;stroke:none;font-family:Purisa;-inkscape-font-specification:Sans Bold"
+       x="316.39532"
+       y="-58.000538"
+       id="text6112"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan6114"
+         x="316.39532"
+         y="-58.000538">Drag the icon</tspan><tspan
+         sodipodi:role="line"
+         x="316.39532"
+         y="-8.0005379"
+         id="tspan6116">onto the link</tspan><tspan
+         sodipodi:role="line"
+         x="316.39532"
+         y="41.999462"
+         id="tspan6118">to install WSJT-X</tspan></text>
+  </g>
+  <metadata
+     id="metadata6108">
+    <rdf:RDF>
+      <cc:Work>
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <cc:license
+           rdf:resource="http://creativecommons.org/licenses/publicdomain/" />
+        <dc:publisher>
+          <cc:Agent
+             rdf:about="http://openclipart.org/">
+            <dc:title>Openclipart</dc:title>
+          </cc:Agent>
+        </dc:publisher>
+        <dc:title></dc:title>
+        <dc:date>2010-03-28T09:25:56</dc:date>
+        <dc:description>Drawing by Francesco 'Architetto' Rollandin. From OCAL 0.18 release.</dc:description>
+        <dc:source>http://openclipart.org/detail/34711/architetto----tasto-5-by-anonymous</dc:source>
+        <dc:creator>
+          <cc:Agent>
+            <dc:title>Anonymous</dc:title>
+          </cc:Agent>
+        </dc:creator>
+        <dc:subject>
+          <rdf:Bag>
+            <rdf:li>arrow</rdf:li>
+            <rdf:li>clip art</rdf:li>
+            <rdf:li>clipart</rdf:li>
+            <rdf:li>green</rdf:li>
+            <rdf:li>icon</rdf:li>
+            <rdf:li>right</rdf:li>
+            <rdf:li>sign</rdf:li>
+            <rdf:li>symbol</rdf:li>
+          </rdf:Bag>
+        </dc:subject>
+      </cc:Work>
+      <cc:License
+         rdf:about="http://creativecommons.org/licenses/publicdomain/">
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Reproduction" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Distribution" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
+      </cc:License>
+    </rdf:RDF>
+  </metadata>
+</svg>
diff --git a/artwork/README b/artwork/README
new file mode 100644
index 0000000..04aa460
--- /dev/null
+++ b/artwork/README
@@ -0,0 +1,30 @@
+This directory contains original artwork used to generate the graphics
+used in various parts of the WSJT-X ecosystem. The CMake build scripts
+do not  generate the  final image bitmaps  because of the  extra tools
+required to  complete this  step. Instead there  is shell  script here
+(make_graphics.sh) that does the generation. If you want to modify the
+source graphics  or add new  ones then you  need an SVG editor  (I use
+inkscape)  and  a   tool  to  do  various  conversion   steps  (I  use
+ImageMagick), the shell script explicitly uses these tools.
+
+The files here are:
+
+installer_logo.svg - A 150x57 pixel  image (the size is important with
+    a  whte background  that is  used  at the  top right  of the  NSIS
+    Windows installer.
+
+wsjt_globe_1024x1024.svg - A 1024x1024 pixel generic globe image which
+    is used in various places, mainly for high resolution icons.
+
+wsjtx_globe_1024x1024.svg -  A 1024x1024  pixel WSJT-X  specific image
+    which is used in various places, mainly for high resolution icons.
+
+wsjt_globe_128x128.svg - A  128x128 pixel image which is  used for low
+    resolution icons.
+
+make_graphics.sh  -  Run  this  script  (on  Linux)  to  generate  the
+    intermediate  bitmap image  files used  in the  wsjtx  build. This
+    script  generates all  but the  final  Mac iconset  file which  is
+    generated by a build on Mac since it requires a Mac developer tool
+    (iconutil). This script requires that inkscape and ImageMagick are
+    installed.
\ No newline at end of file
diff --git a/artwork/installer_logo.svg b/artwork/installer_logo.svg
new file mode 100644
index 0000000..4dcf15e
--- /dev/null
+++ b/artwork/installer_logo.svg
@@ -0,0 +1,1126 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   height="1024"
+   id="svg1432"
+   inkscape:version="0.48.4 r9939"
+   sodipodi:docname="installer_logo.svg"
+   sodipodi:version="0.32"
+   width="2700"
+   version="1.1">
+  <sodipodi:namedview
+     bordercolor="#666666"
+     borderopacity="1.0"
+     id="base"
+     inkscape:current-layer="svg1432"
+     inkscape:cx="736.10268"
+     inkscape:cy="525.6389"
+     inkscape:guide-bbox="true"
+     inkscape:pageopacity="1"
+     inkscape:pageshadow="2"
+     inkscape:window-height="732"
+     inkscape:window-width="1818"
+     inkscape:window-x="72"
+     inkscape:window-y="31"
+     inkscape:zoom="0.57128906"
+     pagecolor="#ffffff"
+     showborder="false"
+     showguides="true"
+     showgrid="false"
+     inkscape:window-maximized="0"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0"
+     inkscape:showpageshadow="false" />
+  <metadata
+     id="metadata3060">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:title />
+        <dc:description>Simple globe centered on North America</dc:description>
+        <dc:subject>
+          <rdf:Bag>
+            <rdf:li>earth globe northamerica</rdf:li>
+          </rdf:Bag>
+        </dc:subject>
+        <dc:publisher>
+          <cc:Agent
+             rdf:about="http://www.openclipart.org/">
+            <dc:title>Open Clip Art Library</dc:title>
+          </cc:Agent>
+        </dc:publisher>
+        <dc:creator>
+          <cc:Agent>
+            <dc:title>Dan Gerhrads</dc:title>
+          </cc:Agent>
+        </dc:creator>
+        <dc:rights>
+          <cc:Agent>
+            <dc:title>Dan Gerhrads</dc:title>
+          </cc:Agent>
+        </dc:rights>
+        <dc:date>May 1, 2005</dc:date>
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <cc:license
+           rdf:resource="http://web.resource.org/cc/PublicDomain" />
+        <dc:language>en</dc:language>
+      </cc:Work>
+      <cc:License
+         rdf:about="http://web.resource.org/cc/PublicDomain">
+        <cc:permits
+           rdf:resource="http://web.resource.org/cc/Reproduction" />
+        <cc:permits
+           rdf:resource="http://web.resource.org/cc/Distribution" />
+        <cc:permits
+           rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
+      </cc:License>
+    </rdf:RDF>
+  </metadata>
+  <defs
+     id="defs1759">
+    <color-profile
+       id="color-profile3264"
+       xlink:href="/usr/share/color/icc/colord/sRGB.icc"
+       name="sRGB" />
+    <linearGradient
+       id="linearGradient3150">
+      <stop
+         id="stop3152"
+         offset="0"
+         style="stop-color:#0015be;stop-opacity:0.34615386;" />
+      <stop
+         id="stop3154"
+         offset="1"
+         style="stop-color:#ffffff;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient37658">
+      <stop
+         style="stop-color:#488afe;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop37660" />
+      <stop
+         style="stop-color:#0000cc;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop37662" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient20137">
+      <stop
+         style="stop-color:#00d800;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop20139" />
+      <stop
+         style="stop-color:#008e00;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop20141" />
+    </linearGradient>
+    <radialGradient
+       xlink:href="#linearGradient20137"
+       r="188.61865"
+       inkscape:collect="always"
+       id="radialGradient1902"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.893959,1.11862)"
+       fy="298.37747"
+       fx="205.17723"
+       cy="297.1124"
+       cx="202.06305" />
+    <linearGradient
+       gradientTransform="translate(2,0)"
+       gradientUnits="userSpaceOnUse"
+       y2="470.63556"
+       x2="2693.2854"
+       y1="481.66608"
+       x1="3.6768403"
+       id="linearGradient3156-4"
+       xlink:href="#linearGradient3150-3"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient3150-3">
+      <stop
+         id="stop3152-8"
+         offset="0"
+         style="stop-color:#0015be;stop-opacity:0.57692307;" />
+      <stop
+         id="stop3154-8"
+         offset="1"
+         style="stop-color:#ffffff;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       gradientUnits="userSpaceOnUse"
+       y2="512"
+       x2="2700"
+       y1="512"
+       x1="0"
+       id="linearGradient6055"
+       xlink:href="#linearGradient3150-3"
+       inkscape:collect="always" />
+    <radialGradient
+       xlink:href="#linearGradient37658-154"
+       r="112.3373"
+       inkscape:collect="always"
+       id="radialGradient37664-353"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.806632,1.239722)"
+       fy="270.08731"
+       fx="221.61394"
+       cy="270.08731"
+       cx="221.61394" />
+    <linearGradient
+       id="linearGradient37658-154">
+      <stop
+         style="stop-color:#619afe;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop8063" />
+      <stop
+         style="stop-color:#0000e5;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop8065" />
+    </linearGradient>
+    <radialGradient
+       xlink:href="#linearGradient20137-322"
+       r="188.61865"
+       inkscape:collect="always"
+       id="radialGradient1902-112"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.893959,1.11862)"
+       fy="298.37747"
+       fx="205.17723"
+       cy="297.1124"
+       cx="202.06305" />
+    <linearGradient
+       id="linearGradient20137-322">
+      <stop
+         style="stop-color:#00f100;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop8069" />
+      <stop
+         style="stop-color:#00a700;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop8071" />
+    </linearGradient>
+    <radialGradient
+       xlink:href="#linearGradient20137-81"
+       r="188.61865"
+       inkscape:collect="always"
+       id="radialGradient1904-638"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.893959,1.11862)"
+       fy="298.37747"
+       fx="205.17723"
+       cy="297.1124"
+       cx="202.06305" />
+    <linearGradient
+       id="linearGradient20137-81">
+      <stop
+         style="stop-color:#00f100;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop8075" />
+      <stop
+         style="stop-color:#00a700;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop8077" />
+    </linearGradient>
+    <radialGradient
+       xlink:href="#linearGradient20137-519"
+       r="188.61865"
+       inkscape:collect="always"
+       id="radialGradient1906-851"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.893959,1.11862)"
+       fy="298.37747"
+       fx="205.17723"
+       cy="297.1124"
+       cx="202.06305" />
+    <linearGradient
+       id="linearGradient20137-519">
+      <stop
+         style="stop-color:#00f100;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop8081" />
+      <stop
+         style="stop-color:#00a700;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop8083" />
+    </linearGradient>
+    <radialGradient
+       xlink:href="#linearGradient20137-435"
+       r="188.61865"
+       inkscape:collect="always"
+       id="radialGradient1908-440"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.893959,1.11862)"
+       fy="298.37747"
+       fx="205.17723"
+       cy="297.1124"
+       cx="202.06305" />
+    <linearGradient
+       id="linearGradient20137-435">
+      <stop
+         style="stop-color:#00f100;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop8087" />
+      <stop
+         style="stop-color:#00a700;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop8089" />
+    </linearGradient>
+    <radialGradient
+       xlink:href="#linearGradient20137-894"
+       r="188.61865"
+       inkscape:collect="always"
+       id="radialGradient1910-742"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.893959,1.11862)"
+       fy="298.37747"
+       fx="205.17723"
+       cy="297.1124"
+       cx="202.06305" />
+    <linearGradient
+       id="linearGradient20137-894">
+      <stop
+         style="stop-color:#00f100;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop8093" />
+      <stop
+         style="stop-color:#00a700;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop8095" />
+    </linearGradient>
+    <radialGradient
+       xlink:href="#linearGradient20137-303"
+       r="188.61865"
+       inkscape:collect="always"
+       id="radialGradient1912-831"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.893959,1.11862)"
+       fy="298.37747"
+       fx="205.17723"
+       cy="297.1124"
+       cx="202.06305" />
+    <linearGradient
+       id="linearGradient20137-303">
+      <stop
+         style="stop-color:#00f100;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop8099" />
+      <stop
+         style="stop-color:#00a700;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop8101" />
+    </linearGradient>
+    <radialGradient
+       xlink:href="#linearGradient20137-620"
+       r="188.61865"
+       inkscape:collect="always"
+       id="radialGradient1914-236"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.893959,1.11862)"
+       fy="298.37747"
+       fx="205.17723"
+       cy="297.1124"
+       cx="202.06305" />
+    <linearGradient
+       id="linearGradient20137-620">
+      <stop
+         style="stop-color:#00f100;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop8105" />
+      <stop
+         style="stop-color:#00a700;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop8107" />
+    </linearGradient>
+    <radialGradient
+       xlink:href="#linearGradient20137-55"
+       r="188.61865"
+       inkscape:collect="always"
+       id="radialGradient1916-546"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.893959,1.11862)"
+       fy="298.37747"
+       fx="205.17723"
+       cy="297.1124"
+       cx="202.06305" />
+    <linearGradient
+       id="linearGradient20137-55">
+      <stop
+         style="stop-color:#00f100;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop8111" />
+      <stop
+         style="stop-color:#00a700;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop8113" />
+    </linearGradient>
+    <radialGradient
+       xlink:href="#linearGradient20137-730"
+       r="188.61865"
+       inkscape:collect="always"
+       id="radialGradient1918-66"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.893959,1.11862)"
+       fy="298.37747"
+       fx="205.17723"
+       cy="297.1124"
+       cx="202.06305" />
+    <linearGradient
+       id="linearGradient20137-730">
+      <stop
+         style="stop-color:#00f100;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop8117" />
+      <stop
+         style="stop-color:#00a700;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop8119" />
+    </linearGradient>
+    <radialGradient
+       xlink:href="#linearGradient20137-743"
+       r="188.61865"
+       inkscape:collect="always"
+       id="radialGradient1920-575"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.893959,1.11862)"
+       fy="298.37747"
+       fx="205.17723"
+       cy="297.1124"
+       cx="202.06305" />
+    <linearGradient
+       id="linearGradient20137-743">
+      <stop
+         style="stop-color:#00f100;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop8123" />
+      <stop
+         style="stop-color:#00a700;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop8125" />
+    </linearGradient>
+    <radialGradient
+       xlink:href="#linearGradient20137-567"
+       r="188.61865"
+       inkscape:collect="always"
+       id="radialGradient20143-511"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.893959,1.11862)"
+       fy="298.37747"
+       fx="205.17723"
+       cy="297.1124"
+       cx="202.06305" />
+    <linearGradient
+       id="linearGradient20137-567">
+      <stop
+         style="stop-color:#00f100;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop8129" />
+      <stop
+         style="stop-color:#00a700;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop8131" />
+    </linearGradient>
+    <filter
+       inkscape:collect="always"
+       id="filter9044">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="0.72650164"
+         id="feGaussianBlur9046" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter9048">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="0.59290756"
+         id="feGaussianBlur9050" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter9052">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="2.4671427"
+         id="feGaussianBlur9054" />
+    </filter>
+    <radialGradient
+       xlink:href="#linearGradient37658-154-452"
+       r="112.3373"
+       inkscape:collect="always"
+       id="radialGradient37664-353-94"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.806632,1.239722)"
+       fy="270.08731"
+       fx="221.61394"
+       cy="270.08731"
+       cx="221.61394" />
+    <linearGradient
+       id="linearGradient37658-154-452">
+      <stop
+         style="stop-color:#7aaafe;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop9132" />
+      <stop
+         style="stop-color:#0000fe;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop9134" />
+    </linearGradient>
+    <radialGradient
+       xlink:href="#linearGradient20137-322-373"
+       r="188.61865"
+       inkscape:collect="always"
+       id="radialGradient1902-112-480"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.893959,1.11862)"
+       fy="298.37747"
+       fx="205.17723"
+       cy="297.1124"
+       cx="202.06305" />
+    <linearGradient
+       id="linearGradient20137-322-373">
+      <stop
+         style="stop-color:#0bfe0b;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop9138" />
+      <stop
+         style="stop-color:#00c000;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop9140" />
+    </linearGradient>
+    <radialGradient
+       xlink:href="#linearGradient20137-81-324"
+       r="188.61865"
+       inkscape:collect="always"
+       id="radialGradient1904-638-4"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.893959,1.11862)"
+       fy="298.37747"
+       fx="205.17723"
+       cy="297.1124"
+       cx="202.06305" />
+    <linearGradient
+       id="linearGradient20137-81-324">
+      <stop
+         style="stop-color:#0bfe0b;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop9144" />
+      <stop
+         style="stop-color:#00c000;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop9146" />
+    </linearGradient>
+    <radialGradient
+       xlink:href="#linearGradient20137-519-815"
+       r="188.61865"
+       inkscape:collect="always"
+       id="radialGradient1906-851-150"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.893959,1.11862)"
+       fy="298.37747"
+       fx="205.17723"
+       cy="297.1124"
+       cx="202.06305" />
+    <linearGradient
+       id="linearGradient20137-519-815">
+      <stop
+         style="stop-color:#0bfe0b;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop9150" />
+      <stop
+         style="stop-color:#00c000;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop9152" />
+    </linearGradient>
+    <radialGradient
+       xlink:href="#linearGradient20137-435-846"
+       r="188.61865"
+       inkscape:collect="always"
+       id="radialGradient1908-440-497"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.893959,1.11862)"
+       fy="298.37747"
+       fx="205.17723"
+       cy="297.1124"
+       cx="202.06305" />
+    <linearGradient
+       id="linearGradient20137-435-846">
+      <stop
+         style="stop-color:#0bfe0b;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop9156" />
+      <stop
+         style="stop-color:#00c000;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop9158" />
+    </linearGradient>
+    <radialGradient
+       xlink:href="#linearGradient20137-894-56"
+       r="188.61865"
+       inkscape:collect="always"
+       id="radialGradient1910-742-917"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.893959,1.11862)"
+       fy="298.37747"
+       fx="205.17723"
+       cy="297.1124"
+       cx="202.06305" />
+    <linearGradient
+       id="linearGradient20137-894-56">
+      <stop
+         style="stop-color:#0bfe0b;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop9162" />
+      <stop
+         style="stop-color:#00c000;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop9164" />
+    </linearGradient>
+    <radialGradient
+       xlink:href="#linearGradient20137-303-107"
+       r="188.61865"
+       inkscape:collect="always"
+       id="radialGradient1912-831-900"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.893959,1.11862)"
+       fy="298.37747"
+       fx="205.17723"
+       cy="297.1124"
+       cx="202.06305" />
+    <linearGradient
+       id="linearGradient20137-303-107">
+      <stop
+         style="stop-color:#0bfe0b;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop9168" />
+      <stop
+         style="stop-color:#00c000;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop9170" />
+    </linearGradient>
+    <radialGradient
+       xlink:href="#linearGradient20137-620-939"
+       r="188.61865"
+       inkscape:collect="always"
+       id="radialGradient1914-236-546"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.893959,1.11862)"
+       fy="298.37747"
+       fx="205.17723"
+       cy="297.1124"
+       cx="202.06305" />
+    <linearGradient
+       id="linearGradient20137-620-939">
+      <stop
+         style="stop-color:#0bfe0b;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop9174" />
+      <stop
+         style="stop-color:#00c000;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop9176" />
+    </linearGradient>
+    <radialGradient
+       xlink:href="#linearGradient20137-55-417"
+       r="188.61865"
+       inkscape:collect="always"
+       id="radialGradient1916-546-728"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.893959,1.11862)"
+       fy="298.37747"
+       fx="205.17723"
+       cy="297.1124"
+       cx="202.06305" />
+    <linearGradient
+       id="linearGradient20137-55-417">
+      <stop
+         style="stop-color:#0bfe0b;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop9180" />
+      <stop
+         style="stop-color:#00c000;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop9182" />
+    </linearGradient>
+    <radialGradient
+       xlink:href="#linearGradient20137-730-735"
+       r="188.61865"
+       inkscape:collect="always"
+       id="radialGradient1918-66-618"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.893959,1.11862)"
+       fy="298.37747"
+       fx="205.17723"
+       cy="297.1124"
+       cx="202.06305" />
+    <linearGradient
+       id="linearGradient20137-730-735">
+      <stop
+         style="stop-color:#0bfe0b;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop9186" />
+      <stop
+         style="stop-color:#00c000;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop9188" />
+    </linearGradient>
+    <radialGradient
+       xlink:href="#linearGradient20137-743-507"
+       r="188.61865"
+       inkscape:collect="always"
+       id="radialGradient1920-575-258"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.893959,1.11862)"
+       fy="298.37747"
+       fx="205.17723"
+       cy="297.1124"
+       cx="202.06305" />
+    <linearGradient
+       id="linearGradient20137-743-507">
+      <stop
+         style="stop-color:#0bfe0b;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop9192" />
+      <stop
+         style="stop-color:#00c000;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop9194" />
+    </linearGradient>
+    <radialGradient
+       xlink:href="#linearGradient20137-567-640"
+       r="188.61865"
+       inkscape:collect="always"
+       id="radialGradient20143-511-422"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.893959,1.11862)"
+       fy="298.37747"
+       fx="205.17723"
+       cy="297.1124"
+       cx="202.06305" />
+    <linearGradient
+       id="linearGradient20137-567-640">
+      <stop
+         style="stop-color:#0bfe0b;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop9198" />
+      <stop
+         style="stop-color:#00c000;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop9200" />
+    </linearGradient>
+    <linearGradient
+       gradientUnits="userSpaceOnUse"
+       y2="512"
+       x2="2700"
+       y1="512"
+       x1="0"
+       id="linearGradient6055-394"
+       xlink:href="#linearGradient3150-3-152"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient3150-3-152">
+      <stop
+         id="stop9482"
+         offset="0"
+         style="stop-color:#0017d7;stop-opacity:0.57692307;" />
+      <stop
+         id="stop9484"
+         offset="1"
+         style="stop-color:#ffffff;stop-opacity:0;" />
+    </linearGradient>
+    <radialGradient
+       xlink:href="#linearGradient37658-154-452-872"
+       r="112.3373"
+       inkscape:collect="always"
+       id="radialGradient37664-353-94-400"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.806632,1.239722)"
+       fy="270.08731"
+       fx="221.61394"
+       cy="270.08731"
+       cx="221.61394" />
+    <linearGradient
+       id="linearGradient37658-154-452-872">
+      <stop
+         style="stop-color:#93bafe;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop9488" />
+      <stop
+         style="stop-color:#1818ff;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop9490" />
+    </linearGradient>
+    <radialGradient
+       xlink:href="#linearGradient20137-322-373-854"
+       r="188.61865"
+       inkscape:collect="always"
+       id="radialGradient1902-112-480-465"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.893959,1.11862)"
+       fy="298.37747"
+       fx="205.17723"
+       cy="297.1124"
+       cx="202.06305" />
+    <linearGradient
+       id="linearGradient20137-322-373-854">
+      <stop
+         style="stop-color:#24fe24;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop9494" />
+      <stop
+         style="stop-color:#00d900;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop9496" />
+    </linearGradient>
+    <radialGradient
+       xlink:href="#linearGradient20137-81-324-224"
+       r="188.61865"
+       inkscape:collect="always"
+       id="radialGradient1904-638-4-94"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.893959,1.11862)"
+       fy="298.37747"
+       fx="205.17723"
+       cy="297.1124"
+       cx="202.06305" />
+    <linearGradient
+       id="linearGradient20137-81-324-224">
+      <stop
+         style="stop-color:#24fe24;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop9500" />
+      <stop
+         style="stop-color:#00d900;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop9502" />
+    </linearGradient>
+    <radialGradient
+       xlink:href="#linearGradient20137-519-815-807"
+       r="188.61865"
+       inkscape:collect="always"
+       id="radialGradient1906-851-150-223"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.893959,1.11862)"
+       fy="298.37747"
+       fx="205.17723"
+       cy="297.1124"
+       cx="202.06305" />
+    <linearGradient
+       id="linearGradient20137-519-815-807">
+      <stop
+         style="stop-color:#24fe24;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop9506" />
+      <stop
+         style="stop-color:#00d900;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop9508" />
+    </linearGradient>
+    <radialGradient
+       xlink:href="#linearGradient20137-435-846-332"
+       r="188.61865"
+       inkscape:collect="always"
+       id="radialGradient1908-440-497-194"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.893959,1.11862)"
+       fy="298.37747"
+       fx="205.17723"
+       cy="297.1124"
+       cx="202.06305" />
+    <linearGradient
+       id="linearGradient20137-435-846-332">
+      <stop
+         style="stop-color:#24fe24;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop9512" />
+      <stop
+         style="stop-color:#00d900;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop9514" />
+    </linearGradient>
+    <radialGradient
+       xlink:href="#linearGradient20137-894-56-1"
+       r="188.61865"
+       inkscape:collect="always"
+       id="radialGradient1910-742-917-65"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.893959,1.11862)"
+       fy="298.37747"
+       fx="205.17723"
+       cy="297.1124"
+       cx="202.06305" />
+    <linearGradient
+       id="linearGradient20137-894-56-1">
+      <stop
+         style="stop-color:#24fe24;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop9518" />
+      <stop
+         style="stop-color:#00d900;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop9520" />
+    </linearGradient>
+    <radialGradient
+       xlink:href="#linearGradient20137-303-107-144"
+       r="188.61865"
+       inkscape:collect="always"
+       id="radialGradient1912-831-900-925"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.893959,1.11862)"
+       fy="298.37747"
+       fx="205.17723"
+       cy="297.1124"
+       cx="202.06305" />
+    <linearGradient
+       id="linearGradient20137-303-107-144">
+      <stop
+         style="stop-color:#24fe24;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop9524" />
+      <stop
+         style="stop-color:#00d900;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop9526" />
+    </linearGradient>
+    <radialGradient
+       xlink:href="#linearGradient20137-620-939-550"
+       r="188.61865"
+       inkscape:collect="always"
+       id="radialGradient1914-236-546-309"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.893959,1.11862)"
+       fy="298.37747"
+       fx="205.17723"
+       cy="297.1124"
+       cx="202.06305" />
+    <linearGradient
+       id="linearGradient20137-620-939-550">
+      <stop
+         style="stop-color:#24fe24;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop9530" />
+      <stop
+         style="stop-color:#00d900;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop9532" />
+    </linearGradient>
+    <radialGradient
+       xlink:href="#linearGradient20137-55-417-836"
+       r="188.61865"
+       inkscape:collect="always"
+       id="radialGradient1916-546-728-597"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.893959,1.11862)"
+       fy="298.37747"
+       fx="205.17723"
+       cy="297.1124"
+       cx="202.06305" />
+    <linearGradient
+       id="linearGradient20137-55-417-836">
+      <stop
+         style="stop-color:#24fe24;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop9536" />
+      <stop
+         style="stop-color:#00d900;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop9538" />
+    </linearGradient>
+    <radialGradient
+       xlink:href="#linearGradient20137-730-735-878"
+       r="188.61865"
+       inkscape:collect="always"
+       id="radialGradient1918-66-618-911"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.893959,1.11862)"
+       fy="298.37747"
+       fx="205.17723"
+       cy="297.1124"
+       cx="202.06305" />
+    <linearGradient
+       id="linearGradient20137-730-735-878">
+      <stop
+         style="stop-color:#24fe24;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop9542" />
+      <stop
+         style="stop-color:#00d900;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop9544" />
+    </linearGradient>
+    <radialGradient
+       xlink:href="#linearGradient20137-743-507-804"
+       r="188.61865"
+       inkscape:collect="always"
+       id="radialGradient1920-575-258-291"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.893959,1.11862)"
+       fy="298.37747"
+       fx="205.17723"
+       cy="297.1124"
+       cx="202.06305" />
+    <linearGradient
+       id="linearGradient20137-743-507-804">
+      <stop
+         style="stop-color:#24fe24;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop9548" />
+      <stop
+         style="stop-color:#00d900;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop9550" />
+    </linearGradient>
+    <radialGradient
+       xlink:href="#linearGradient20137-567-640-6"
+       r="188.61865"
+       inkscape:collect="always"
+       id="radialGradient20143-511-422-890"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.893959,1.11862)"
+       fy="298.37747"
+       fx="205.17723"
+       cy="297.1124"
+       cx="202.06305" />
+    <linearGradient
+       id="linearGradient20137-567-640-6">
+      <stop
+         style="stop-color:#24fe24;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop9554" />
+      <stop
+         style="stop-color:#00d900;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop9556" />
+    </linearGradient>
+    <filter
+       inkscape:collect="always"
+       id="filter9802">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="0.43590098"
+         id="feGaussianBlur9804" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter9806">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="0.35574454"
+         id="feGaussianBlur9808" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter9810">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="1.4802856"
+         id="feGaussianBlur9812" />
+    </filter>
+  </defs>
+  <desc
+     id="desc1434">wmf2svg</desc>
+  <rect
+     y="0"
+     x="0"
+     height="1024"
+     width="2700"
+     id="rect3148"
+     style="color:#000000;fill:url(#linearGradient6055-394);fill-opacity:1.0;fill-rule:nonzero;stroke:none;stroke-width:3.20800000000000018;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;stroke-miterlimit:4;stroke-dasharray:none" />
+  <polyline
+     transform="matrix(2.2285926,-3.5745108,2.3232002,1.4484387,-335.7972,673.31075)"
+     style="fill:url(#radialGradient37664-353-94-400);fill-opacity:1;stroke:#242424;stroke-width:0.68750000000000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;opacity:1;filter:url(#filter9802)"
+     points="103.191467,409.292114   100.730545,403.134064 98.525299,396.927094 96.543777,390.573547 94.785973,384.171082   93.219925,377.622009 91.909569,371.072968 90.790962,364.426147 89.928040,357.779327   89.256882,351.083649 88.777481,344.387970 88.521805,337.692261 88.489838,330.947693   88.681602,324.300873 89.033165,317.605194 89.640404,311.007263 90.407448,304.458221   91.398209,298.006897 92.580727,291.604431 93.986977,285.299744 95.553017,279.092804   97.342781,272.983582 99. [...]
+     id="polyline1560" />
+  <g
+     transform="matrix(4.1610916,0,0,4.1610916,72.860393,-736.02673)"
+     style="fill:url(#radialGradient1902-112-480-465);fill-opacity:1;fill-rule:evenodd;opacity:1;filter:url(#filter9806)"
+     inkscape:label="Continents"
+     id="Continents">
+    <polyline
+       transform="matrix(0.535579,-0.859032,0.558315,0.348091,-98.20917,338.6942)"
+       style="fill:url(#radialGradient1904-638-4-94);stroke:#242424;stroke-width:0.44458500000000001;stroke-linecap:round;stroke-linejoin:round"
+       points="132.818436,384.610931   131.827682,384.953064 128.184235,388.227600 126.074867,388.667450 123.422180,385.441803   120.417938,385.832794 117.126053,389.107300 116.838409,393.896912 116.902328,400.641479   115.655891,409.292114 114.409447,415.352448 115.432167,418.235992 113.578484,420.386444   111.053642,420.924042 109.903076,422.732361 109.871117,423.172241 116.295090,433.728943   123.262383,443.161530 130.836914,451.421204 140.904327,460.071808 151.195465,466.425385   153 [...]
+       id="polyline1460" />
+    <polyline
+       transform="matrix(0.535579,-0.859032,0.558315,0.348091,-98.20917,338.6942)"
+       style="fill:url(#radialGradient1906-851-150-223);stroke:#242424;stroke-width:0.44458500000000001;stroke-linecap:round;stroke-linejoin:round"
+       points="144.579727,355.237885   146.497345,357.241699 147.583984,362.324585 148.638672,368.384918 149.980988,372.539154   150.364502,377.035553 148.798477,377.279877 146.753021,373.467743 146.976746,368.433777   146.593216,362.959930 144.579727,355.237885 "
+       id="polyline1464" />
+    <polyline
+       transform="matrix(0.535579,-0.859032,0.558315,0.348091,-98.20917,338.6942)"
+       style="fill:url(#radialGradient1908-440-497-194);stroke:#242424;stroke-width:0.44458500000000001;stroke-linecap:round;stroke-linejoin:round"
+       points="150.108826,378.892731   148.830429,379.870209 149.309830,383.584595 150.172745,386.614777 152.633667,390.964508   152.505829,386.565887 153.336792,386.077148 153.017197,383.780090 150.108826,378.892731 "
+       id="polyline1468" />
+    <polyline
+       transform="matrix(0.535579,-0.859032,0.558315,0.348091,-98.20917,338.6942)"
+       style="fill:url(#radialGradient1910-742-917-65);stroke:#242424;stroke-width:0.44458500000000001;stroke-linecap:round;stroke-linejoin:round"
+       points="201.181000,353.820557   200.797470,356.459747 200.413956,361.053864 199.966507,365.990082 199.007706,368.238281   196.866379,363.204285 197.921066,357.681580 199.103592,354.895782 201.181000,353.820557 "
+       id="polyline1472" />
+    <polyline
+       transform="matrix(0.535579,-0.859032,0.558315,0.348091,-98.20917,338.6942)"
+       style="fill:url(#radialGradient1912-831-900-925);stroke:#242424;stroke-width:0.44458500000000001;stroke-linecap:round;stroke-linejoin:round"
+       points="204.632675,320.342133   203.993469,316.774353 202.906830,312.668976 206.230682,314.575043 208.883362,312.277985   209.842163,309.052338 208.915314,303.822876 208.563766,299.961853 209.874130,294.487976   212.430923,295.514343 213.261887,299.570862 213.581497,305.386810 213.837173,310.958405   212.111328,314.917175 211.951538,317.018738 212.335052,321.466217 210.800964,325.913727   208.691605,325.376099 206.454407,326.646820 205.016205,324.203125 204.632675,320.342133 "
+       id="polyline1476" />
+    <polyline
+       transform="matrix(0.535579,-0.859032,0.558315,0.348091,-98.20917,338.6942)"
+       style="fill:url(#radialGradient1914-236-546-309);stroke:#242424;stroke-width:0.44458500000000001;stroke-linecap:round;stroke-linejoin:round"
+       points="213.773254,334.955322   213.709335,340.820160 213.869125,343.263885 216.362015,346.636139 219.526062,350.594910   218.695099,344.632324 219.685867,341.406677 222.722061,339.060730 227.835663,334.662109   230.648163,335.786194 233.332809,333.147003 234.355515,326.011475 234.675125,319.218048   233.556534,312.522369 233.588486,306.071045 231.511078,300.646057 228.890350,297.420410   226.365509,296.980560 225.246902,294.830109 226.365509,293.461639 225.023193,290.235992   222 [...]
+       id="polyline1480" />
+    <polyline
+       transform="matrix(0.535579,-0.859032,0.558315,0.348091,-98.20917,338.6942)"
+       style="fill:url(#radialGradient1916-546-728-597);stroke:#242424;stroke-width:0.44458500000000001;stroke-linecap:round;stroke-linejoin:round"
+       points="232.533813,338.767487   230.200729,341.748779 229.401718,344.436798 229.721313,347.662476 233.460648,348.542206   237.040161,346.929382 237.231934,342.872864 235.378250,340.478088 233.620453,340.282562   232.533813,338.767487 "
+       id="polyline1484" />
+    <polyline
+       transform="matrix(0.535579,-0.859032,0.558315,0.348091,-98.20917,338.6942)"
+       style="fill:url(#radialGradient1918-66-618-911);stroke:#242424;stroke-width:0.44458500000000001;stroke-linecap:round;stroke-linejoin:round"
+       points="264.877380,375.813690   262.991730,379.919098 260.371002,382.167236 258.645172,385.148529 258.645172,389.693817   256.887360,391.062256 255.161514,388.911804 254.522308,386.956848 252.732559,385.197418   253.339798,391.697632 251.709839,392.332977 249.792236,387.738861 248.322067,389.840393   246.724060,393.017212 244.327072,395.412018 242.952774,399.664001 241.514587,403.329529   241.067139,407.337158 239.565018,407.190552 238.318573,407.777039 235.665894,409.096649   233 [...]
+       id="polyline1488" />
+    <polyline
+       transform="matrix(0.535579,-0.859032,0.558315,0.348091,-98.20917,338.6942)"
+       style="fill:url(#radialGradient1920-575-258-291);stroke:#242424;stroke-width:0.44458500000000001;stroke-linecap:round;stroke-linejoin:round"
+       points="244.774506,357.779327   243.304337,356.313110 242.345535,358.512421 241.131058,362.666687 239.916580,364.817108   238.062897,367.945038 237.615448,372.930145 238.414459,375.324951 239.373245,373.125641   239.852661,368.727020 240.683624,367.602905 241.067139,371.121826 241.290848,375.129456   241.834183,378.452850 243.336304,376.986664 243.528061,376.937775 243.719818,376.888916   243.911591,376.791168 244.071396,376.644531 244.390976,376.351288 244.678635,376.009186   244 [...]
+       id="polyline1492" />
+    <polyline
+       transform="matrix(0.535579,-0.859032,0.558315,0.348091,-98.20917,338.6942)"
+       style="fill:url(#radialGradient20143-511-422-890);stroke:#242424;stroke-width:0.44458500000000001;stroke-linecap:round;stroke-linejoin:round"
+       points="262.192749,389.449432   260.115326,391.160004 258.261658,394.287933 256.663635,394.532288 255.992477,392.968323   255.065643,395.802979 253.851151,400.885864 250.783005,404.209290 250.175766,401.276855   249.344803,399.810638 245.573502,402.889679 242.537292,406.213104 240.747543,406.995056   238.126801,409.878601 236.049423,409.976349 233.748291,411.002716 231.606964,415.010315   228.986237,420.826294 226.333542,423.123352 220.996231,428.059601 216.617691,433.680054   213 [...]
+       id="polyline1496" />
+  </g>
+  <text
+     transform="matrix(0.98267844,-0.18531886,0.18531886,0.98267844,0,0)"
+     sodipodi:linespacing="125%"
+     id="text3096"
+     y="500.67648"
+     x="733.04114"
+     style="font-size:187.56237793000002512px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#fe9c4b;fill-opacity:0.77168950000000003;stroke:none;font-family:Purisa;-inkscape-font-specification:Purisa Bold;opacity:1;filter:url(#filter9810)"
+     xml:space="preserve"><tspan
+       dy="-109.78781"
+       dx="0 -9.8032694 -11.763925 -17.645885"
+       id="tspan3102"
+       y="500.67648"
+       x="733.04114"
+       sodipodi:role="line">WSJT-X</tspan><tspan
+       dx="0 -17.645885 -23.527849 -13.724579 29.30662 29.30662 -17.645885 -23.527849"
+       id="tspan3874"
+       y="735.12946"
+       x="733.04114"
+       sodipodi:role="line">JT65&JT9</tspan><tspan
+       dy="91.489815"
+       dx="0 0 0 0 -17.645885 -5.8819623 -17.645885"
+       id="tspan3100"
+       y="969.5824"
+       x="733.04114"
+       sodipodi:role="line">by K1JT</tspan></text>
+</svg>
diff --git a/artwork/make_graphics.sh b/artwork/make_graphics.sh
new file mode 100755
index 0000000..6178734
--- /dev/null
+++ b/artwork/make_graphics.sh
@@ -0,0 +1,72 @@
+#!/bin/sh
+
+#
+# Windows
+#
+inkscape -z -e /tmp/image-0.png wsjt_globe_128x128.svg
+inkscape -z -e /tmp/image-1.png wsjtx_globe_1024x1024.svg
+convert '/tmp/image-%d.png[0-1]' -background transparent	\
+    \( -clone 0 -resize 16 -colors 256 -compress none \)	\
+    \( -clone 0 -resize 20 -colors 256 -compress none \)	\
+    \( -clone 0 -resize 24 -colors 256 -compress none \)	\
+    \( -clone 0 -resize 32 -colors 256 -compress none \)	\
+    \( -clone 0 -resize 40 -colors 256 -compress none \)	\
+    \( -clone 1 -resize 48 -colors 256 -compress none \)	\
+    \( -clone 1 -resize 96 -colors 256 -compress none \)	\
+    \( -clone 1 -resize 128 -colors 256 -compress none \)	\
+    \( -clone 0 -resize 16 -compress none \)	\
+    \( -clone 0 -resize 20 -compress none \)	\
+    \( -clone 0 -resize 24 -compress none \)	\
+    \( -clone 0 -resize 32 -compress none \)	\
+    \( -clone 0 -resize 40 -compress none \)	\
+    \( -clone 1 -resize 48 -compress none \)	\
+    \( -clone 1 -resize 64 -compress none \)	\
+    \( -clone 1 -resize 96 -compress none \)	\
+    \( -clone 1 -resize 128 -compress none \)	\
+    \( -clone 1 -resize 256 -compress Zip \)	\
+    -delete 1 -delete 0	\
+    -alpha remove ../icons/windows-icons/wsjtx.ico
+rm /tmp/image-0.png /tmp/image-1.png
+identify -format '%f %p/%n %m %C/%Q %r %G %A %z\n' ../icons/windows-icons/wsjtx.ico
+#
+inkscape -z -e /dev/stdout -w 150 -h 57 -b white installer_logo.svg | tail -n +4 |	\
+    convert png:- -resize 150x57 +matte BMP3:../icons/windows-icons/installer_logo.bmp
+identify -format '%f %p/%n %m %C/%Q %r %G %A %z\n' ../icons/windows-icons/installer_logo.bmp
+
+#
+# Mac
+#
+mkdir -p ../icons/Darwin/wsjtx.iconset
+inkscape -z -e ../icons/Darwin/wsjtx.iconset/icon_16x16.png -w 16 -h 16 wsjt_globe_128x128.svg
+inkscape -z -e ../icons/Darwin/wsjtx.iconset/icon_16x16 at 2x.png -w 32 -h 32 wsjt_globe_128x128.svg
+inkscape -z -e ../icons/Darwin/wsjtx.iconset/icon_32x32.png -w 32 -h 32 wsjt_globe_128x128.svg
+inkscape -z -e ../icons/Darwin/wsjtx.iconset/icon_32x32 at 2x.png -w 64 -h 64 wsjt_globe_128x128.svg
+inkscape -z -e ../icons/Darwin/wsjtx.iconset/icon_128x128.png -w 128 -h 128 wsjtx_globe_1024x1024.svg
+inkscape -z -e ../icons/Darwin/wsjtx.iconset/icon_128x128 at 2x.png -w 256 -h 256 wsjtx_globe_1024x1024.svg
+inkscape -z -e ../icons/Darwin/wsjtx.iconset/icon_256x256.png -w 256 -h 256 wsjtx_globe_1024x1024.svg
+inkscape -z -e ../icons/Darwin/wsjtx.iconset/icon_256x256 at 2x.png -w 512 -h 512 wsjtx_globe_1024x1024.svg
+inkscape -z -e ../icons/Darwin/wsjtx.iconset/icon_512x512.png -w 512 -h 512 wsjtx_globe_1024x1024.svg
+inkscape -z -e ../icons/Darwin/wsjtx.iconset/icon_512x512 at 2x.png -w 1024 -h 1024 wsjtx_globe_1024x1024.svg
+identify -format '%f %p/%n %m %C/%Q %r %G %A %z\n' ../icons/Darwin/wsjtx.iconset/*
+# generic globe iconset for utilities
+mkdir -p ../icons/Darwin/wsjt.iconset
+inkscape -z -e ../icons/Darwin/wsjt.iconset/icon_16x16.png -w 16 -h 16 wsjt_globe_128x128.svg
+inkscape -z -e ../icons/Darwin/wsjt.iconset/icon_16x16 at 2x.png -w 32 -h 32 wsjt_globe_128x128.svg
+inkscape -z -e ../icons/Darwin/wsjt.iconset/icon_32x32.png -w 32 -h 32 wsjt_globe_128x128.svg
+inkscape -z -e ../icons/Darwin/wsjt.iconset/icon_32x32 at 2x.png -w 64 -h 64 wsjt_globe_128x128.svg
+inkscape -z -e ../icons/Darwin/wsjt.iconset/icon_128x128.png -w 128 -h 128 wsjt_globe_1024x1024.svg
+inkscape -z -e ../icons/Darwin/wsjt.iconset/icon_128x128 at 2x.png -w 256 -h 256 wsjt_globe_1024x1024.svg
+inkscape -z -e ../icons/Darwin/wsjt.iconset/icon_256x256.png -w 256 -h 256 wsjt_globe_1024x1024.svg
+inkscape -z -e ../icons/Darwin/wsjt.iconset/icon_256x256 at 2x.png -w 512 -h 512 wsjt_globe_1024x1024.svg
+inkscape -z -e ../icons/Darwin/wsjt.iconset/icon_512x512.png -w 512 -h 512 wsjt_globe_1024x1024.svg
+inkscape -z -e ../icons/Darwin/wsjt.iconset/icon_512x512 at 2x.png -w 1024 -h 1024 wsjt_globe_1024x1024.svg
+identify -format '%f %p/%n %m %C/%Q %r %G %A %z\n' ../icons/Darwin/wsjt.iconset/*
+#
+inkscape -z -e "../icons/Darwin/DragNDrop Background.png" -w 640 -h 480 -b white "DragNDrop Background.svg"
+identify -format '%f %p/%n %m %C/%Q %r %G %A %z\n' "../icons/Darwin/DragNDrop Background.png"
+
+#
+# KDE & Gnome
+#
+inkscape -z -e ../icons/Unix/wsjtx_icon.png -w 128 -h 128 wsjtx_globe_1024x1024.svg
+identify -format '%f %p/%n %m %C/%Q %r %G %A %z\n' ../icons/Unix/wsjtx_icon.png
diff --git a/artwork/wsjt_globe_1024x1024.svg b/artwork/wsjt_globe_1024x1024.svg
new file mode 100644
index 0000000..c9c155a
--- /dev/null
+++ b/artwork/wsjt_globe_1024x1024.svg
@@ -0,0 +1,577 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   inkscape:export-ydpi="90"
+   inkscape:export-xdpi="90"
+   inkscape:export-filename="/home/bill/Dropbox/src/wsjtx-dev/icons/windows-icons/icon_1024x1024.png"
+   version="1.1"
+   width="1024"
+   sodipodi:version="0.32"
+   sodipodi:docname="wsjtx_globe_1024x1024.svg"
+   inkscape:version="0.48.4 r9939"
+   id="svg1432"
+   height="1024">
+  <sodipodi:namedview
+     bordercolor="#666666"
+     borderopacity="1.0"
+     id="base"
+     inkscape:current-layer="svg1432"
+     inkscape:cx="512"
+     inkscape:cy="512"
+     inkscape:guide-bbox="true"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-height="858"
+     inkscape:window-width="1114"
+     inkscape:window-x="72"
+     inkscape:window-y="31"
+     inkscape:zoom="0.69433594"
+     pagecolor="#ffffff"
+     showborder="true"
+     showguides="true"
+     showgrid="false"
+     inkscape:window-maximized="0"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0"
+     inkscape:showpageshadow="false" />
+  <metadata
+     id="metadata3060">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:title></dc:title>
+        <dc:description>Simple globe centered on North America</dc:description>
+        <dc:subject>
+          <rdf:Bag>
+            <rdf:li>earth globe northamerica</rdf:li>
+          </rdf:Bag>
+        </dc:subject>
+        <dc:publisher>
+          <cc:Agent
+             rdf:about="http://www.openclipart.org/">
+            <dc:title>Open Clip Art Library</dc:title>
+          </cc:Agent>
+        </dc:publisher>
+        <dc:creator>
+          <cc:Agent>
+            <dc:title>Dan Gerhrads</dc:title>
+          </cc:Agent>
+        </dc:creator>
+        <dc:rights>
+          <cc:Agent>
+            <dc:title>Dan Gerhrads</dc:title>
+          </cc:Agent>
+        </dc:rights>
+        <dc:date>May 1, 2005</dc:date>
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <cc:license
+           rdf:resource="http://web.resource.org/cc/PublicDomain" />
+        <dc:language>en</dc:language>
+      </cc:Work>
+      <cc:License
+         rdf:about="http://web.resource.org/cc/PublicDomain">
+        <cc:permits
+           rdf:resource="http://web.resource.org/cc/Reproduction" />
+        <cc:permits
+           rdf:resource="http://web.resource.org/cc/Distribution" />
+        <cc:permits
+           rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
+      </cc:License>
+    </rdf:RDF>
+  </metadata>
+  <defs
+     id="defs1759">
+    <linearGradient
+       id="linearGradient37658">
+      <stop
+         style="stop-color:#2f7aff;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop37660" />
+      <stop
+         style="stop-color:#0000b3;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop37662" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient20137">
+      <stop
+         style="stop-color:#00bf00;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop20139" />
+      <stop
+         style="stop-color:#007500;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop20141" />
+    </linearGradient>
+    <radialGradient
+       xlink:href="#linearGradient20137"
+       r="188.61865"
+       inkscape:collect="always"
+       id="radialGradient20143"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.893959,1.11862)"
+       fy="298.37747"
+       fx="205.17723"
+       cy="297.1124"
+       cx="202.06305" />
+    <radialGradient
+       xlink:href="#linearGradient37658"
+       r="112.3373"
+       inkscape:collect="always"
+       id="radialGradient37664"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.806632,1.239722)"
+       fy="270.08731"
+       fx="221.61394"
+       cy="270.08731"
+       cx="221.61394" />
+    <radialGradient
+       xlink:href="#linearGradient20137"
+       r="188.61865"
+       inkscape:collect="always"
+       id="radialGradient1902"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.893959,1.11862)"
+       fy="298.37747"
+       fx="205.17723"
+       cy="297.1124"
+       cx="202.06305" />
+    <radialGradient
+       xlink:href="#linearGradient20137"
+       r="188.61865"
+       inkscape:collect="always"
+       id="radialGradient1904"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.893959,1.11862)"
+       fy="298.37747"
+       fx="205.17723"
+       cy="297.1124"
+       cx="202.06305" />
+    <radialGradient
+       xlink:href="#linearGradient20137"
+       r="188.61865"
+       inkscape:collect="always"
+       id="radialGradient1906"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.893959,1.11862)"
+       fy="298.37747"
+       fx="205.17723"
+       cy="297.1124"
+       cx="202.06305" />
+    <radialGradient
+       xlink:href="#linearGradient20137"
+       r="188.61865"
+       inkscape:collect="always"
+       id="radialGradient1908"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.893959,1.11862)"
+       fy="298.37747"
+       fx="205.17723"
+       cy="297.1124"
+       cx="202.06305" />
+    <radialGradient
+       xlink:href="#linearGradient20137"
+       r="188.61865"
+       inkscape:collect="always"
+       id="radialGradient1910"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.893959,1.11862)"
+       fy="298.37747"
+       fx="205.17723"
+       cy="297.1124"
+       cx="202.06305" />
+    <radialGradient
+       xlink:href="#linearGradient20137"
+       r="188.61865"
+       inkscape:collect="always"
+       id="radialGradient1912"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.893959,1.11862)"
+       fy="298.37747"
+       fx="205.17723"
+       cy="297.1124"
+       cx="202.06305" />
+    <radialGradient
+       xlink:href="#linearGradient20137"
+       r="188.61865"
+       inkscape:collect="always"
+       id="radialGradient1914"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.893959,1.11862)"
+       fy="298.37747"
+       fx="205.17723"
+       cy="297.1124"
+       cx="202.06305" />
+    <radialGradient
+       xlink:href="#linearGradient20137"
+       r="188.61865"
+       inkscape:collect="always"
+       id="radialGradient1916"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.893959,1.11862)"
+       fy="298.37747"
+       fx="205.17723"
+       cy="297.1124"
+       cx="202.06305" />
+    <radialGradient
+       xlink:href="#linearGradient20137"
+       r="188.61865"
+       inkscape:collect="always"
+       id="radialGradient1918"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.893959,1.11862)"
+       fy="298.37747"
+       fx="205.17723"
+       cy="297.1124"
+       cx="202.06305" />
+    <radialGradient
+       xlink:href="#linearGradient20137"
+       r="188.61865"
+       inkscape:collect="always"
+       id="radialGradient1920"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.893959,1.11862)"
+       fy="298.37747"
+       fx="205.17723"
+       cy="297.1124"
+       cx="202.06305" />
+    <radialGradient
+       xlink:href="#linearGradient37658-427"
+       r="112.3373"
+       inkscape:collect="always"
+       id="radialGradient37664-403"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.806632,1.239722)"
+       fy="270.08731"
+       fx="221.61394"
+       cy="270.08731"
+       cx="221.61394" />
+    <linearGradient
+       id="linearGradient37658-427">
+      <stop
+         style="stop-color:#488afe;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop7178" />
+      <stop
+         style="stop-color:#0000cc;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop7180" />
+    </linearGradient>
+    <radialGradient
+       xlink:href="#linearGradient20137-396"
+       r="188.61865"
+       inkscape:collect="always"
+       id="radialGradient1902-893"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.893959,1.11862)"
+       fy="298.37747"
+       fx="205.17723"
+       cy="297.1124"
+       cx="202.06305" />
+    <linearGradient
+       id="linearGradient20137-396">
+      <stop
+         style="stop-color:#00d800;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop7184" />
+      <stop
+         style="stop-color:#008e00;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop7186" />
+    </linearGradient>
+    <radialGradient
+       xlink:href="#linearGradient20137-527"
+       r="188.61865"
+       inkscape:collect="always"
+       id="radialGradient1904-666"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.893959,1.11862)"
+       fy="298.37747"
+       fx="205.17723"
+       cy="297.1124"
+       cx="202.06305" />
+    <linearGradient
+       id="linearGradient20137-527">
+      <stop
+         style="stop-color:#00d800;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop7190" />
+      <stop
+         style="stop-color:#008e00;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop7192" />
+    </linearGradient>
+    <radialGradient
+       xlink:href="#linearGradient20137-774"
+       r="188.61865"
+       inkscape:collect="always"
+       id="radialGradient1906-717"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.893959,1.11862)"
+       fy="298.37747"
+       fx="205.17723"
+       cy="297.1124"
+       cx="202.06305" />
+    <linearGradient
+       id="linearGradient20137-774">
+      <stop
+         style="stop-color:#00d800;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop7196" />
+      <stop
+         style="stop-color:#008e00;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop7198" />
+    </linearGradient>
+    <radialGradient
+       xlink:href="#linearGradient20137-253"
+       r="188.61865"
+       inkscape:collect="always"
+       id="radialGradient1908-922"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.893959,1.11862)"
+       fy="298.37747"
+       fx="205.17723"
+       cy="297.1124"
+       cx="202.06305" />
+    <linearGradient
+       id="linearGradient20137-253">
+      <stop
+         style="stop-color:#00d800;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop7202" />
+      <stop
+         style="stop-color:#008e00;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop7204" />
+    </linearGradient>
+    <radialGradient
+       xlink:href="#linearGradient20137-972"
+       r="188.61865"
+       inkscape:collect="always"
+       id="radialGradient1910-261"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.893959,1.11862)"
+       fy="298.37747"
+       fx="205.17723"
+       cy="297.1124"
+       cx="202.06305" />
+    <linearGradient
+       id="linearGradient20137-972">
+      <stop
+         style="stop-color:#00d800;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop7208" />
+      <stop
+         style="stop-color:#008e00;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop7210" />
+    </linearGradient>
+    <radialGradient
+       xlink:href="#linearGradient20137-945"
+       r="188.61865"
+       inkscape:collect="always"
+       id="radialGradient1912-713"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.893959,1.11862)"
+       fy="298.37747"
+       fx="205.17723"
+       cy="297.1124"
+       cx="202.06305" />
+    <linearGradient
+       id="linearGradient20137-945">
+      <stop
+         style="stop-color:#00d800;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop7214" />
+      <stop
+         style="stop-color:#008e00;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop7216" />
+    </linearGradient>
+    <radialGradient
+       xlink:href="#linearGradient20137-600"
+       r="188.61865"
+       inkscape:collect="always"
+       id="radialGradient1914-146"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.893959,1.11862)"
+       fy="298.37747"
+       fx="205.17723"
+       cy="297.1124"
+       cx="202.06305" />
+    <linearGradient
+       id="linearGradient20137-600">
+      <stop
+         style="stop-color:#00d800;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop7220" />
+      <stop
+         style="stop-color:#008e00;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop7222" />
+    </linearGradient>
+    <radialGradient
+       xlink:href="#linearGradient20137-196"
+       r="188.61865"
+       inkscape:collect="always"
+       id="radialGradient1916-817"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.893959,1.11862)"
+       fy="298.37747"
+       fx="205.17723"
+       cy="297.1124"
+       cx="202.06305" />
+    <linearGradient
+       id="linearGradient20137-196">
+      <stop
+         style="stop-color:#00d800;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop7226" />
+      <stop
+         style="stop-color:#008e00;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop7228" />
+    </linearGradient>
+    <radialGradient
+       xlink:href="#linearGradient20137-388"
+       r="188.61865"
+       inkscape:collect="always"
+       id="radialGradient1918-23"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.893959,1.11862)"
+       fy="298.37747"
+       fx="205.17723"
+       cy="297.1124"
+       cx="202.06305" />
+    <linearGradient
+       id="linearGradient20137-388">
+      <stop
+         style="stop-color:#00d800;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop7232" />
+      <stop
+         style="stop-color:#008e00;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop7234" />
+    </linearGradient>
+    <radialGradient
+       xlink:href="#linearGradient20137-202"
+       r="188.61865"
+       inkscape:collect="always"
+       id="radialGradient1920-260"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.893959,1.11862)"
+       fy="298.37747"
+       fx="205.17723"
+       cy="297.1124"
+       cx="202.06305" />
+    <linearGradient
+       id="linearGradient20137-202">
+      <stop
+         style="stop-color:#00d800;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop7238" />
+      <stop
+         style="stop-color:#008e00;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop7240" />
+    </linearGradient>
+    <radialGradient
+       xlink:href="#linearGradient20137-151"
+       r="188.61865"
+       inkscape:collect="always"
+       id="radialGradient20143-884"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.893959,1.11862)"
+       fy="298.37747"
+       fx="205.17723"
+       cy="297.1124"
+       cx="202.06305" />
+    <linearGradient
+       id="linearGradient20137-151">
+      <stop
+         style="stop-color:#00d800;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop7244" />
+      <stop
+         style="stop-color:#008e00;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop7246" />
+    </linearGradient>
+  </defs>
+  <desc
+     id="desc1434">wmf2svg</desc>
+  <polyline
+     transform="matrix(2.2285926,-3.5745108,2.3232002,1.4484387,-677.00545,692.67468)"
+     style="fill:url(#radialGradient37664-403);fill-opacity:1;stroke:#0c0c0c;stroke-width:0.6875;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4"
+     points="103.191467,409.292114   100.730545,403.134064 98.525299,396.927094 96.543777,390.573547 94.785973,384.171082   93.219925,377.622009 91.909569,371.072968 90.790962,364.426147 89.928040,357.779327   89.256882,351.083649 88.777481,344.387970 88.521805,337.692261 88.489838,330.947693   88.681602,324.300873 89.033165,317.605194 89.640404,311.007263 90.407448,304.458221   91.398209,298.006897 92.580727,291.604431 93.986977,285.299744 95.553017,279.092804   97.342781,272.983582 99. [...]
+     id="polyline1560" />
+  <g
+     transform="matrix(4.1610916,0,0,4.1610916,-268.34786,-716.6628)"
+     style="fill:url(#radialGradient1902-893);fill-opacity:1;fill-rule:evenodd"
+     inkscape:label="Continents"
+     id="Continents">
+    <polyline
+       transform="matrix(0.535579,-0.859032,0.558315,0.348091,-98.20917,338.6942)"
+       style="fill:url(#radialGradient1904-666);stroke:#0c0c0c;stroke-width:0.444585;stroke-linecap:round;stroke-linejoin:round"
+       points="132.818436,384.610931   131.827682,384.953064 128.184235,388.227600 126.074867,388.667450 123.422180,385.441803   120.417938,385.832794 117.126053,389.107300 116.838409,393.896912 116.902328,400.641479   115.655891,409.292114 114.409447,415.352448 115.432167,418.235992 113.578484,420.386444   111.053642,420.924042 109.903076,422.732361 109.871117,423.172241 116.295090,433.728943   123.262383,443.161530 130.836914,451.421204 140.904327,460.071808 151.195465,466.425385   153 [...]
+       id="polyline1460" />
+    <polyline
+       transform="matrix(0.535579,-0.859032,0.558315,0.348091,-98.20917,338.6942)"
+       style="fill:url(#radialGradient1906-717);stroke:#0c0c0c;stroke-width:0.444585;stroke-linecap:round;stroke-linejoin:round"
+       points="144.579727,355.237885   146.497345,357.241699 147.583984,362.324585 148.638672,368.384918 149.980988,372.539154   150.364502,377.035553 148.798477,377.279877 146.753021,373.467743 146.976746,368.433777   146.593216,362.959930 144.579727,355.237885 "
+       id="polyline1464" />
+    <polyline
+       transform="matrix(0.535579,-0.859032,0.558315,0.348091,-98.20917,338.6942)"
+       style="fill:url(#radialGradient1908-922);stroke:#0c0c0c;stroke-width:0.444585;stroke-linecap:round;stroke-linejoin:round"
+       points="150.108826,378.892731   148.830429,379.870209 149.309830,383.584595 150.172745,386.614777 152.633667,390.964508   152.505829,386.565887 153.336792,386.077148 153.017197,383.780090 150.108826,378.892731 "
+       id="polyline1468" />
+    <polyline
+       transform="matrix(0.535579,-0.859032,0.558315,0.348091,-98.20917,338.6942)"
+       style="fill:url(#radialGradient1910-261);stroke:#0c0c0c;stroke-width:0.444585;stroke-linecap:round;stroke-linejoin:round"
+       points="201.181000,353.820557   200.797470,356.459747 200.413956,361.053864 199.966507,365.990082 199.007706,368.238281   196.866379,363.204285 197.921066,357.681580 199.103592,354.895782 201.181000,353.820557 "
+       id="polyline1472" />
+    <polyline
+       transform="matrix(0.535579,-0.859032,0.558315,0.348091,-98.20917,338.6942)"
+       style="fill:url(#radialGradient1912-713);stroke:#0c0c0c;stroke-width:0.444585;stroke-linecap:round;stroke-linejoin:round"
+       points="204.632675,320.342133   203.993469,316.774353 202.906830,312.668976 206.230682,314.575043 208.883362,312.277985   209.842163,309.052338 208.915314,303.822876 208.563766,299.961853 209.874130,294.487976   212.430923,295.514343 213.261887,299.570862 213.581497,305.386810 213.837173,310.958405   212.111328,314.917175 211.951538,317.018738 212.335052,321.466217 210.800964,325.913727   208.691605,325.376099 206.454407,326.646820 205.016205,324.203125 204.632675,320.342133 "
+       id="polyline1476" />
+    <polyline
+       transform="matrix(0.535579,-0.859032,0.558315,0.348091,-98.20917,338.6942)"
+       style="fill:url(#radialGradient1914-146);stroke:#0c0c0c;stroke-width:0.444585;stroke-linecap:round;stroke-linejoin:round"
+       points="213.773254,334.955322   213.709335,340.820160 213.869125,343.263885 216.362015,346.636139 219.526062,350.594910   218.695099,344.632324 219.685867,341.406677 222.722061,339.060730 227.835663,334.662109   230.648163,335.786194 233.332809,333.147003 234.355515,326.011475 234.675125,319.218048   233.556534,312.522369 233.588486,306.071045 231.511078,300.646057 228.890350,297.420410   226.365509,296.980560 225.246902,294.830109 226.365509,293.461639 225.023193,290.235992   222 [...]
+       id="polyline1480" />
+    <polyline
+       transform="matrix(0.535579,-0.859032,0.558315,0.348091,-98.20917,338.6942)"
+       style="fill:url(#radialGradient1916-817);stroke:#0c0c0c;stroke-width:0.444585;stroke-linecap:round;stroke-linejoin:round"
+       points="232.533813,338.767487   230.200729,341.748779 229.401718,344.436798 229.721313,347.662476 233.460648,348.542206   237.040161,346.929382 237.231934,342.872864 235.378250,340.478088 233.620453,340.282562   232.533813,338.767487 "
+       id="polyline1484" />
+    <polyline
+       transform="matrix(0.535579,-0.859032,0.558315,0.348091,-98.20917,338.6942)"
+       style="fill:url(#radialGradient1918-23);stroke:#0c0c0c;stroke-width:0.444585;stroke-linecap:round;stroke-linejoin:round"
+       points="264.877380,375.813690   262.991730,379.919098 260.371002,382.167236 258.645172,385.148529 258.645172,389.693817   256.887360,391.062256 255.161514,388.911804 254.522308,386.956848 252.732559,385.197418   253.339798,391.697632 251.709839,392.332977 249.792236,387.738861 248.322067,389.840393   246.724060,393.017212 244.327072,395.412018 242.952774,399.664001 241.514587,403.329529   241.067139,407.337158 239.565018,407.190552 238.318573,407.777039 235.665894,409.096649   233 [...]
+       id="polyline1488" />
+    <polyline
+       transform="matrix(0.535579,-0.859032,0.558315,0.348091,-98.20917,338.6942)"
+       style="fill:url(#radialGradient1920-260);stroke:#0c0c0c;stroke-width:0.444585;stroke-linecap:round;stroke-linejoin:round"
+       points="244.774506,357.779327   243.304337,356.313110 242.345535,358.512421 241.131058,362.666687 239.916580,364.817108   238.062897,367.945038 237.615448,372.930145 238.414459,375.324951 239.373245,373.125641   239.852661,368.727020 240.683624,367.602905 241.067139,371.121826 241.290848,375.129456   241.834183,378.452850 243.336304,376.986664 243.528061,376.937775 243.719818,376.888916   243.911591,376.791168 244.071396,376.644531 244.390976,376.351288 244.678635,376.009186   244 [...]
+       id="polyline1492" />
+    <polyline
+       transform="matrix(0.535579,-0.859032,0.558315,0.348091,-98.20917,338.6942)"
+       style="fill:url(#radialGradient20143-884);stroke:#0c0c0c;stroke-width:0.444585;stroke-linecap:round;stroke-linejoin:round"
+       points="262.192749,389.449432   260.115326,391.160004 258.261658,394.287933 256.663635,394.532288 255.992477,392.968323   255.065643,395.802979 253.851151,400.885864 250.783005,404.209290 250.175766,401.276855   249.344803,399.810638 245.573502,402.889679 242.537292,406.213104 240.747543,406.995056   238.126801,409.878601 236.049423,409.976349 233.748291,411.002716 231.606964,415.010315   228.986237,420.826294 226.333542,423.123352 220.996231,428.059601 216.617691,433.680054   213 [...]
+       id="polyline1496" />
+  </g>
+</svg>
diff --git a/artwork/wsjt_globe_128x128.svg b/artwork/wsjt_globe_128x128.svg
new file mode 100644
index 0000000..6503243
--- /dev/null
+++ b/artwork/wsjt_globe_128x128.svg
@@ -0,0 +1,839 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   height="128"
+   id="svg1432"
+   inkscape:version="0.48.4 r9939"
+   sodipodi:docname="wsjtx_globe_128x128.svg"
+   sodipodi:version="0.32"
+   width="128"
+   version="1.1">
+  <sodipodi:namedview
+     bordercolor="#666666"
+     borderopacity="1.0"
+     id="base"
+     inkscape:current-layer="svg1432"
+     inkscape:cx="64"
+     inkscape:cy="64"
+     inkscape:guide-bbox="true"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:window-height="1027"
+     inkscape:window-width="1846"
+     inkscape:window-x="72"
+     inkscape:window-y="24"
+     inkscape:zoom="6.875"
+     pagecolor="#ffffff"
+     showborder="false"
+     showguides="true"
+     showgrid="false"
+     inkscape:window-maximized="0"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0"
+     inkscape:showpageshadow="false"
+     inkscape:snap-from-guide="true" />
+  <metadata
+     id="metadata3060">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:title />
+        <dc:description>Simple globe centered on North America</dc:description>
+        <dc:subject>
+          <rdf:Bag>
+            <rdf:li>earth globe northamerica</rdf:li>
+          </rdf:Bag>
+        </dc:subject>
+        <dc:publisher>
+          <cc:Agent
+             rdf:about="http://www.openclipart.org/">
+            <dc:title>Open Clip Art Library</dc:title>
+          </cc:Agent>
+        </dc:publisher>
+        <dc:creator>
+          <cc:Agent>
+            <dc:title>Dan Gerhrads</dc:title>
+          </cc:Agent>
+        </dc:creator>
+        <dc:rights>
+          <cc:Agent>
+            <dc:title>Dan Gerhrads</dc:title>
+          </cc:Agent>
+        </dc:rights>
+        <dc:date>May 1, 2005</dc:date>
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <cc:license
+           rdf:resource="http://web.resource.org/cc/PublicDomain" />
+        <dc:language>en</dc:language>
+      </cc:Work>
+      <cc:License
+         rdf:about="http://web.resource.org/cc/PublicDomain">
+        <cc:permits
+           rdf:resource="http://web.resource.org/cc/Reproduction" />
+        <cc:permits
+           rdf:resource="http://web.resource.org/cc/Distribution" />
+        <cc:permits
+           rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
+      </cc:License>
+    </rdf:RDF>
+  </metadata>
+  <defs
+     id="defs1759">
+    <linearGradient
+       id="linearGradient37658">
+      <stop
+         id="stop37660"
+         offset="0.0000000"
+         style="stop-color:#619afe;stop-opacity:1.0000000;" />
+      <stop
+         id="stop37662"
+         offset="1.0000000"
+         style="stop-color:#0000e5;stop-opacity:1.0000000;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient20137">
+      <stop
+         id="stop20139"
+         offset="0.0000000"
+         style="stop-color:#00f100;stop-opacity:1.0000000;" />
+      <stop
+         id="stop20141"
+         offset="1.0000000"
+         style="stop-color:#00a700;stop-opacity:1.0000000;" />
+    </linearGradient>
+    <radialGradient
+       cx="202.06305"
+       cy="297.1124"
+       fx="205.17723"
+       fy="298.37747"
+       gradientTransform="scale(0.893959,1.11862)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient20143"
+       inkscape:collect="always"
+       r="188.61865"
+       xlink:href="#linearGradient20137" />
+    <radialGradient
+       cx="221.61394"
+       cy="270.08731"
+       fx="221.61394"
+       fy="270.08731"
+       gradientTransform="scale(0.806632,1.239722)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient37664"
+       inkscape:collect="always"
+       r="112.3373"
+       xlink:href="#linearGradient37658" />
+    <radialGradient
+       cx="202.06305"
+       cy="297.1124"
+       fx="205.17723"
+       fy="298.37747"
+       gradientTransform="scale(0.893959,1.11862)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient1902"
+       inkscape:collect="always"
+       r="188.61865"
+       xlink:href="#linearGradient20137" />
+    <radialGradient
+       cx="202.06305"
+       cy="297.1124"
+       fx="205.17723"
+       fy="298.37747"
+       gradientTransform="scale(0.893959,1.11862)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient1904"
+       inkscape:collect="always"
+       r="188.61865"
+       xlink:href="#linearGradient20137" />
+    <radialGradient
+       cx="202.06305"
+       cy="297.1124"
+       fx="205.17723"
+       fy="298.37747"
+       gradientTransform="scale(0.893959,1.11862)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient1906"
+       inkscape:collect="always"
+       r="188.61865"
+       xlink:href="#linearGradient20137" />
+    <radialGradient
+       cx="202.06305"
+       cy="297.1124"
+       fx="205.17723"
+       fy="298.37747"
+       gradientTransform="scale(0.893959,1.11862)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient1908"
+       inkscape:collect="always"
+       r="188.61865"
+       xlink:href="#linearGradient20137" />
+    <radialGradient
+       cx="202.06305"
+       cy="297.1124"
+       fx="205.17723"
+       fy="298.37747"
+       gradientTransform="scale(0.893959,1.11862)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient1910"
+       inkscape:collect="always"
+       r="188.61865"
+       xlink:href="#linearGradient20137" />
+    <radialGradient
+       cx="202.06305"
+       cy="297.1124"
+       fx="205.17723"
+       fy="298.37747"
+       gradientTransform="scale(0.893959,1.11862)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient1912"
+       inkscape:collect="always"
+       r="188.61865"
+       xlink:href="#linearGradient20137" />
+    <radialGradient
+       cx="202.06305"
+       cy="297.1124"
+       fx="205.17723"
+       fy="298.37747"
+       gradientTransform="scale(0.893959,1.11862)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient1914"
+       inkscape:collect="always"
+       r="188.61865"
+       xlink:href="#linearGradient20137" />
+    <radialGradient
+       cx="202.06305"
+       cy="297.1124"
+       fx="205.17723"
+       fy="298.37747"
+       gradientTransform="scale(0.893959,1.11862)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient1916"
+       inkscape:collect="always"
+       r="188.61865"
+       xlink:href="#linearGradient20137" />
+    <radialGradient
+       cx="202.06305"
+       cy="297.1124"
+       fx="205.17723"
+       fy="298.37747"
+       gradientTransform="scale(0.893959,1.11862)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient1918"
+       inkscape:collect="always"
+       r="188.61865"
+       xlink:href="#linearGradient20137" />
+    <radialGradient
+       cx="202.06305"
+       cy="297.1124"
+       fx="205.17723"
+       fy="298.37747"
+       gradientTransform="scale(0.893959,1.11862)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient1920"
+       inkscape:collect="always"
+       r="188.61865"
+       xlink:href="#linearGradient20137" />
+    <radialGradient
+       cx="221.61394"
+       cy="270.08731"
+       fx="221.61394"
+       fy="270.08731"
+       gradientTransform="scale(0.806632,1.239722)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient37664-284"
+       inkscape:collect="always"
+       r="112.3373"
+       xlink:href="#linearGradient37658-332" />
+    <linearGradient
+       id="linearGradient37658-332">
+      <stop
+         id="stop8375"
+         offset="0.0000000"
+         style="stop-color:#7aaafe;stop-opacity:1.0000000;" />
+      <stop
+         id="stop8377"
+         offset="1.0000000"
+         style="stop-color:#0000fe;stop-opacity:1.0000000;" />
+    </linearGradient>
+    <radialGradient
+       cx="202.06305"
+       cy="297.1124"
+       fx="205.17723"
+       fy="298.37747"
+       gradientTransform="scale(0.893959,1.11862)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient1902-108"
+       inkscape:collect="always"
+       r="188.61865"
+       xlink:href="#linearGradient20137-970" />
+    <linearGradient
+       id="linearGradient20137-970">
+      <stop
+         id="stop8381"
+         offset="0.0000000"
+         style="stop-color:#0bfe0b;stop-opacity:1.0000000;" />
+      <stop
+         id="stop8383"
+         offset="1.0000000"
+         style="stop-color:#00c000;stop-opacity:1.0000000;" />
+    </linearGradient>
+    <radialGradient
+       cx="202.06305"
+       cy="297.1124"
+       fx="205.17723"
+       fy="298.37747"
+       gradientTransform="scale(0.893959,1.11862)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient1904-972"
+       inkscape:collect="always"
+       r="188.61865"
+       xlink:href="#linearGradient20137-24" />
+    <linearGradient
+       id="linearGradient20137-24">
+      <stop
+         id="stop8387"
+         offset="0.0000000"
+         style="stop-color:#0bfe0b;stop-opacity:1.0000000;" />
+      <stop
+         id="stop8389"
+         offset="1.0000000"
+         style="stop-color:#00c000;stop-opacity:1.0000000;" />
+    </linearGradient>
+    <radialGradient
+       cx="202.06305"
+       cy="297.1124"
+       fx="205.17723"
+       fy="298.37747"
+       gradientTransform="scale(0.893959,1.11862)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient1906-828"
+       inkscape:collect="always"
+       r="188.61865"
+       xlink:href="#linearGradient20137-376" />
+    <linearGradient
+       id="linearGradient20137-376">
+      <stop
+         id="stop8393"
+         offset="0.0000000"
+         style="stop-color:#0bfe0b;stop-opacity:1.0000000;" />
+      <stop
+         id="stop8395"
+         offset="1.0000000"
+         style="stop-color:#00c000;stop-opacity:1.0000000;" />
+    </linearGradient>
+    <radialGradient
+       cx="202.06305"
+       cy="297.1124"
+       fx="205.17723"
+       fy="298.37747"
+       gradientTransform="scale(0.893959,1.11862)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient1908-502"
+       inkscape:collect="always"
+       r="188.61865"
+       xlink:href="#linearGradient20137-289" />
+    <linearGradient
+       id="linearGradient20137-289">
+      <stop
+         id="stop8399"
+         offset="0.0000000"
+         style="stop-color:#0bfe0b;stop-opacity:1.0000000;" />
+      <stop
+         id="stop8401"
+         offset="1.0000000"
+         style="stop-color:#00c000;stop-opacity:1.0000000;" />
+    </linearGradient>
+    <radialGradient
+       cx="202.06305"
+       cy="297.1124"
+       fx="205.17723"
+       fy="298.37747"
+       gradientTransform="scale(0.893959,1.11862)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient1910-187"
+       inkscape:collect="always"
+       r="188.61865"
+       xlink:href="#linearGradient20137-879" />
+    <linearGradient
+       id="linearGradient20137-879">
+      <stop
+         id="stop8405"
+         offset="0.0000000"
+         style="stop-color:#0bfe0b;stop-opacity:1.0000000;" />
+      <stop
+         id="stop8407"
+         offset="1.0000000"
+         style="stop-color:#00c000;stop-opacity:1.0000000;" />
+    </linearGradient>
+    <radialGradient
+       cx="202.06305"
+       cy="297.1124"
+       fx="205.17723"
+       fy="298.37747"
+       gradientTransform="scale(0.893959,1.11862)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient1912-38"
+       inkscape:collect="always"
+       r="188.61865"
+       xlink:href="#linearGradient20137-891" />
+    <linearGradient
+       id="linearGradient20137-891">
+      <stop
+         id="stop8411"
+         offset="0.0000000"
+         style="stop-color:#0bfe0b;stop-opacity:1.0000000;" />
+      <stop
+         id="stop8413"
+         offset="1.0000000"
+         style="stop-color:#00c000;stop-opacity:1.0000000;" />
+    </linearGradient>
+    <radialGradient
+       cx="202.06305"
+       cy="297.1124"
+       fx="205.17723"
+       fy="298.37747"
+       gradientTransform="scale(0.893959,1.11862)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient1914-119"
+       inkscape:collect="always"
+       r="188.61865"
+       xlink:href="#linearGradient20137-529" />
+    <linearGradient
+       id="linearGradient20137-529">
+      <stop
+         id="stop8417"
+         offset="0.0000000"
+         style="stop-color:#0bfe0b;stop-opacity:1.0000000;" />
+      <stop
+         id="stop8419"
+         offset="1.0000000"
+         style="stop-color:#00c000;stop-opacity:1.0000000;" />
+    </linearGradient>
+    <radialGradient
+       cx="202.06305"
+       cy="297.1124"
+       fx="205.17723"
+       fy="298.37747"
+       gradientTransform="scale(0.893959,1.11862)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient1916-825"
+       inkscape:collect="always"
+       r="188.61865"
+       xlink:href="#linearGradient20137-469" />
+    <linearGradient
+       id="linearGradient20137-469">
+      <stop
+         id="stop8423"
+         offset="0.0000000"
+         style="stop-color:#0bfe0b;stop-opacity:1.0000000;" />
+      <stop
+         id="stop8425"
+         offset="1.0000000"
+         style="stop-color:#00c000;stop-opacity:1.0000000;" />
+    </linearGradient>
+    <radialGradient
+       cx="202.06305"
+       cy="297.1124"
+       fx="205.17723"
+       fy="298.37747"
+       gradientTransform="scale(0.893959,1.11862)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient1918-387"
+       inkscape:collect="always"
+       r="188.61865"
+       xlink:href="#linearGradient20137-981" />
+    <linearGradient
+       id="linearGradient20137-981">
+      <stop
+         id="stop8429"
+         offset="0.0000000"
+         style="stop-color:#0bfe0b;stop-opacity:1.0000000;" />
+      <stop
+         id="stop8431"
+         offset="1.0000000"
+         style="stop-color:#00c000;stop-opacity:1.0000000;" />
+    </linearGradient>
+    <radialGradient
+       cx="202.06305"
+       cy="297.1124"
+       fx="205.17723"
+       fy="298.37747"
+       gradientTransform="scale(0.893959,1.11862)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient1920-264"
+       inkscape:collect="always"
+       r="188.61865"
+       xlink:href="#linearGradient20137-421" />
+    <linearGradient
+       id="linearGradient20137-421">
+      <stop
+         id="stop8435"
+         offset="0.0000000"
+         style="stop-color:#0bfe0b;stop-opacity:1.0000000;" />
+      <stop
+         id="stop8437"
+         offset="1.0000000"
+         style="stop-color:#00c000;stop-opacity:1.0000000;" />
+    </linearGradient>
+    <radialGradient
+       cx="202.06305"
+       cy="297.1124"
+       fx="205.17723"
+       fy="298.37747"
+       gradientTransform="scale(0.893959,1.11862)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient20143-627"
+       inkscape:collect="always"
+       r="188.61865"
+       xlink:href="#linearGradient20137-58" />
+    <linearGradient
+       id="linearGradient20137-58">
+      <stop
+         id="stop8441"
+         offset="0.0000000"
+         style="stop-color:#0bfe0b;stop-opacity:1.0000000;" />
+      <stop
+         id="stop8443"
+         offset="1.0000000"
+         style="stop-color:#00c000;stop-opacity:1.0000000;" />
+    </linearGradient>
+    <radialGradient
+       cx="221.61394"
+       cy="270.08731"
+       fx="221.61394"
+       fy="270.08731"
+       gradientTransform="scale(0.806632,1.239722)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient37664-284-781"
+       inkscape:collect="always"
+       r="112.3373"
+       xlink:href="#linearGradient37658-332-354" />
+    <linearGradient
+       id="linearGradient37658-332-354">
+      <stop
+         id="stop8612"
+         offset="0.0000000"
+         style="stop-color:#93bafe;stop-opacity:1.0000000;" />
+      <stop
+         id="stop8614"
+         offset="1.0000000"
+         style="stop-color:#1818ff;stop-opacity:1.0000000;" />
+    </linearGradient>
+    <radialGradient
+       cx="202.06305"
+       cy="297.1124"
+       fx="205.17723"
+       fy="298.37747"
+       gradientTransform="scale(0.893959,1.11862)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient1902-108-124"
+       inkscape:collect="always"
+       r="188.61865"
+       xlink:href="#linearGradient20137-970-892" />
+    <linearGradient
+       id="linearGradient20137-970-892">
+      <stop
+         id="stop8618"
+         offset="0.0000000"
+         style="stop-color:#24fe24;stop-opacity:1.0000000;" />
+      <stop
+         id="stop8620"
+         offset="1.0000000"
+         style="stop-color:#00d900;stop-opacity:1.0000000;" />
+    </linearGradient>
+    <radialGradient
+       cx="202.06305"
+       cy="297.1124"
+       fx="205.17723"
+       fy="298.37747"
+       gradientTransform="scale(0.893959,1.11862)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient1904-972-786"
+       inkscape:collect="always"
+       r="188.61865"
+       xlink:href="#linearGradient20137-24-119" />
+    <linearGradient
+       id="linearGradient20137-24-119">
+      <stop
+         id="stop8624"
+         offset="0.0000000"
+         style="stop-color:#24fe24;stop-opacity:1.0000000;" />
+      <stop
+         id="stop8626"
+         offset="1.0000000"
+         style="stop-color:#00d900;stop-opacity:1.0000000;" />
+    </linearGradient>
+    <radialGradient
+       cx="202.06305"
+       cy="297.1124"
+       fx="205.17723"
+       fy="298.37747"
+       gradientTransform="scale(0.893959,1.11862)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient1906-828-861"
+       inkscape:collect="always"
+       r="188.61865"
+       xlink:href="#linearGradient20137-376-597" />
+    <linearGradient
+       id="linearGradient20137-376-597">
+      <stop
+         id="stop8630"
+         offset="0.0000000"
+         style="stop-color:#24fe24;stop-opacity:1.0000000;" />
+      <stop
+         id="stop8632"
+         offset="1.0000000"
+         style="stop-color:#00d900;stop-opacity:1.0000000;" />
+    </linearGradient>
+    <radialGradient
+       cx="202.06305"
+       cy="297.1124"
+       fx="205.17723"
+       fy="298.37747"
+       gradientTransform="scale(0.893959,1.11862)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient1908-502-115"
+       inkscape:collect="always"
+       r="188.61865"
+       xlink:href="#linearGradient20137-289-824" />
+    <linearGradient
+       id="linearGradient20137-289-824">
+      <stop
+         id="stop8636"
+         offset="0.0000000"
+         style="stop-color:#24fe24;stop-opacity:1.0000000;" />
+      <stop
+         id="stop8638"
+         offset="1.0000000"
+         style="stop-color:#00d900;stop-opacity:1.0000000;" />
+    </linearGradient>
+    <radialGradient
+       cx="202.06305"
+       cy="297.1124"
+       fx="205.17723"
+       fy="298.37747"
+       gradientTransform="scale(0.893959,1.11862)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient1910-187-480"
+       inkscape:collect="always"
+       r="188.61865"
+       xlink:href="#linearGradient20137-879-315" />
+    <linearGradient
+       id="linearGradient20137-879-315">
+      <stop
+         id="stop8642"
+         offset="0.0000000"
+         style="stop-color:#24fe24;stop-opacity:1.0000000;" />
+      <stop
+         id="stop8644"
+         offset="1.0000000"
+         style="stop-color:#00d900;stop-opacity:1.0000000;" />
+    </linearGradient>
+    <radialGradient
+       cx="202.06305"
+       cy="297.1124"
+       fx="205.17723"
+       fy="298.37747"
+       gradientTransform="scale(0.893959,1.11862)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient1912-38-980"
+       inkscape:collect="always"
+       r="188.61865"
+       xlink:href="#linearGradient20137-891-460" />
+    <linearGradient
+       id="linearGradient20137-891-460">
+      <stop
+         id="stop8648"
+         offset="0.0000000"
+         style="stop-color:#24fe24;stop-opacity:1.0000000;" />
+      <stop
+         id="stop8650"
+         offset="1.0000000"
+         style="stop-color:#00d900;stop-opacity:1.0000000;" />
+    </linearGradient>
+    <radialGradient
+       cx="202.06305"
+       cy="297.1124"
+       fx="205.17723"
+       fy="298.37747"
+       gradientTransform="scale(0.893959,1.11862)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient1914-119-179"
+       inkscape:collect="always"
+       r="188.61865"
+       xlink:href="#linearGradient20137-529-932" />
+    <linearGradient
+       id="linearGradient20137-529-932">
+      <stop
+         id="stop8654"
+         offset="0.0000000"
+         style="stop-color:#24fe24;stop-opacity:1.0000000;" />
+      <stop
+         id="stop8656"
+         offset="1.0000000"
+         style="stop-color:#00d900;stop-opacity:1.0000000;" />
+    </linearGradient>
+    <radialGradient
+       cx="202.06305"
+       cy="297.1124"
+       fx="205.17723"
+       fy="298.37747"
+       gradientTransform="scale(0.893959,1.11862)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient1916-825-422"
+       inkscape:collect="always"
+       r="188.61865"
+       xlink:href="#linearGradient20137-469-24" />
+    <linearGradient
+       id="linearGradient20137-469-24">
+      <stop
+         id="stop8660"
+         offset="0.0000000"
+         style="stop-color:#24fe24;stop-opacity:1.0000000;" />
+      <stop
+         id="stop8662"
+         offset="1.0000000"
+         style="stop-color:#00d900;stop-opacity:1.0000000;" />
+    </linearGradient>
+    <radialGradient
+       cx="202.06305"
+       cy="297.1124"
+       fx="205.17723"
+       fy="298.37747"
+       gradientTransform="scale(0.893959,1.11862)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient1918-387-755"
+       inkscape:collect="always"
+       r="188.61865"
+       xlink:href="#linearGradient20137-981-521" />
+    <linearGradient
+       id="linearGradient20137-981-521">
+      <stop
+         id="stop8666"
+         offset="0.0000000"
+         style="stop-color:#24fe24;stop-opacity:1.0000000;" />
+      <stop
+         id="stop8668"
+         offset="1.0000000"
+         style="stop-color:#00d900;stop-opacity:1.0000000;" />
+    </linearGradient>
+    <radialGradient
+       cx="202.06305"
+       cy="297.1124"
+       fx="205.17723"
+       fy="298.37747"
+       gradientTransform="scale(0.893959,1.11862)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient1920-264-381"
+       inkscape:collect="always"
+       r="188.61865"
+       xlink:href="#linearGradient20137-421-297" />
+    <linearGradient
+       id="linearGradient20137-421-297">
+      <stop
+         id="stop8672"
+         offset="0.0000000"
+         style="stop-color:#24fe24;stop-opacity:1.0000000;" />
+      <stop
+         id="stop8674"
+         offset="1.0000000"
+         style="stop-color:#00d900;stop-opacity:1.0000000;" />
+    </linearGradient>
+    <radialGradient
+       cx="202.06305"
+       cy="297.1124"
+       fx="205.17723"
+       fy="298.37747"
+       gradientTransform="scale(0.893959,1.11862)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient20143-627-23"
+       inkscape:collect="always"
+       r="188.61865"
+       xlink:href="#linearGradient20137-58-615" />
+    <linearGradient
+       id="linearGradient20137-58-615">
+      <stop
+         id="stop8678"
+         offset="0.0000000"
+         style="stop-color:#24fe24;stop-opacity:1.0000000;" />
+      <stop
+         id="stop8680"
+         offset="1.0000000"
+         style="stop-color:#00d900;stop-opacity:1.0000000;" />
+    </linearGradient>
+  </defs>
+  <desc
+     id="desc1434">wmf2svg</desc>
+  <polyline
+     id="polyline1560"
+     points="103.191467,409.292114   100.730545,403.134064 98.525299,396.927094 96.543777,390.573547 94.785973,384.171082   93.219925,377.622009 91.909569,371.072968 90.790962,364.426147 89.928040,357.779327   89.256882,351.083649 88.777481,344.387970 88.521805,337.692261 88.489838,330.947693   88.681602,324.300873 89.033165,317.605194 89.640404,311.007263 90.407448,304.458221   91.398209,298.006897 92.580727,291.604431 93.986977,285.299744 95.553017,279.092804   97.342781,272.983582 99. [...]
+     style="fill:url(#radialGradient37664-284-781);fill-opacity:1;stroke:#181818;stroke-width:0.6875;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4"
+     transform="matrix(0.3640721,-0.58678257,0.3795276,0.23777199,-128.13162,89.336986)" />
+  <g
+     id="Continents"
+     inkscape:label="Continents"
+     style="fill:url(#radialGradient1902-108-124);fill-opacity:1;fill-rule:evenodd"
+     transform="matrix(0.67977314,0,0,0.68307417,-61.371653,-142.01634)">
+    <polyline
+       id="polyline1460"
+       points="132.818436,384.610931   131.827682,384.953064 128.184235,388.227600 126.074867,388.667450 123.422180,385.441803   120.417938,385.832794 117.126053,389.107300 116.838409,393.896912 116.902328,400.641479   115.655891,409.292114 114.409447,415.352448 115.432167,418.235992 113.578484,420.386444   111.053642,420.924042 109.903076,422.732361 109.871117,423.172241 116.295090,433.728943   123.262383,443.161530 130.836914,451.421204 140.904327,460.071808 151.195465,466.425385   153 [...]
+       style="fill:url(#radialGradient1904-972-786);stroke:#181818;stroke-width:0.444585;stroke-linecap:round;stroke-linejoin:round"
+       transform="matrix(0.535579,-0.859032,0.558315,0.348091,-98.20917,338.6942)" />
+    <polyline
+       id="polyline1464"
+       points="144.579727,355.237885   146.497345,357.241699 147.583984,362.324585 148.638672,368.384918 149.980988,372.539154   150.364502,377.035553 148.798477,377.279877 146.753021,373.467743 146.976746,368.433777   146.593216,362.959930 144.579727,355.237885 "
+       style="fill:url(#radialGradient1906-828-861);stroke:#181818;stroke-width:0.444585;stroke-linecap:round;stroke-linejoin:round"
+       transform="matrix(0.535579,-0.859032,0.558315,0.348091,-98.20917,338.6942)" />
+    <polyline
+       id="polyline1468"
+       points="150.108826,378.892731   148.830429,379.870209 149.309830,383.584595 150.172745,386.614777 152.633667,390.964508   152.505829,386.565887 153.336792,386.077148 153.017197,383.780090 150.108826,378.892731 "
+       style="fill:url(#radialGradient1908-502-115);stroke:#181818;stroke-width:0.444585;stroke-linecap:round;stroke-linejoin:round"
+       transform="matrix(0.535579,-0.859032,0.558315,0.348091,-98.20917,338.6942)" />
+    <polyline
+       id="polyline1472"
+       points="201.181000,353.820557   200.797470,356.459747 200.413956,361.053864 199.966507,365.990082 199.007706,368.238281   196.866379,363.204285 197.921066,357.681580 199.103592,354.895782 201.181000,353.820557 "
+       style="fill:url(#radialGradient1910-187-480);stroke:#181818;stroke-width:0.444585;stroke-linecap:round;stroke-linejoin:round"
+       transform="matrix(0.535579,-0.859032,0.558315,0.348091,-98.20917,338.6942)" />
+    <polyline
+       id="polyline1476"
+       points="204.632675,320.342133   203.993469,316.774353 202.906830,312.668976 206.230682,314.575043 208.883362,312.277985   209.842163,309.052338 208.915314,303.822876 208.563766,299.961853 209.874130,294.487976   212.430923,295.514343 213.261887,299.570862 213.581497,305.386810 213.837173,310.958405   212.111328,314.917175 211.951538,317.018738 212.335052,321.466217 210.800964,325.913727   208.691605,325.376099 206.454407,326.646820 205.016205,324.203125 204.632675,320.342133 "
+       style="fill:url(#radialGradient1912-38-980);stroke:#181818;stroke-width:0.444585;stroke-linecap:round;stroke-linejoin:round"
+       transform="matrix(0.535579,-0.859032,0.558315,0.348091,-98.20917,338.6942)" />
+    <polyline
+       id="polyline1480"
+       points="213.773254,334.955322   213.709335,340.820160 213.869125,343.263885 216.362015,346.636139 219.526062,350.594910   218.695099,344.632324 219.685867,341.406677 222.722061,339.060730 227.835663,334.662109   230.648163,335.786194 233.332809,333.147003 234.355515,326.011475 234.675125,319.218048   233.556534,312.522369 233.588486,306.071045 231.511078,300.646057 228.890350,297.420410   226.365509,296.980560 225.246902,294.830109 226.365509,293.461639 225.023193,290.235992   222 [...]
+       style="fill:url(#radialGradient1914-119-179);stroke:#181818;stroke-width:0.444585;stroke-linecap:round;stroke-linejoin:round"
+       transform="matrix(0.535579,-0.859032,0.558315,0.348091,-98.20917,338.6942)" />
+    <polyline
+       id="polyline1484"
+       points="232.533813,338.767487   230.200729,341.748779 229.401718,344.436798 229.721313,347.662476 233.460648,348.542206   237.040161,346.929382 237.231934,342.872864 235.378250,340.478088 233.620453,340.282562   232.533813,338.767487 "
+       style="fill:url(#radialGradient1916-825-422);stroke:#181818;stroke-width:0.444585;stroke-linecap:round;stroke-linejoin:round"
+       transform="matrix(0.535579,-0.859032,0.558315,0.348091,-98.20917,338.6942)" />
+    <polyline
+       id="polyline1488"
+       points="264.877380,375.813690   262.991730,379.919098 260.371002,382.167236 258.645172,385.148529 258.645172,389.693817   256.887360,391.062256 255.161514,388.911804 254.522308,386.956848 252.732559,385.197418   253.339798,391.697632 251.709839,392.332977 249.792236,387.738861 248.322067,389.840393   246.724060,393.017212 244.327072,395.412018 242.952774,399.664001 241.514587,403.329529   241.067139,407.337158 239.565018,407.190552 238.318573,407.777039 235.665894,409.096649   233 [...]
+       style="fill:url(#radialGradient1918-387-755);stroke:#181818;stroke-width:0.444585;stroke-linecap:round;stroke-linejoin:round"
+       transform="matrix(0.535579,-0.859032,0.558315,0.348091,-98.20917,338.6942)" />
+    <polyline
+       id="polyline1492"
+       points="244.774506,357.779327   243.304337,356.313110 242.345535,358.512421 241.131058,362.666687 239.916580,364.817108   238.062897,367.945038 237.615448,372.930145 238.414459,375.324951 239.373245,373.125641   239.852661,368.727020 240.683624,367.602905 241.067139,371.121826 241.290848,375.129456   241.834183,378.452850 243.336304,376.986664 243.528061,376.937775 243.719818,376.888916   243.911591,376.791168 244.071396,376.644531 244.390976,376.351288 244.678635,376.009186   244 [...]
+       style="fill:url(#radialGradient1920-264-381);stroke:#181818;stroke-width:0.444585;stroke-linecap:round;stroke-linejoin:round"
+       transform="matrix(0.535579,-0.859032,0.558315,0.348091,-98.20917,338.6942)" />
+    <polyline
+       id="polyline1496"
+       points="262.192749,389.449432   260.115326,391.160004 258.261658,394.287933 256.663635,394.532288 255.992477,392.968323   255.065643,395.802979 253.851151,400.885864 250.783005,404.209290 250.175766,401.276855   249.344803,399.810638 245.573502,402.889679 242.537292,406.213104 240.747543,406.995056   238.126801,409.878601 236.049423,409.976349 233.748291,411.002716 231.606964,415.010315   228.986237,420.826294 226.333542,423.123352 220.996231,428.059601 216.617691,433.680054   213 [...]
+       style="fill:url(#radialGradient20143-627-23);stroke:#181818;stroke-width:0.444585;stroke-linecap:round;stroke-linejoin:round"
+       transform="matrix(0.535579,-0.859032,0.558315,0.348091,-98.20917,338.6942)" />
+  </g>
+</svg>
diff --git a/artwork/wsjtx_globe_1024x1024.svg b/artwork/wsjtx_globe_1024x1024.svg
new file mode 100644
index 0000000..e294483
--- /dev/null
+++ b/artwork/wsjtx_globe_1024x1024.svg
@@ -0,0 +1,602 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   inkscape:export-ydpi="90"
+   inkscape:export-xdpi="90"
+   inkscape:export-filename="/home/bill/Dropbox/src/wsjtx-dev/icons/windows-icons/icon_1024x1024.png"
+   version="1.1"
+   width="1024"
+   sodipodi:version="0.32"
+   sodipodi:docname="wsjtx_globe_1024x1024.svg"
+   inkscape:version="0.48.4 r9939"
+   id="svg1432"
+   height="1024">
+  <sodipodi:namedview
+     bordercolor="#666666"
+     borderopacity="1.0"
+     id="base"
+     inkscape:current-layer="svg1432"
+     inkscape:cx="512"
+     inkscape:cy="512"
+     inkscape:guide-bbox="true"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-height="858"
+     inkscape:window-width="1114"
+     inkscape:window-x="72"
+     inkscape:window-y="31"
+     inkscape:zoom="0.69433594"
+     pagecolor="#ffffff"
+     showborder="true"
+     showguides="true"
+     showgrid="false"
+     inkscape:window-maximized="0"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0"
+     inkscape:showpageshadow="false" />
+  <metadata
+     id="metadata3060">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:title />
+        <dc:description>Simple globe centered on North America</dc:description>
+        <dc:subject>
+          <rdf:Bag>
+            <rdf:li>earth globe northamerica</rdf:li>
+          </rdf:Bag>
+        </dc:subject>
+        <dc:publisher>
+          <cc:Agent
+             rdf:about="http://www.openclipart.org/">
+            <dc:title>Open Clip Art Library</dc:title>
+          </cc:Agent>
+        </dc:publisher>
+        <dc:creator>
+          <cc:Agent>
+            <dc:title>Dan Gerhrads</dc:title>
+          </cc:Agent>
+        </dc:creator>
+        <dc:rights>
+          <cc:Agent>
+            <dc:title>Dan Gerhrads</dc:title>
+          </cc:Agent>
+        </dc:rights>
+        <dc:date>May 1, 2005</dc:date>
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <cc:license
+           rdf:resource="http://web.resource.org/cc/PublicDomain" />
+        <dc:language>en</dc:language>
+      </cc:Work>
+      <cc:License
+         rdf:about="http://web.resource.org/cc/PublicDomain">
+        <cc:permits
+           rdf:resource="http://web.resource.org/cc/Reproduction" />
+        <cc:permits
+           rdf:resource="http://web.resource.org/cc/Distribution" />
+        <cc:permits
+           rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
+      </cc:License>
+    </rdf:RDF>
+  </metadata>
+  <defs
+     id="defs1759">
+    <linearGradient
+       id="linearGradient37658">
+      <stop
+         style="stop-color:#2f7aff;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop37660" />
+      <stop
+         style="stop-color:#0000b3;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop37662" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient20137">
+      <stop
+         style="stop-color:#00bf00;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop20139" />
+      <stop
+         style="stop-color:#007500;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop20141" />
+    </linearGradient>
+    <radialGradient
+       xlink:href="#linearGradient20137"
+       r="188.61865"
+       inkscape:collect="always"
+       id="radialGradient20143"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.893959,1.11862)"
+       fy="298.37747"
+       fx="205.17723"
+       cy="297.1124"
+       cx="202.06305" />
+    <radialGradient
+       xlink:href="#linearGradient37658"
+       r="112.3373"
+       inkscape:collect="always"
+       id="radialGradient37664"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.806632,1.239722)"
+       fy="270.08731"
+       fx="221.61394"
+       cy="270.08731"
+       cx="221.61394" />
+    <radialGradient
+       xlink:href="#linearGradient20137"
+       r="188.61865"
+       inkscape:collect="always"
+       id="radialGradient1902"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.893959,1.11862)"
+       fy="298.37747"
+       fx="205.17723"
+       cy="297.1124"
+       cx="202.06305" />
+    <radialGradient
+       xlink:href="#linearGradient20137"
+       r="188.61865"
+       inkscape:collect="always"
+       id="radialGradient1904"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.893959,1.11862)"
+       fy="298.37747"
+       fx="205.17723"
+       cy="297.1124"
+       cx="202.06305" />
+    <radialGradient
+       xlink:href="#linearGradient20137"
+       r="188.61865"
+       inkscape:collect="always"
+       id="radialGradient1906"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.893959,1.11862)"
+       fy="298.37747"
+       fx="205.17723"
+       cy="297.1124"
+       cx="202.06305" />
+    <radialGradient
+       xlink:href="#linearGradient20137"
+       r="188.61865"
+       inkscape:collect="always"
+       id="radialGradient1908"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.893959,1.11862)"
+       fy="298.37747"
+       fx="205.17723"
+       cy="297.1124"
+       cx="202.06305" />
+    <radialGradient
+       xlink:href="#linearGradient20137"
+       r="188.61865"
+       inkscape:collect="always"
+       id="radialGradient1910"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.893959,1.11862)"
+       fy="298.37747"
+       fx="205.17723"
+       cy="297.1124"
+       cx="202.06305" />
+    <radialGradient
+       xlink:href="#linearGradient20137"
+       r="188.61865"
+       inkscape:collect="always"
+       id="radialGradient1912"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.893959,1.11862)"
+       fy="298.37747"
+       fx="205.17723"
+       cy="297.1124"
+       cx="202.06305" />
+    <radialGradient
+       xlink:href="#linearGradient20137"
+       r="188.61865"
+       inkscape:collect="always"
+       id="radialGradient1914"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.893959,1.11862)"
+       fy="298.37747"
+       fx="205.17723"
+       cy="297.1124"
+       cx="202.06305" />
+    <radialGradient
+       xlink:href="#linearGradient20137"
+       r="188.61865"
+       inkscape:collect="always"
+       id="radialGradient1916"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.893959,1.11862)"
+       fy="298.37747"
+       fx="205.17723"
+       cy="297.1124"
+       cx="202.06305" />
+    <radialGradient
+       xlink:href="#linearGradient20137"
+       r="188.61865"
+       inkscape:collect="always"
+       id="radialGradient1918"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.893959,1.11862)"
+       fy="298.37747"
+       fx="205.17723"
+       cy="297.1124"
+       cx="202.06305" />
+    <radialGradient
+       xlink:href="#linearGradient20137"
+       r="188.61865"
+       inkscape:collect="always"
+       id="radialGradient1920"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.893959,1.11862)"
+       fy="298.37747"
+       fx="205.17723"
+       cy="297.1124"
+       cx="202.06305" />
+    <radialGradient
+       xlink:href="#linearGradient37658-427"
+       r="112.3373"
+       inkscape:collect="always"
+       id="radialGradient37664-403"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.806632,1.239722)"
+       fy="270.08731"
+       fx="221.61394"
+       cy="270.08731"
+       cx="221.61394" />
+    <linearGradient
+       id="linearGradient37658-427">
+      <stop
+         style="stop-color:#488afe;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop7178" />
+      <stop
+         style="stop-color:#0000cc;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop7180" />
+    </linearGradient>
+    <radialGradient
+       xlink:href="#linearGradient20137-396"
+       r="188.61865"
+       inkscape:collect="always"
+       id="radialGradient1902-893"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.893959,1.11862)"
+       fy="298.37747"
+       fx="205.17723"
+       cy="297.1124"
+       cx="202.06305" />
+    <linearGradient
+       id="linearGradient20137-396">
+      <stop
+         style="stop-color:#00d800;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop7184" />
+      <stop
+         style="stop-color:#008e00;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop7186" />
+    </linearGradient>
+    <radialGradient
+       xlink:href="#linearGradient20137-527"
+       r="188.61865"
+       inkscape:collect="always"
+       id="radialGradient1904-666"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.893959,1.11862)"
+       fy="298.37747"
+       fx="205.17723"
+       cy="297.1124"
+       cx="202.06305" />
+    <linearGradient
+       id="linearGradient20137-527">
+      <stop
+         style="stop-color:#00d800;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop7190" />
+      <stop
+         style="stop-color:#008e00;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop7192" />
+    </linearGradient>
+    <radialGradient
+       xlink:href="#linearGradient20137-774"
+       r="188.61865"
+       inkscape:collect="always"
+       id="radialGradient1906-717"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.893959,1.11862)"
+       fy="298.37747"
+       fx="205.17723"
+       cy="297.1124"
+       cx="202.06305" />
+    <linearGradient
+       id="linearGradient20137-774">
+      <stop
+         style="stop-color:#00d800;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop7196" />
+      <stop
+         style="stop-color:#008e00;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop7198" />
+    </linearGradient>
+    <radialGradient
+       xlink:href="#linearGradient20137-253"
+       r="188.61865"
+       inkscape:collect="always"
+       id="radialGradient1908-922"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.893959,1.11862)"
+       fy="298.37747"
+       fx="205.17723"
+       cy="297.1124"
+       cx="202.06305" />
+    <linearGradient
+       id="linearGradient20137-253">
+      <stop
+         style="stop-color:#00d800;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop7202" />
+      <stop
+         style="stop-color:#008e00;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop7204" />
+    </linearGradient>
+    <radialGradient
+       xlink:href="#linearGradient20137-972"
+       r="188.61865"
+       inkscape:collect="always"
+       id="radialGradient1910-261"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.893959,1.11862)"
+       fy="298.37747"
+       fx="205.17723"
+       cy="297.1124"
+       cx="202.06305" />
+    <linearGradient
+       id="linearGradient20137-972">
+      <stop
+         style="stop-color:#00d800;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop7208" />
+      <stop
+         style="stop-color:#008e00;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop7210" />
+    </linearGradient>
+    <radialGradient
+       xlink:href="#linearGradient20137-945"
+       r="188.61865"
+       inkscape:collect="always"
+       id="radialGradient1912-713"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.893959,1.11862)"
+       fy="298.37747"
+       fx="205.17723"
+       cy="297.1124"
+       cx="202.06305" />
+    <linearGradient
+       id="linearGradient20137-945">
+      <stop
+         style="stop-color:#00d800;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop7214" />
+      <stop
+         style="stop-color:#008e00;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop7216" />
+    </linearGradient>
+    <radialGradient
+       xlink:href="#linearGradient20137-600"
+       r="188.61865"
+       inkscape:collect="always"
+       id="radialGradient1914-146"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.893959,1.11862)"
+       fy="298.37747"
+       fx="205.17723"
+       cy="297.1124"
+       cx="202.06305" />
+    <linearGradient
+       id="linearGradient20137-600">
+      <stop
+         style="stop-color:#00d800;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop7220" />
+      <stop
+         style="stop-color:#008e00;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop7222" />
+    </linearGradient>
+    <radialGradient
+       xlink:href="#linearGradient20137-196"
+       r="188.61865"
+       inkscape:collect="always"
+       id="radialGradient1916-817"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.893959,1.11862)"
+       fy="298.37747"
+       fx="205.17723"
+       cy="297.1124"
+       cx="202.06305" />
+    <linearGradient
+       id="linearGradient20137-196">
+      <stop
+         style="stop-color:#00d800;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop7226" />
+      <stop
+         style="stop-color:#008e00;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop7228" />
+    </linearGradient>
+    <radialGradient
+       xlink:href="#linearGradient20137-388"
+       r="188.61865"
+       inkscape:collect="always"
+       id="radialGradient1918-23"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.893959,1.11862)"
+       fy="298.37747"
+       fx="205.17723"
+       cy="297.1124"
+       cx="202.06305" />
+    <linearGradient
+       id="linearGradient20137-388">
+      <stop
+         style="stop-color:#00d800;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop7232" />
+      <stop
+         style="stop-color:#008e00;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop7234" />
+    </linearGradient>
+    <radialGradient
+       xlink:href="#linearGradient20137-202"
+       r="188.61865"
+       inkscape:collect="always"
+       id="radialGradient1920-260"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.893959,1.11862)"
+       fy="298.37747"
+       fx="205.17723"
+       cy="297.1124"
+       cx="202.06305" />
+    <linearGradient
+       id="linearGradient20137-202">
+      <stop
+         style="stop-color:#00d800;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop7238" />
+      <stop
+         style="stop-color:#008e00;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop7240" />
+    </linearGradient>
+    <radialGradient
+       xlink:href="#linearGradient20137-151"
+       r="188.61865"
+       inkscape:collect="always"
+       id="radialGradient20143-884"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.893959,1.11862)"
+       fy="298.37747"
+       fx="205.17723"
+       cy="297.1124"
+       cx="202.06305" />
+    <linearGradient
+       id="linearGradient20137-151">
+      <stop
+         style="stop-color:#00d800;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop7244" />
+      <stop
+         style="stop-color:#008e00;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop7246" />
+    </linearGradient>
+  </defs>
+  <desc
+     id="desc1434">wmf2svg</desc>
+  <polyline
+     transform="matrix(2.2285926,-3.5745108,2.3232002,1.4484387,-677.00545,692.67468)"
+     style="fill:url(#radialGradient37664-403);fill-opacity:1;stroke:#0c0c0c;stroke-width:0.6875;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4"
+     points="103.191467,409.292114   100.730545,403.134064 98.525299,396.927094 96.543777,390.573547 94.785973,384.171082   93.219925,377.622009 91.909569,371.072968 90.790962,364.426147 89.928040,357.779327   89.256882,351.083649 88.777481,344.387970 88.521805,337.692261 88.489838,330.947693   88.681602,324.300873 89.033165,317.605194 89.640404,311.007263 90.407448,304.458221   91.398209,298.006897 92.580727,291.604431 93.986977,285.299744 95.553017,279.092804   97.342781,272.983582 99. [...]
+     id="polyline1560" />
+  <g
+     transform="matrix(4.1610916,0,0,4.1610916,-268.34786,-716.6628)"
+     style="fill:url(#radialGradient1902-893);fill-opacity:1;fill-rule:evenodd"
+     inkscape:label="Continents"
+     id="Continents">
+    <polyline
+       transform="matrix(0.535579,-0.859032,0.558315,0.348091,-98.20917,338.6942)"
+       style="fill:url(#radialGradient1904-666);stroke:#0c0c0c;stroke-width:0.444585;stroke-linecap:round;stroke-linejoin:round"
+       points="132.818436,384.610931   131.827682,384.953064 128.184235,388.227600 126.074867,388.667450 123.422180,385.441803   120.417938,385.832794 117.126053,389.107300 116.838409,393.896912 116.902328,400.641479   115.655891,409.292114 114.409447,415.352448 115.432167,418.235992 113.578484,420.386444   111.053642,420.924042 109.903076,422.732361 109.871117,423.172241 116.295090,433.728943   123.262383,443.161530 130.836914,451.421204 140.904327,460.071808 151.195465,466.425385   153 [...]
+       id="polyline1460" />
+    <polyline
+       transform="matrix(0.535579,-0.859032,0.558315,0.348091,-98.20917,338.6942)"
+       style="fill:url(#radialGradient1906-717);stroke:#0c0c0c;stroke-width:0.444585;stroke-linecap:round;stroke-linejoin:round"
+       points="144.579727,355.237885   146.497345,357.241699 147.583984,362.324585 148.638672,368.384918 149.980988,372.539154   150.364502,377.035553 148.798477,377.279877 146.753021,373.467743 146.976746,368.433777   146.593216,362.959930 144.579727,355.237885 "
+       id="polyline1464" />
+    <polyline
+       transform="matrix(0.535579,-0.859032,0.558315,0.348091,-98.20917,338.6942)"
+       style="fill:url(#radialGradient1908-922);stroke:#0c0c0c;stroke-width:0.444585;stroke-linecap:round;stroke-linejoin:round"
+       points="150.108826,378.892731   148.830429,379.870209 149.309830,383.584595 150.172745,386.614777 152.633667,390.964508   152.505829,386.565887 153.336792,386.077148 153.017197,383.780090 150.108826,378.892731 "
+       id="polyline1468" />
+    <polyline
+       transform="matrix(0.535579,-0.859032,0.558315,0.348091,-98.20917,338.6942)"
+       style="fill:url(#radialGradient1910-261);stroke:#0c0c0c;stroke-width:0.444585;stroke-linecap:round;stroke-linejoin:round"
+       points="201.181000,353.820557   200.797470,356.459747 200.413956,361.053864 199.966507,365.990082 199.007706,368.238281   196.866379,363.204285 197.921066,357.681580 199.103592,354.895782 201.181000,353.820557 "
+       id="polyline1472" />
+    <polyline
+       transform="matrix(0.535579,-0.859032,0.558315,0.348091,-98.20917,338.6942)"
+       style="fill:url(#radialGradient1912-713);stroke:#0c0c0c;stroke-width:0.444585;stroke-linecap:round;stroke-linejoin:round"
+       points="204.632675,320.342133   203.993469,316.774353 202.906830,312.668976 206.230682,314.575043 208.883362,312.277985   209.842163,309.052338 208.915314,303.822876 208.563766,299.961853 209.874130,294.487976   212.430923,295.514343 213.261887,299.570862 213.581497,305.386810 213.837173,310.958405   212.111328,314.917175 211.951538,317.018738 212.335052,321.466217 210.800964,325.913727   208.691605,325.376099 206.454407,326.646820 205.016205,324.203125 204.632675,320.342133 "
+       id="polyline1476" />
+    <polyline
+       transform="matrix(0.535579,-0.859032,0.558315,0.348091,-98.20917,338.6942)"
+       style="fill:url(#radialGradient1914-146);stroke:#0c0c0c;stroke-width:0.444585;stroke-linecap:round;stroke-linejoin:round"
+       points="213.773254,334.955322   213.709335,340.820160 213.869125,343.263885 216.362015,346.636139 219.526062,350.594910   218.695099,344.632324 219.685867,341.406677 222.722061,339.060730 227.835663,334.662109   230.648163,335.786194 233.332809,333.147003 234.355515,326.011475 234.675125,319.218048   233.556534,312.522369 233.588486,306.071045 231.511078,300.646057 228.890350,297.420410   226.365509,296.980560 225.246902,294.830109 226.365509,293.461639 225.023193,290.235992   222 [...]
+       id="polyline1480" />
+    <polyline
+       transform="matrix(0.535579,-0.859032,0.558315,0.348091,-98.20917,338.6942)"
+       style="fill:url(#radialGradient1916-817);stroke:#0c0c0c;stroke-width:0.444585;stroke-linecap:round;stroke-linejoin:round"
+       points="232.533813,338.767487   230.200729,341.748779 229.401718,344.436798 229.721313,347.662476 233.460648,348.542206   237.040161,346.929382 237.231934,342.872864 235.378250,340.478088 233.620453,340.282562   232.533813,338.767487 "
+       id="polyline1484" />
+    <polyline
+       transform="matrix(0.535579,-0.859032,0.558315,0.348091,-98.20917,338.6942)"
+       style="fill:url(#radialGradient1918-23);stroke:#0c0c0c;stroke-width:0.444585;stroke-linecap:round;stroke-linejoin:round"
+       points="264.877380,375.813690   262.991730,379.919098 260.371002,382.167236 258.645172,385.148529 258.645172,389.693817   256.887360,391.062256 255.161514,388.911804 254.522308,386.956848 252.732559,385.197418   253.339798,391.697632 251.709839,392.332977 249.792236,387.738861 248.322067,389.840393   246.724060,393.017212 244.327072,395.412018 242.952774,399.664001 241.514587,403.329529   241.067139,407.337158 239.565018,407.190552 238.318573,407.777039 235.665894,409.096649   233 [...]
+       id="polyline1488" />
+    <polyline
+       transform="matrix(0.535579,-0.859032,0.558315,0.348091,-98.20917,338.6942)"
+       style="fill:url(#radialGradient1920-260);stroke:#0c0c0c;stroke-width:0.444585;stroke-linecap:round;stroke-linejoin:round"
+       points="244.774506,357.779327   243.304337,356.313110 242.345535,358.512421 241.131058,362.666687 239.916580,364.817108   238.062897,367.945038 237.615448,372.930145 238.414459,375.324951 239.373245,373.125641   239.852661,368.727020 240.683624,367.602905 241.067139,371.121826 241.290848,375.129456   241.834183,378.452850 243.336304,376.986664 243.528061,376.937775 243.719818,376.888916   243.911591,376.791168 244.071396,376.644531 244.390976,376.351288 244.678635,376.009186   244 [...]
+       id="polyline1492" />
+    <polyline
+       transform="matrix(0.535579,-0.859032,0.558315,0.348091,-98.20917,338.6942)"
+       style="fill:url(#radialGradient20143-884);stroke:#0c0c0c;stroke-width:0.444585;stroke-linecap:round;stroke-linejoin:round"
+       points="262.192749,389.449432   260.115326,391.160004 258.261658,394.287933 256.663635,394.532288 255.992477,392.968323   255.065643,395.802979 253.851151,400.885864 250.783005,404.209290 250.175766,401.276855   249.344803,399.810638 245.573502,402.889679 242.537292,406.213104 240.747543,406.995056   238.126801,409.878601 236.049423,409.976349 233.748291,411.002716 231.606964,415.010315   228.986237,420.826294 226.333542,423.123352 220.996231,428.059601 216.617691,433.680054   213 [...]
+       id="polyline1496" />
+  </g>
+  <text
+     transform="matrix(0.98267844,-0.18531886,0.18531886,0.98267844,0,0)"
+     sodipodi:linespacing="125%"
+     id="text3096"
+     y="456.47293"
+     x="394.15689"
+     style="font-size:187.56237793000002512px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#ff8119;fill-opacity:0.77168947;stroke:none;font-family:Purisa;-inkscape-font-specification:Purisa Bold"
+     xml:space="preserve"><tspan
+       dy="-109.78781"
+       dx="0 -9.8032694 -11.763925 -17.645885"
+       id="tspan3102"
+       y="456.47293"
+       x="394.15692"
+       sodipodi:role="line">WSJT-X</tspan><tspan
+       dx="0 -17.645885 -23.527849 -13.724579 29.30662 29.30662 -17.645885 -23.527849"
+       id="tspan3874"
+       y="690.92584"
+       x="394.15689"
+       sodipodi:role="line">JT65&JT9</tspan><tspan
+       dy="91.489815"
+       dx="0 0 0 0 -17.645885 -5.8819623 -17.645885"
+       id="tspan3100"
+       y="925.37885"
+       x="394.15689"
+       sodipodi:role="line">by K1JT</tspan></text>
+</svg>
diff --git a/astro.cpp b/astro.cpp
new file mode 100644
index 0000000..9fecf51
--- /dev/null
+++ b/astro.cpp
@@ -0,0 +1,212 @@
+#include "astro.h"
+
+#include <stdio.h>
+
+#include <QApplication>
+#include <QFile>
+#include <QTextStream>
+#include <QMessageBox>
+#include <QSettings>
+#include <QDateTime>
+#include <QFont>
+#include <QFontDialog>
+#include <QStandardPaths>
+#include <QDir>
+#include <QDebug>
+
+#include "commons.h"
+#include "qt_helpers.hpp"
+
+#include "ui_astro.h"
+
+#include "moc_astro.cpp"
+
+Astro::Astro(QSettings * settings, QWidget * parent)
+  : QWidget {parent}
+  , settings_ {settings}
+  , ui_ {new Ui::Astro}
+{
+  ui_->setupUi(this);
+
+  setWindowFlags (Qt::Dialog | Qt::WindowCloseButtonHint | Qt::WindowMinimizeButtonHint);
+  setWindowTitle(QApplication::applicationName () + " - " + tr ("Astronomical Data"));
+  setStyleSheet ("QWidget {background: cyan;}");
+
+  read_settings ();
+
+  ui_->text_label->clear();
+}
+
+Astro::~Astro ()
+{
+  if (isVisible ())
+    {
+      write_settings ();
+    }
+}
+
+void Astro::closeEvent (QCloseEvent * e)
+{
+  write_settings ();
+  QWidget::closeEvent (e);
+}
+
+void Astro::read_settings ()
+{
+  settings_->beginGroup ("Astro");
+  move (settings_->value ("window/pos", pos ()).toPoint ());
+  QFont font;
+  if (font.fromString (settings_->value ("font", ui_->text_label->font ().toString ()).toString ()))
+    {
+      ui_->text_label->setStyleSheet ("QLabel {" + font_as_stylesheet (font) + '}');
+      adjustSize ();
+    }
+  settings_->endGroup ();
+}
+
+void Astro::write_settings ()
+{
+  settings_->beginGroup ("Astro");
+  settings_->setValue ("window/pos", pos ());
+  settings_->setValue ("font", ui_->text_label->font ().toString ());
+  settings_->endGroup ();
+}
+
+void Astro::on_font_push_button_clicked (bool /* checked */)
+{
+  bool changed;
+  auto ss = styleSheet ();
+  setStyleSheet ("");
+  auto font = QFontDialog::getFont (&changed
+                                    , ui_->text_label->font ()
+                                    , this
+                                    , tr ("WSJT-X Astro Text Font Chooser")
+#if QT_VERSION >= 0x050201
+                                    , QFontDialog::MonospacedFonts
+#endif
+                                    );
+  if (changed)
+    {
+      ui_->text_label->setStyleSheet ("QLabel {" + font_as_stylesheet (font) + '}');
+      adjustSize ();
+    }
+  setStyleSheet (ss);
+}
+
+void Astro::astroUpdate(QDateTime t, QString mygrid, QString hisgrid,
+                        int fQSO, int nsetftx, int ntxFreq)
+{
+  static int ntxFreq0=-99;
+  double azsun,elsun,azmoon,elmoon,azmoondx,elmoondx;
+  double ramoon,decmoon,dgrd,poloffset,xnr,techo;
+  int ntsky,ndop,ndop00;
+  QString date = t.date().toString("yyyy MMM dd").trimmed ();
+  QString utc = t.time().toString().trimmed ();
+  int nyear=t.date().year();
+  int month=t.date().month();
+  int nday=t.date().day();
+  int nhr=t.time().hour();
+  int nmin=t.time().minute();
+  double sec=t.time().second() + 0.001*t.time().msec();
+  int isec=sec;
+  double uth=nhr + nmin/60.0 + sec/3600.0;
+  //  int nfreq=(int)datcom_.fcenter;
+  int nfreq=10368;
+  if(nfreq<10 or nfreq > 50000) nfreq=144;
+
+  astrosub_(&nyear, &month, &nday, &uth, &nfreq, mygrid.toLatin1(),
+            hisgrid.toLatin1(), &azsun, &elsun, &azmoon, &elmoon,
+            &azmoondx, &elmoondx, &ntsky, &ndop, &ndop00,&ramoon, &decmoon,
+            &dgrd, &poloffset, &xnr, &techo, 6, 6);
+
+  QString message;
+  {
+    QTextStream out {&message};
+    out
+      << " " << date << "\n"
+      "UTC: " << utc << "\n"
+      << fixed
+      << qSetFieldWidth (6)
+      << qSetRealNumberPrecision (1)
+      << "Az:    " << azmoon << "\n"
+      "El:    " << elmoon << "\n"
+      "MyDop: " << ndop00 << "\n"
+      << qSetRealNumberPrecision (2)
+      << "Delay: " << techo << "\n"
+      << qSetRealNumberPrecision (1)
+      << "DxAz:  " << azmoondx << "\n"
+      "DxEl:  " << elmoondx << "\n"
+      "DxDop: " << ndop << "\n"
+      "Dec:   " << decmoon << "\n"
+      "SunAz: " << azsun << "\n"
+      "SunEl: " << elsun << "\n"
+      "Freq:  " << nfreq << "\n"
+      "Tsky:  " << ntsky << "\n"
+      "MNR:   " << xnr << "\n"
+      "Dgrd:  " << dgrd;
+  }
+  ui_->text_label->setText(message);
+
+  static QFile f {QDir {QStandardPaths::writableLocation (QStandardPaths::DataLocation)}.absoluteFilePath ("azel.dat")};
+  if (!f.open (QIODevice::WriteOnly | QIODevice::Text))
+    {
+    QMessageBox mb;
+    mb.setText ("Cannot open \"" + f.fileName () + "\" for writing:" + f.errorString ());
+    mb.exec();
+    return;
+  }
+  int ndiff=0;
+  if(ntxFreq != ntxFreq0) ndiff=1;
+  ntxFreq0=ntxFreq;
+  {
+    QTextStream out {&f};
+    out << fixed
+        << qSetRealNumberPrecision (1)
+        << qSetPadChar ('0')
+        << right
+        << qSetFieldWidth (2) << nhr
+        << qSetFieldWidth (0) << ':'
+        << qSetFieldWidth (2) << nmin
+        << qSetFieldWidth (0) << ':'
+        << qSetFieldWidth (2) << isec
+        << qSetFieldWidth (0) << ','
+        << qSetFieldWidth (5) << azmoon
+        << qSetFieldWidth (0) << ','
+        << qSetFieldWidth (5) << elmoon
+        << qSetFieldWidth (0) << ",Moon\n"
+        << qSetFieldWidth (2) << nhr
+        << qSetFieldWidth (0) << ':'
+        << qSetFieldWidth (2) << nmin
+        << qSetFieldWidth (0) << ':'
+        << qSetFieldWidth (2) << isec
+        << qSetFieldWidth (0) << ','
+        << qSetFieldWidth (5) << azsun
+        << qSetFieldWidth (0) << ','
+        << qSetFieldWidth (5) << elsun
+        << qSetFieldWidth (0) << ",Sun\n"
+        << qSetFieldWidth (2) << nhr
+        << qSetFieldWidth (0) << ':'
+        << qSetFieldWidth (2) << nmin
+        << qSetFieldWidth (0) << ':'
+        << qSetFieldWidth (2) << isec
+        << qSetFieldWidth (0) << ','
+        << qSetFieldWidth (5) << 0.
+        << qSetFieldWidth (0) << ','
+        << qSetFieldWidth (5) << 0.
+        << qSetFieldWidth (0) << ",Sun\n"
+        << qSetPadChar (' ')
+        << qSetFieldWidth (4) << nfreq
+        << qSetFieldWidth (0) << ','
+        << qSetFieldWidth (6) << ndop
+        << qSetFieldWidth (0) << ",Doppler\n"
+        << qSetFieldWidth (3) << fQSO
+        << qSetFieldWidth (0) << ','
+        << qSetFieldWidth (1) << nsetftx
+        << qSetFieldWidth (0) << ",fQSO\n"
+        << qSetFieldWidth (3) << ntxFreq
+        << qSetFieldWidth (0) << ','
+        << qSetFieldWidth (1) << ndiff
+        << qSetFieldWidth (0) << ",fQSO2";
+  }
+  f.close();
+}
diff --git a/astro.h b/astro.h
new file mode 100644
index 0000000..8a45a6e
--- /dev/null
+++ b/astro.h
@@ -0,0 +1,51 @@
+// -*- Mode: C++ -*-
+#ifndef ASTRO_H
+#define ASTRO_H
+
+#include <QWidget>
+#include <QDir>
+
+class QSettings;
+
+namespace Ui {
+  class Astro;
+}
+
+class Astro final
+  : public QWidget
+{
+  Q_OBJECT;
+
+private:
+  Q_DISABLE_COPY (Astro);
+
+public:
+  explicit Astro(QSettings * settings, QWidget * parent = nullptr);
+  ~Astro ();
+
+  void astroUpdate(QDateTime t, QString mygrid, QString hisgrid,
+                   int fQSO, int nsetftx, int ntxFreq);
+
+  Q_SLOT void on_font_push_button_clicked (bool);
+
+protected:
+  void closeEvent (QCloseEvent *) override;
+
+private:
+  void read_settings ();
+  void write_settings ();
+
+  QSettings * settings_;
+  QScopedPointer<Ui::Astro> ui_;
+};
+
+extern "C" {
+  void astrosub_(int* nyear, int* month, int* nday, double* uth, int* nfreq,
+                 const char* mygrid, const char* hisgrid, double* azsun,
+                 double* elsun, double* azmoon, double* elmoon, double* azmoondx,
+                 double* elmoondx, int* ntsky, int* ndop, int* ndop00,
+                 double* ramoon, double* decmoon, double* dgrd, double* poloffset,
+                 double* xnr, double* techo, int len1, int len2);
+}
+
+#endif // ASTRO_H
diff --git a/astro.ui b/astro.ui
new file mode 100644
index 0000000..7d8f7fa
--- /dev/null
+++ b/astro.ui
@@ -0,0 +1,103 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Astro</class>
+ <widget class="QWidget" name="Astro">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>169</width>
+    <height>79</height>
+   </rect>
+  </property>
+  <property name="sizePolicy">
+   <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
+    <horstretch>0</horstretch>
+    <verstretch>0</verstretch>
+   </sizepolicy>
+  </property>
+  <property name="styleSheet">
+   <string notr="true"/>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <property name="leftMargin">
+    <number>0</number>
+   </property>
+   <property name="topMargin">
+    <number>0</number>
+   </property>
+   <property name="rightMargin">
+    <number>0</number>
+   </property>
+   <property name="bottomMargin">
+    <number>9</number>
+   </property>
+   <item>
+    <widget class="QLabel" name="text_label">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
+       <horstretch>0</horstretch>
+       <verstretch>0</verstretch>
+      </sizepolicy>
+     </property>
+     <property name="styleSheet">
+      <string notr="true">QLabel {
+font: 18pt "Courier";
+}</string>
+     </property>
+     <property name="frameShadow">
+      <enum>QFrame::Sunken</enum>
+     </property>
+     <property name="text">
+      <string>Astro Data</string>
+     </property>
+     <property name="alignment">
+      <set>Qt::AlignCenter</set>
+     </property>
+     <property name="margin">
+      <number>6</number>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <layout class="QHBoxLayout" name="horizontalLayout">
+     <item>
+      <spacer name="horizontalSpacer">
+       <property name="orientation">
+        <enum>Qt::Horizontal</enum>
+       </property>
+       <property name="sizeHint" stdset="0">
+        <size>
+         <width>40</width>
+         <height>20</height>
+        </size>
+       </property>
+      </spacer>
+     </item>
+     <item>
+      <widget class="QPushButton" name="font_push_button">
+       <property name="text">
+        <string>Font</string>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <spacer name="horizontalSpacer_2">
+       <property name="orientation">
+        <enum>Qt::Horizontal</enum>
+       </property>
+       <property name="sizeHint" stdset="0">
+        <size>
+         <width>40</width>
+         <height>20</height>
+        </size>
+       </property>
+      </spacer>
+     </item>
+    </layout>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/blue.dat b/blue.dat
deleted file mode 100644
index d9fc886..0000000
--- a/blue.dat
+++ /dev/null
@@ -1,256 +0,0 @@
-     0      0.0000    0.0000    0.0000
-     1	    0.0902    0.0902    0.2558
-     2	    0.1176    0.1176    0.2694
-     3	    0.1412    0.1412    0.2820
-     4	    0.1569    0.1569    0.2938
-     5	    0.1725    0.1725    0.3049
-     6	    0.1843    0.1843    0.3154
-     7	    0.1961    0.1961    0.3254
-     8	    0.2039    0.2039    0.3349
-     9	    0.2157    0.2157    0.3440
-    10	    0.2235    0.2235    0.3528
-    11	    0.2314    0.2314    0.3612
-    12	    0.2392    0.2392    0.3693
-    13	    0.2471    0.2471    0.3772
-    14	    0.2549    0.2549    0.3848
-    15	    0.2588    0.2588    0.3921
-    16	    0.2667    0.2667    0.3992
-    17	    0.2706    0.2706    0.4061
-    18	    0.2784    0.2784    0.4129
-    19	    0.2824    0.2824    0.4194
-    20	    0.2902    0.2902    0.4258
-    21	    0.2941    0.2941    0.4319
-    22	    0.2980    0.2980    0.4380
-    23	    0.3059    0.3059    0.4439
-    24	    0.3098    0.3098    0.4496
-    25	    0.3137    0.3137    0.4553
-    26	    0.3176    0.3176    0.4608
-    27	    0.3216    0.3216    0.4661
-    28	    0.3294    0.3294    0.4714
-    29	    0.3333    0.3333    0.4765
-    30	    0.3373    0.3373    0.4815
-    31	    0.3412    0.3412    0.4865
-    32	    0.3451    0.3451    0.4913
-    33	    0.3490    0.3490    0.4960
-    34	    0.3529    0.3529    0.5006
-    35	    0.3569    0.3569    0.5052
-    36	    0.3608    0.3608    0.5096
-    37	    0.3647    0.3647    0.5140
-    38	    0.3686    0.3686    0.5183
-    39	    0.3725    0.3725    0.5225
-    40	    0.3765    0.3765    0.5266
-    41	    0.3804    0.3804    0.5306
-    42	    0.3843    0.3843    0.5346
-    43	    0.3843    0.3843    0.5385
-    44	    0.3882    0.3882    0.5423
-    45	    0.3922    0.3922    0.5460
-    46	    0.3961    0.3961    0.5497
-    47	    0.4000    0.4000    0.5533
-    48	    0.4039    0.4039    0.5569
-    49	    0.4078    0.4078    0.5603
-    50	    0.4118    0.4118    0.5638
-    51	    0.4118    0.4118    0.5671
-    52	    0.4157    0.4157    0.5704
-    53	    0.4196    0.4196    0.5736
-    54	    0.4235    0.4235    0.5768
-    55	    0.4275    0.4275    0.5799
-    56	    0.4314    0.4314    0.5829
-    57	    0.4314    0.4314    0.5859
-    58	    0.4353    0.4353    0.5889
-    59	    0.4392    0.4392    0.5917
-    60	    0.4431    0.4431    0.5946
-    61	    0.4471    0.4471    0.5973
-    62	    0.4471    0.4471    0.6001
-    63	    0.4510    0.4510    0.6027
-    64	    0.4549    0.4549    0.6053
-    65	    0.4588    0.4588    0.6079
-    66	    0.4627    0.4627    0.6104
-    67	    0.4627    0.4627    0.6129
-    68	    0.4667    0.4667    0.6153
-    69	    0.4706    0.4706    0.6176
-    70	    0.4745    0.4745    0.6199
-    71	    0.4745    0.4745    0.6222
-    72	    0.4784    0.4784    0.6244
-    73	    0.4824    0.4824    0.6266
-    74	    0.4863    0.4863    0.6287
-    75	    0.4863    0.4863    0.6308
-    76	    0.4902    0.4902    0.6328
-    77	    0.4941    0.4941    0.6348
-    78	    0.4980    0.4980    0.6367
-    79	    0.5020    0.5020    0.6386
-    80	    0.5020    0.5020    0.6404
-    81	    0.5059    0.5059    0.6422
-    82	    0.5098    0.5098    0.6440
-    83	    0.5098    0.5098    0.6457
-    84	    0.5137    0.5137    0.6474
-    85	    0.5176    0.5176    0.6490
-    86	    0.5216    0.5216    0.6506
-    87	    0.5216    0.5216    0.6521
-    88	    0.5255    0.5255    0.6536
-    89	    0.5294    0.5294    0.6551
-    90	    0.5333    0.5333    0.6565
-    91	    0.5333    0.5333    0.6578
-    92	    0.5373    0.5373    0.6591
-    93	    0.5412    0.5412    0.6604
-    94	    0.5451    0.5451    0.6617
-    95	    0.5451    0.5451    0.6629
-    96	    0.5490    0.5490    0.6640
-    97	    0.5529    0.5529    0.6651
-    98	    0.5569    0.5569    0.6662
-    99	    0.5569    0.5569    0.6672
-   100	    0.5608    0.5608    0.6682
-   101	    0.5647    0.5647    0.6692
-   102	    0.5647    0.5647    0.6701
-   103	    0.5686    0.5686    0.6710
-   104	    0.5725    0.5725    0.6718
-   105	    0.5765    0.5765    0.6726
-   106	    0.5765    0.5765    0.6733
-   107	    0.5804    0.5804    0.6740
-   108	    0.5843    0.5843    0.6747
-   109	    0.5843    0.5843    0.6753
-   110	    0.5882    0.5882    0.6759
-   111	    0.5922    0.5922    0.6765
-   112	    0.5961    0.5961    0.6770
-   113	    0.5961    0.5961    0.6774
-   114	    0.6000    0.6000    0.6779
-   115	    0.6039    0.6039    0.6783
-   116	    0.6039    0.6039    0.6786
-   117	    0.6078    0.6078    0.6789
-   118	    0.6118    0.6118    0.6792
-   119	    0.6157    0.6157    0.6794
-   120	    0.6157    0.6157    0.6796
-   121	    0.6196    0.6196    0.6798
-   122	    0.6235    0.6235    0.6799
-   123	    0.6235    0.6235    0.6800
-   124	    0.6275    0.6275    0.6800
-   125	    0.6314    0.6314    0.6800
-   126	    0.6353    0.6353    0.6799
-   127	    0.6353    0.6353    0.6799
-   128	    0.6392    0.6392    0.6797
-   129	    0.6431    0.6431    0.6796
-   130	    0.6431    0.6431    0.6794
-   131	    0.6471    0.6471    0.6791
-   132	    0.6510    0.6510    0.6789
-   133	    0.6549    0.6549    0.6785
-   134	    0.6549    0.6549    0.6782
-   135	    0.6588    0.6588    0.6778
-   136	    0.6627    0.6627    0.6773
-   137	    0.6627    0.6627    0.6769
-   138	    0.6667    0.6667    0.6763
-   139	    0.6706    0.6706    0.6758
-   140	    0.6745    0.6745    0.6752
-   141	    0.6745    0.6745    0.6746
-   142	    0.6784    0.6784    0.6739
-   143	    0.6824    0.6824    0.6732
-   144	    0.6824    0.6824    0.6724
-   145	    0.6863    0.6863    0.6716
-   146	    0.6902    0.6902    0.6708
-   147	    0.6941    0.6941    0.6699
-   148	    0.6941    0.6941    0.6690
-   149	    0.6980    0.6980    0.6680
-   150	    0.7020    0.7020    0.6670
-   151	    0.7020    0.7020    0.6660
-   152	    0.7059    0.7059    0.6649
-   153	    0.7098    0.7098    0.6638
-   154	    0.7098    0.7098    0.6626
-   155	    0.7137    0.7137    0.6614
-   156	    0.7176    0.7176    0.6601
-   157	    0.7216    0.7216    0.6589
-   158	    0.7216    0.7216    0.6575
-   159	    0.7255    0.7255    0.6561
-   160	    0.7294    0.7294    0.6547
-   161	    0.7294    0.7294    0.6533
-   162	    0.7333    0.7333    0.6518
-   163	    0.7373    0.7373    0.6502
-   164	    0.7412    0.7412    0.6486
-   165	    0.7412    0.7412    0.6470
-   166	    0.7451    0.7451    0.6453
-   167	    0.7490    0.7490    0.6436
-   168	    0.7490    0.7490    0.6418
-   169	    0.7529    0.7529    0.6400
-   170	    0.7569    0.7569    0.6382
-   171	    0.7608    0.7608    0.6363
-   172	    0.7608    0.7608    0.6343
-   173	    0.7647    0.7647    0.6324
-   174	    0.7686    0.7686    0.6303
-   175	    0.7686    0.7686    0.6282
-   176	    0.7725    0.7725    0.6261
-   177	    0.7765    0.7765    0.6239
-   178	    0.7804    0.7804    0.6217
-   179	    0.7804    0.7804    0.6194
-   180	    0.7843    0.7843    0.6171
-   181	    0.7882    0.7882    0.6147
-   182	    0.7882    0.7882    0.6123
-   183	    0.7922    0.7922    0.6098
-   184	    0.7961    0.7961    0.6073
-   185	    0.8000    0.8000    0.6047
-   186	    0.8000    0.8000    0.6021
-   187	    0.8039    0.8039    0.5994
-   188	    0.8078    0.8078    0.5967
-   189	    0.8078    0.8078    0.5939
-   190	    0.8118    0.8118    0.5911
-   191	    0.8157    0.8157    0.5882
-   192	    0.8196    0.8196    0.5853
-   193	    0.8196    0.8196    0.5823
-   194	    0.8235    0.8235    0.5792
-   195	    0.8275    0.8275    0.5761
-   196	    0.8275    0.8275    0.5729
-   197	    0.8314    0.8314    0.5697
-   198	    0.8353    0.8353    0.5664
-   199	    0.8392    0.8392    0.5630
-   200	    0.8392    0.8392    0.5596
-   201	    0.8431    0.8431    0.5561
-   202	    0.8471    0.8471    0.5525
-   203	    0.8471    0.8471    0.5489
-   204	    0.8510    0.8510    0.5452
-   205	    0.8549    0.8549    0.5414
-   206	    0.8588    0.8588    0.5376
-   207	    0.8588    0.8588    0.5337
-   208	    0.8627    0.8627    0.5297
-   209	    0.8667    0.8667    0.5257
-   210	    0.8667    0.8667    0.5215
-   211	    0.8706    0.8706    0.5173
-   212	    0.8745    0.8745    0.5130
-   213	    0.8784    0.8784    0.5086
-   214	    0.8784    0.8784    0.5042
-   215	    0.8824    0.8824    0.4996
-   216	    0.8863    0.8863    0.4950
-   217	    0.8863    0.8863    0.4902
-   218	    0.8902    0.8902    0.4854
-   219	    0.8941    0.8941    0.4804
-   220	    0.8980    0.8980    0.4754
-   221	    0.8980    0.8980    0.4702
-   222	    0.9020    0.9020    0.4649
-   223	    0.9059    0.9059    0.4595
-   224	    0.9098    0.9098    0.4540
-   225	    0.9098    0.9098    0.4484
-   226	    0.9137    0.9137    0.4426
-   227	    0.9176    0.9176    0.4366
-   228	    0.9176    0.9176    0.4306
-   229	    0.9216    0.9216    0.4243
-   230	    0.9255    0.9255    0.4179
-   231	    0.9294    0.9294    0.4114
-   232	    0.9294    0.9294    0.4046
-   233	    0.9333    0.9333    0.3977
-   234	    0.9373    0.9373    0.3905
-   235	    0.9373    0.9373    0.3831
-   236	    0.9412    0.9412    0.3754
-   237	    0.9451    0.9451    0.3675
-   238	    0.9490    0.9490    0.3594
-   239	    0.9490    0.9490    0.3509
-   240	    0.9529    0.9529    0.3420
-   241	    0.9569    0.9569    0.3328
-   242	    0.9608    0.9608    0.3232
-   243	    0.9608    0.9608    0.3131
-   244	    0.9647    0.9647    0.3024
-   245	    0.9686    0.9686    0.2912
-   246	    0.9686    0.9686    0.2792
-   247	    0.9725    0.9725    0.2664
-   248	    0.9765    0.9765    0.2526
-   249	    0.9804    0.9804    0.2375
-   250	    0.9804    0.9804    0.2208
-   251	    0.9843    0.9843    0.2020
-   252	    0.9882    0.9882    0.1800
-   253	    1.0       0.0       0.0
-   254	    1.0       1.0       0.0
-   255	    0.0       1.000     0.0
diff --git a/commons.h b/commons.h
index e521841..51834f3 100644
--- a/commons.h
+++ b/commons.h
@@ -1,16 +1,14 @@
 #ifndef COMMONS_H
 #define COMMONS_H
 
-//#define NSMAX 1365
 #define NSMAX 6827
 #define NTMAX 120
+#define RX_SAMPLE_RATE 12000
 
-extern "C" {
-
-extern struct {
+extern struct FortranCommon {
   float ss[184*NSMAX];              //This is "common/jt9com/..." in fortran
   float savg[NSMAX];
-  short int d2[NTMAX*12000];
+  short int d2[NTMAX*RX_SAMPLE_RATE];
   int nutc;                         //UTC as integer, HHMM
   int ndiskdat;                     //1 ==> data read from *.wav file
   int ntrperiod;                    //TR period (seconds)
@@ -18,6 +16,7 @@ extern struct {
   int newdat;                       //1 ==> new data, must do long FFT
   int npts8;                        //npts for c0() array
   int nfa;                          //Low decode limit (Hz)
+  int nfSplit;                      //JT65 | JT9 split frequency
   int nfb;                          //High decode limit (Hz)
   int ntol;                         //+/- decoding range around fQSO (Hz)
   int kin;
@@ -30,6 +29,10 @@ extern struct {
   char datetime[20];
 } jt9com_;
 
+extern "C" {
+extern struct {
+  float syellow[NSMAX];
+} jt9w_;
 }
 
 #endif // COMMONS_H
diff --git a/contrib/Commander TCPIP Mesages.pdf b/contrib/Commander TCPIP Mesages.pdf
new file mode 100644
index 0000000..1c7e6a8
Binary files /dev/null and b/contrib/Commander TCPIP Mesages.pdf differ
diff --git a/contrib/Darwin/KVASD-installer.app/Contents/Info.plist b/contrib/Darwin/KVASD-installer.app/Contents/Info.plist
new file mode 100644
index 0000000..2fb0078
--- /dev/null
+++ b/contrib/Darwin/KVASD-installer.app/Contents/Info.plist
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>BuildMachineOSBuild</key>
+	<string>12F45</string>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>en</string>
+	<key>CFBundleDocumentTypes</key>
+	<array>
+		<dict>
+			<key>CFBundleTypeRole</key>
+			<string>Viewer</string>
+			<key>LSItemContentTypes</key>
+			<array>
+				<string>com.apple.application-bundle</string>
+			</array>
+		</dict>
+	</array>
+	<key>CFBundleExecutable</key>
+	<string>KVASD-installer</string>
+	<key>CFBundleIconFile</key>
+	<string>AppIcon</string>
+	<key>CFBundleIdentifier</key>
+	<string>org.k1jt.KVASD-installer</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundleName</key>
+	<string>KVASD-installer</string>
+	<key>CFBundlePackageType</key>
+	<string>APPL</string>
+	<key>CFBundleShortVersionString</key>
+	<string>1.0</string>
+	<key>CFBundleSignature</key>
+	<string>????</string>
+	<key>CFBundleVersion</key>
+	<string>1</string>
+	<key>DTCompiler</key>
+	<string>com.apple.compilers.llvm.clang.1_0</string>
+	<key>DTPlatformBuild</key>
+	<string>5A2053</string>
+	<key>DTPlatformVersion</key>
+	<string>GM</string>
+	<key>DTSDKBuild</key>
+	<string>13A595</string>
+	<key>DTSDKName</key>
+	<string>macosx10.9</string>
+	<key>DTXcode</key>
+	<string>0501</string>
+	<key>DTXcodeBuild</key>
+	<string>5A2053</string>
+	<key>LSApplicationCategoryType</key>
+	<string>public.app-category.utilities</string>
+	<key>LSMinimumSystemVersion</key>
+	<string>10.7</string>
+	<key>NSHumanReadableCopyright</key>
+	<string>Created by Bill Somerville (G4WJS) on 12/11/2014.
+
+ The author of this work hereby waives all claim of copyright (economic and moral)
+in this work and immediately places it in the public domain; it may be used, distorted
+or destroyed in any manner whatsoever without further attribution or notice to the creator.</string>
+	<key>NSMainNibFile</key>
+	<string>MainMenu</string>
+	<key>NSPrincipalClass</key>
+	<string>NSApplication</string>
+</dict>
+</plist>
diff --git a/contrib/Darwin/KVASD-installer.app/Contents/MacOS/KVASD-installer b/contrib/Darwin/KVASD-installer.app/Contents/MacOS/KVASD-installer
new file mode 100755
index 0000000..248a9b3
Binary files /dev/null and b/contrib/Darwin/KVASD-installer.app/Contents/MacOS/KVASD-installer differ
diff --git a/contrib/Darwin/KVASD-installer.app/Contents/PkgInfo b/contrib/Darwin/KVASD-installer.app/Contents/PkgInfo
new file mode 100644
index 0000000..bd04210
--- /dev/null
+++ b/contrib/Darwin/KVASD-installer.app/Contents/PkgInfo
@@ -0,0 +1 @@
+APPL????
\ No newline at end of file
diff --git a/contrib/Darwin/KVASD-installer.app/Contents/Resources/AppIcon.icns b/contrib/Darwin/KVASD-installer.app/Contents/Resources/AppIcon.icns
new file mode 100644
index 0000000..928b56e
Binary files /dev/null and b/contrib/Darwin/KVASD-installer.app/Contents/Resources/AppIcon.icns differ
diff --git a/contrib/Darwin/KVASD-installer.app/Contents/Resources/Credits.rtf b/contrib/Darwin/KVASD-installer.app/Contents/Resources/Credits.rtf
new file mode 100644
index 0000000..fb63b08
--- /dev/null
+++ b/contrib/Darwin/KVASD-installer.app/Contents/Resources/Credits.rtf
@@ -0,0 +1,30 @@
+{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf400
+{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\paperw11900\paperh16840\vieww9600\viewh8400\viewkind0
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720
+
+\f0\b\fs24 \cf0 Engineering:
+\b0 \
+	G4WJS - Bill Somerville\
+\
+
+\b Human Interface Design:
+\b0 \
+	G4WJS - Bill Somerville\
+\
+
+\b Testing:
+\b0 \
+	G4WJS - Bill Somerville\
+\
+
+\b Documentation:
+\b0 \
+	G4WJS - Bill Somerville\
+\
+
+\b With special thanks to:
+\b0 \
+	No one in particular.\
+}
\ No newline at end of file
diff --git a/contrib/Darwin/KVASD-installer.app/Contents/Resources/InfoPlist.strings b/contrib/Darwin/KVASD-installer.app/Contents/Resources/InfoPlist.strings
new file mode 100644
index 0000000..5e45963
Binary files /dev/null and b/contrib/Darwin/KVASD-installer.app/Contents/Resources/InfoPlist.strings differ
diff --git a/contrib/Darwin/KVASD-installer.app/Contents/Resources/MainMenu.nib b/contrib/Darwin/KVASD-installer.app/Contents/Resources/MainMenu.nib
new file mode 100644
index 0000000..e8b411a
Binary files /dev/null and b/contrib/Darwin/KVASD-installer.app/Contents/Resources/MainMenu.nib differ
diff --git a/contrib/Darwin/KVASD-installer.app/Contents/Resources/WSJTAppDelegate.scpt b/contrib/Darwin/KVASD-installer.app/Contents/Resources/WSJTAppDelegate.scpt
new file mode 100644
index 0000000..d8789aa
Binary files /dev/null and b/contrib/Darwin/KVASD-installer.app/Contents/Resources/WSJTAppDelegate.scpt differ
diff --git a/contrib/NSIS/AccessControl.zip b/contrib/NSIS/AccessControl.zip
new file mode 100644
index 0000000..94fa892
Binary files /dev/null and b/contrib/NSIS/AccessControl.zip differ
diff --git a/contrib/NSIS/Md5dll.zip b/contrib/NSIS/Md5dll.zip
new file mode 100644
index 0000000..1d80771
Binary files /dev/null and b/contrib/NSIS/Md5dll.zip differ
diff --git a/contrib/NSIS/NsRichEdit.zip b/contrib/NSIS/NsRichEdit.zip
new file mode 100644
index 0000000..f028a74
Binary files /dev/null and b/contrib/NSIS/NsRichEdit.zip differ
diff --git a/contrib/NSIS/Plugins-i386-ansi/AccessControl.dll b/contrib/NSIS/Plugins-i386-ansi/AccessControl.dll
new file mode 100644
index 0000000..0de0324
Binary files /dev/null and b/contrib/NSIS/Plugins-i386-ansi/AccessControl.dll differ
diff --git a/contrib/NSIS/Plugins-i386-ansi/md5dll.dll b/contrib/NSIS/Plugins-i386-ansi/md5dll.dll
new file mode 100644
index 0000000..003e163
Binary files /dev/null and b/contrib/NSIS/Plugins-i386-ansi/md5dll.dll differ
diff --git a/contrib/NSIS/Plugins-i386-ansi/nsRichEdit.dll b/contrib/NSIS/Plugins-i386-ansi/nsRichEdit.dll
new file mode 100644
index 0000000..e07f395
Binary files /dev/null and b/contrib/NSIS/Plugins-i386-ansi/nsRichEdit.dll differ
diff --git a/contrib/NSIS/Plugins-i386-unicode/AccessControl.dll b/contrib/NSIS/Plugins-i386-unicode/AccessControl.dll
new file mode 100644
index 0000000..cc27f63
Binary files /dev/null and b/contrib/NSIS/Plugins-i386-unicode/AccessControl.dll differ
diff --git a/contrib/NSIS/Plugins-i386-unicode/md5dll.dll b/contrib/NSIS/Plugins-i386-unicode/md5dll.dll
new file mode 100644
index 0000000..bde153f
Binary files /dev/null and b/contrib/NSIS/Plugins-i386-unicode/md5dll.dll differ
diff --git a/contrib/NSIS/Plugins-i386-unicode/nsRichEdit.dll b/contrib/NSIS/Plugins-i386-unicode/nsRichEdit.dll
new file mode 100644
index 0000000..b44340f
Binary files /dev/null and b/contrib/NSIS/Plugins-i386-unicode/nsRichEdit.dll differ
diff --git a/contrib/NSIS/README b/contrib/NSIS/README
new file mode 100644
index 0000000..2182d81
--- /dev/null
+++ b/contrib/NSIS/README
@@ -0,0 +1,9 @@
+NSIS Addons
+===========
+
+This directory contains archives of NSIS plugins and includes that are
+used in making the WSJT-X Windows  installer. The plugin DLLs are also
+extracted and deployed in sub-directories  where they are added to the
+project  NSIS plugin  path in  the project  CMakeCPackOptions.cmake.in
+template which is in turn used in generating the NSIS installer script
+from the CMake/Modules/NSIS.template.in template file.
diff --git a/cty.dat b/cty.dat
new file mode 100644
index 0000000..b57437f
--- /dev/null
+++ b/cty.dat
@@ -0,0 +1,1325 @@
+Sov Mil Order of Malta:   15:  28:  EU:   41.90:   -12.43:    -1.0:  1A:
+    1A;
+Spratly Islands:          26:  50:  AS:    9.88:  -114.23:    -8.0:  1S:
+    1S,9M0,BV9S;
+Monaco:                   14:  27:  EU:   43.73:    -7.40:    -1.0:  3A:
+    3A;
+Agalega & St. Brandon:    39:  53:  AF:  -10.45:   -56.67:    -4.0:  3B6:
+    3B6,3B7;
+Mauritius:                39:  53:  AF:  -20.35:   -57.50:    -4.0:  3B8:
+    3B8;
+Rodriguez Island:         39:  53:  AF:  -19.70:   -63.42:    -4.0:  3B9:
+    3B9;
+Equatorial Guinea:        36:  47:  AF:    1.70:   -10.33:    -1.0:  3C:
+    3C;
+Annobon Island:           36:  52:  AF:   -1.43:    -5.62:    -1.0:  3C0:
+    3C0;
+Fiji:                     32:  56:  OC:  -17.78:  -177.92:   -12.0:  3D2:
+    3D2;
+Conway Reef:              32:  56:  OC:  -22.00:  -175.00:   -12.0:  3D2/c:
+    =3D2C;
+Rotuma Island:            32:  56:  OC:  -12.48:  -177.08:   -12.0:  3D2/r:
+    =3D2RI;
+Swaziland:                38:  57:  AF:  -26.65:   -31.48:    -2.0:  3DA:
+    3DA;
+Tunisia:                  33:  37:  AF:   35.40:    -9.32:    -1.0:  3V:
+    3V,TS;
+Vietnam:                  26:  49:  AS:   15.80:  -107.90:    -7.0:  3W:
+    3W,XV;
+Guinea:                   35:  46:  AF:   11.00:    10.68:     0.0:  3X:
+    3X;
+Bouvet:                   38:  67:  AF:  -54.42:    -3.38:    -1.0:  3Y/b:
+    =3Y0E;
+Peter 1 Island:           12:  72:  SA:  -68.77:    90.58:     4.0:  3Y/p:
+    =3Y0X;
+Azerbaijan:               21:  29:  AS:   40.45:   -47.37:    -4.0:  4J:
+    4J,4K;
+Georgia:                  21:  29:  AS:   42.00:   -45.00:    -4.0:  4L:
+    4L,UF6V;
+Montenegro:               15:  28:  EU:   42.50:   -19.28:    -1.0:  4O:
+    4O;
+Sri Lanka:                22:  41:  AS:    7.60:   -80.70:    -5.5:  4S:
+    4P,4Q,4R,4S;
+ITU HQ:                   14:  28:  EU:   46.17:    -6.05:    -1.0:  4U1I:
+    4U0I,4U1I,4U2I,4U3I,4U4I,4U5I,4U6I,4U7I,4U8I,4U9I,=4U1WRC;
+United Nations HQ:        05:  08:  NA:   40.75:    73.97:     5.0:  4U1U:
+    4U1U,=VERSION;
+Vienna Intl Ctr:          15:  28:  EU:   48.20:   -16.30:    -1.0:  *4U1V:
+    4U1V;
+Timor - Leste:            28:  54:  OC:   -8.80:  -126.05:    -9.0:  4W:
+    4W;
+Israel:                   20:  39:  AS:   31.32:   -34.82:    -2.0:  4X:
+    4X,4Z;
+Libya:                    34:  38:  AF:   27.20:   -16.60:    -2.0:  5A:
+    5A;
+Cyprus:                   20:  39:  AS:   35.00:   -33.00:    -2.0:  5B:
+    5B,C4,H2,P3;
+Tanzania:                 37:  53:  AF:   -5.75:   -33.92:    -3.0:  5H:
+    5H,5I;
+Nigeria:                  35:  46:  AF:    9.87:    -7.55:    -1.0:  5N:
+    5N,5O;
+Madagascar:               39:  53:  AF:  -19.00:   -46.58:    -3.0:  5R:
+    5R,5S,6X;
+Mauritania:               35:  46:  AF:   20.60:    10.50:     0.0:  5T:
+    5T;
+Niger:                    35:  46:  AF:   17.63:    -9.43:    -1.0:  5U:
+    5U;
+Togo:                     35:  46:  AF:    8.40:    -1.28:     0.0:  5V:
+    5V;
+Samoa:                    32:  62:  OC:  -13.93:   171.70:   -13.0:  5W:
+    5W;
+Uganda:                   37:  48:  AF:    1.92:   -32.60:    -3.0:  5X:
+    5X;
+Kenya:                    37:  48:  AF:    0.32:   -38.15:    -3.0:  5Z:
+    5Y,5Z;
+Senegal:                  35:  46:  AF:   15.20:    14.63:     0.0:  6W:
+    6V,6W;
+Jamaica:                  08:  11:  NA:   18.20:    77.47:     5.0:  6Y:
+    6Y;
+Yemen:                    21:  39:  AS:   15.65:   -48.12:    -3.0:  7O:
+    7O;
+Lesotho:                  38:  57:  AF:  -29.22:   -27.88:    -2.0:  7P:
+    7P;
+Malawi:                   37:  53:  AF:  -14.00:   -34.00:    -2.0:  7Q:
+    7Q;
+Algeria:                  33:  37:  AF:   28.00:    -2.00:    -1.0:  7X:
+    7R,7T,7U,7V,7W,7X,7Y;
+Barbados:                 08:  11:  NA:   13.18:    59.53:     4.0:  8P:
+    8P;
+Maldives:                 22:  41:  AS:    4.15:   -73.45:    -5.0:  8Q:
+    8Q;
+Guyana:                   09:  12:  SA:    6.02:    59.45:     4.0:  8R:
+    8R;
+Croatia:                  15:  28:  EU:   45.18:   -15.30:    -1.0:  9A:
+    9A;
+Ghana:                    35:  46:  AF:    7.70:     1.57:     0.0:  9G:
+    9G;
+Malta:                    15:  28:  EU:   35.88:   -14.42:    -1.0:  9H:
+    9H;
+Zambia:                   36:  53:  AF:  -14.22:   -26.73:    -2.0:  9J:
+    9I,9J;
+Kuwait:                   21:  39:  AS:   29.38:   -47.38:    -3.0:  9K:
+    9K,NLD;
+Sierra Leone:             35:  46:  AF:    8.50:    13.25:     0.0:  9L:
+    9L;
+West Malaysia:            28:  54:  AS:    3.95:  -102.23:    -8.0:  9M2:
+    9M2,9M4,9W2,9W4,=9M8DX/2;
+East Malaysia:            28:  54:  OC:    2.68:  -113.32:    -8.0:  9M6:
+    9M6,9M8,9M9,9W6,9W8,=9M4SAB;
+Nepal:                    22:  42:  AS:   27.70:   -85.33:   -5.75:  9N:
+    9N;
+Dem. Rep. of the Congo:   36:  52:  AF:   -3.12:   -23.03:    -1.0:  9Q:
+    9O,9P,9Q,9R,9S,9T;
+Burundi:                  36:  52:  AF:   -3.17:   -29.78:    -2.0:  9U:
+    9U;
+Singapore:                28:  54:  AS:    1.37:  -103.78:    -8.0:  9V:
+    9V,S6;
+Rwanda:                   36:  52:  AF:   -1.75:   -29.82:    -2.0:  9X:
+    9X;
+Trinidad & Tobago:        09:  11:  SA:   10.38:    61.28:     4.0:  9Y:
+    9Y,9Z;
+Botswana:                 38:  57:  AF:  -22.00:   -24.00:    -2.0:  A2:
+    8O,A2;
+Tonga:                    32:  62:  OC:  -21.22:   175.13:   -13.0:  A3:
+    A3;
+Oman:                     21:  39:  AS:   23.60:   -58.55:    -4.0:  A4:
+    A4;
+Bhutan:                   22:  41:  AS:   27.40:   -90.18:    -6.0:  A5:
+    A5;
+United Arab Emirates:     21:  39:  AS:   24.00:   -54.00:    -4.0:  A6:
+    A6;
+Qatar:                    21:  39:  AS:   25.25:   -51.13:    -3.0:  A7:
+    A7;
+Bahrain:                  21:  39:  AS:   26.03:   -50.53:    -3.0:  A9:
+    A9;
+Pakistan:                 21:  41:  AS:   30.00:   -70.00:    -5.0:  AP:
+    6P,6Q,6R,6S,AP,AQ,AR,AS;
+Scarborough Reef:         27:  50:  AS:   15.08:  -117.72:    -8.0:  BS7:
+    =BS7H;
+Taiwan:                   24:  44:  AS:   23.72:  -120.88:    -8.0:  BV:
+    BM,BN,BO,BP,BQ,BU,BV,BW,BX;
+Pratas Island:            24:  44:  AS:   20.70:  -116.70:    -8.0:  BV9P:
+    BM9P,BN9P,BO9P,BP9P,BQ9P,BU9P,BV9P,BW9P,BX9P;
+China:                    24:  44:  AS:   36.00:  -102.00:    -8.0:  BY:
+    3H,3H0(23)[42],3H9(23)[43],3I,3I0(23)[42],3I9(23)[43],3J,3J0(23)[42],
+    3J9(23)[43],3K,3K0(23)[42],3K9(23)[43],3L,3L0(23)[42],3L9(23)[43],3M,
+    3M0(23)[42],3M9(23)[43],3N,3N0(23)[42],3N9(23)[43],3O,3O0(23)[42],
+    3O9(23)[43],3P,3P0(23)[42],3P9(23)[43],3Q,3Q0(23)[42],3Q9(23)[43],3R,
+    3R0(23)[42],3R9(23)[43],3S,3S0(23)[42],3S9(23)[43],3T,3T0(23)[42],
+    3T9(23)[43],3U,3U0(23)[42],3U9(23)[43],B0(23)[42],B2,B3,B4,B5,B6,B7,B8,
+    B9(23)[43],BA,BA0(23)[42],BA9(23)[43],BD,BD0(23)[42],BD9(23)[43],BG,
+    BG0(23)[42],BG9(23)[43],BH,BH0(23)[42],BH9(23)[43],BI,BI0(23)[42],
+    BI9(23)[43],BJ,BJ0(23)[42],BJ9(23)[43],BL,BL0(23)[42],BL9(23)[43],BT,
+    BT0(23)[42],BT9(23)[43],BY,BY0(23)[42],BY9(23)[43],BZ,BZ0(23)[42],
+    BZ9(23)[43],XS,XS0(23)[42],XS9(23)[43],B1,B2A[33],B2B[33],B2C[33],B2D[33],
+    B2E[33],B2F[33],B2G[33],B2H[33],B2I[33],B2J[33],B2K[33],B2L[33],B2M[33],
+    B2N[33],B2O[33],B2P[33],B3G(23)[33],B3H(23)[33],B3I(23)[33],B3J(23)[33],
+    B3K(23)[33],B3L(23)[33],B6Q[43],B6R[43],B6S[43],B6T[43],B6U[43],B6V[43],
+    B6W[43],B6X[43],B7A[43],B7B[43],B7C[43],B7D[43],B7E[43],B7F[43],B7G[43],
+    B7H[43],B7Q[43],B7R[43],B7S[43],B7T[43],B7U[43],B7V[43],B7W[43],B7X[43],
+    B8A[43],B8B[43],B8C[43],B8D[43],B8E[43],B8F[43],B8G[43],B8H[43],B8I[43],
+    B8J[43],B8K[43],B8L[43],B8M[43],B8N[43],B8O[43],B8P[43],B8Q[43],B8R[43],
+    B8S[43],B8T[43],B8U[43],B8V[43],B8W[43],B8X[43],B9A(24)[43],B9B(24)[43],
+    B9C(24)[43],B9D(24)[43],B9E(24)[43],B9F(24)[43],B9S(23)[42],B9T(23)[42],
+    B9U(23)[42],B9V(23)[42],B9W(23)[42],B9X(23)[42],BA2A[33],BA2B[33],
+    BA2C[33],BA2D[33],BA2E[33],BA2F[33],BA2G[33],BA2H[33],BA2I[33],BA2J[33],
+    BA2K[33],BA2L[33],BA2M[33],BA2N[33],BA2O[33],BA2P[33],BA3G(23)[33],
+    BA3H(23)[33],BA3I(23)[33],BA3J(23)[33],BA3K(23)[33],BA3L(23)[33],BA6Q[43],
+    BA6R[43],BA6S[43],BA6T[43],BA6U[43],BA6V[43],BA6W[43],BA6X[43],BA7A[43],
+    BA7B[43],BA7C[43],BA7D[43],BA7E[43],BA7F[43],BA7G[43],BA7H[43],BA7Q[43],
+    BA7R[43],BA7S[43],BA7T[43],BA7U[43],BA7V[43],BA7W[43],BA7X[43],BA8A[43],
+    BA8B[43],BA8C[43],BA8D[43],BA8E[43],BA8F[43],BA8G[43],BA8H[43],BA8I[43],
+    BA8J[43],BA8K[43],BA8L[43],BA8M[43],BA8N[43],BA8O[43],BA8P[43],BA8Q[43],
+    BA8R[43],BA8S[43],BA8T[43],BA8U[43],BA8V[43],BA8W[43],BA8X[43],
+    BA9A(24)[43],BA9B(24)[43],BA9C(24)[43],BA9D(24)[43],BA9E(24)[43],
+    BA9F(24)[43],BA9S(23)[42],BA9T(23)[42],BA9U(23)[42],BA9V(23)[42],
+    BA9W(23)[42],BA9X(23)[42],BD2A[33],BD2B[33],BD2C[33],BD2D[33],BD2E[33],
+    BD2F[33],BD2G[33],BD2H[33],BD2I[33],BD2J[33],BD2K[33],BD2L[33],BD2M[33],
+    BD2N[33],BD2O[33],BD2P[33],BD3G(23)[33],BD3H(23)[33],BD3I(23)[33],
+    BD3J(23)[33],BD3K(23)[33],BD3L(23)[33],BD6Q[43],BD6R[43],BD6S[43],
+    BD6T[43],BD6U[43],BD6V[43],BD6W[43],BD6X[43],BD7A[43],BD7B[43],BD7C[43],
+    BD7D[43],BD7E[43],BD7F[43],BD7G[43],BD7H[43],BD7Q[43],BD7R[43],BD7S[43],
+    BD7T[43],BD7U[43],BD7V[43],BD7W[43],BD7X[43],BD8A[43],BD8B[43],BD8C[43],
+    BD8D[43],BD8E[43],BD8F[43],BD8G[43],BD8H[43],BD8I[43],BD8J[43],BD8K[43],
+    BD8L[43],BD8M[43],BD8N[43],BD8O[43],BD8P[43],BD8Q[43],BD8R[43],BD8S[43],
+    BD8T[43],BD8U[43],BD8V[43],BD8W[43],BD8X[43],BD9A(24)[43],BD9B(24)[43],
+    BD9C(24)[43],BD9D(24)[43],BD9E(24)[43],BD9F(24)[43],BD9S(23)[42],
+    BD9T(23)[42],BD9U(23)[42],BD9V(23)[42],BD9W(23)[42],BD9X(23)[42],BG2A[33],
+    BG2B[33],BG2C[33],BG2D[33],BG2E[33],BG2F[33],BG2G[33],BG2H[33],BG2I[33],
+    BG2J[33],BG2K[33],BG2L[33],BG2M[33],BG2N[33],BG2O[33],BG2P[33],
+    BG3G(23)[33],BG3H(23)[33],BG3I(23)[33],BG3J(23)[33],BG3K(23)[33],
+    BG3L(23)[33],BG6Q[43],BG6R[43],BG6S[43],BG6T[43],BG6U[43],BG6V[43],
+    BG6W[43],BG6X[43],BG7A[43],BG7B[43],BG7C[43],BG7D[43],BG7E[43],BG7F[43],
+    BG7G[43],BG7H[43],BG7Q[43],BG7R[43],BG7S[43],BG7T[43],BG7U[43],BG7V[43],
+    BG7W[43],BG7X[43],BG8A[43],BG8B[43],BG8C[43],BG8D[43],BG8E[43],BG8F[43],
+    BG8G[43],BG8H[43],BG8I[43],BG8J[43],BG8K[43],BG8L[43],BG8M[43],BG8N[43],
+    BG8O[43],BG8P[43],BG8Q[43],BG8R[43],BG8S[43],BG8T[43],BG8U[43],BG8V[43],
+    BG8W[43],BG8X[43],BG9A(24)[43],BG9B(24)[43],BG9C(24)[43],BG9D(24)[43],
+    BG9E(24)[43],BG9F(24)[43],BG9S(23)[42],BG9T(23)[42],BG9U(23)[42],
+    BG9V(23)[42],BG9W(23)[42],BG9X(23)[42],BH2A[33],BH2B[33],BH2C[33],
+    BH2D[33],BH2E[33],BH2F[33],BH2G[33],BH2H[33],BH2I[33],BH2J[33],BH2K[33],
+    BH2L[33],BH2M[33],BH2N[33],BH2O[33],BH2P[33],BH3G(23)[33],BH3H(23)[33],
+    BH3I(23)[33],BH3J(23)[33],BH3K(23)[33],BH3L(23)[33],BH6Q[43],BH6R[43],
+    BH6S[43],BH6T[43],BH6U[43],BH6V[43],BH6W[43],BH6X[43],BH7A[43],BH7B[43],
+    BH7C[43],BH7D[43],BH7E[43],BH7F[43],BH7G[43],BH7H[43],BH7Q[43],BH7R[43],
+    BH7S[43],BH7T[43],BH7U[43],BH7V[43],BH7W[43],BH7X[43],BH8A[43],BH8B[43],
+    BH8C[43],BH8D[43],BH8E[43],BH8F[43],BH8G[43],BH8H[43],BH8I[43],BH8J[43],
+    BH8K[43],BH8L[43],BH8M[43],BH8N[43],BH8O[43],BH8P[43],BH8Q[43],BH8R[43],
+    BH8S[43],BH8T[43],BH8U[43],BH8V[43],BH8W[43],BH8X[43],BH9A(24)[43],
+    BH9B(24)[43],BH9C(24)[43],BH9D(24)[43],BH9E(24)[43],BH9F(24)[43],
+    BH9S(23)[42],BH9T(23)[42],BH9U(23)[42],BH9V(23)[42],BH9W(23)[42],
+    BH9X(23)[42],BI2A[33],BI2B[33],BI2C[33],BI2D[33],BI2E[33],BI2F[33],
+    BI2G[33],BI2H[33],BI2I[33],BI2J[33],BI2K[33],BI2L[33],BI2M[33],BI2N[33],
+    BI2O[33],BI2P[33],BI3G(23)[33],BI3H(23)[33],BI3I(23)[33],BI3J(23)[33],
+    BI3K(23)[33],BI3L(23)[33],BI6Q[43],BI6R[43],BI6S[43],BI6T[43],BI6U[43],
+    BI6V[43],BI6W[43],BI6X[43],BI7A[43],BI7B[43],BI7C[43],BI7D[43],BI7E[43],
+    BI7F[43],BI7G[43],BI7H[43],BI7Q[43],BI7R[43],BI7S[43],BI7T[43],BI7U[43],
+    BI7V[43],BI7W[43],BI7X[43],BI8A[43],BI8B[43],BI8C[43],BI8D[43],BI8E[43],
+    BI8F[43],BI8G[43],BI8H[43],BI8I[43],BI8J[43],BI8K[43],BI8L[43],BI8M[43],
+    BI8N[43],BI8O[43],BI8P[43],BI8Q[43],BI8R[43],BI8S[43],BI8T[43],BI8U[43],
+    BI8V[43],BI8W[43],BI8X[43],BI9A(24)[43],BI9B(24)[43],BI9C(24)[43],
+    BI9D(24)[43],BI9E(24)[43],BI9F(24)[43],BI9S(23)[42],BI9T(23)[42],
+    BI9U(23)[42],BI9V(23)[42],BI9W(23)[42],BI9X(23)[42],BJ2A[33],BJ2B[33],
+    BJ2C[33],BJ2D[33],BJ2E[33],BJ2F[33],BJ2G[33],BJ2H[33],BJ2I[33],BJ2J[33],
+    BJ2K[33],BJ2L[33],BJ2M[33],BJ2N[33],BJ2O[33],BJ2P[33],BJ3G(23)[33],
+    BJ3H(23)[33],BJ3I(23)[33],BJ3J(23)[33],BJ3K(23)[33],BJ3L(23)[33],BJ6Q[43],
+    BJ6R[43],BJ6S[43],BJ6T[43],BJ6U[43],BJ6V[43],BJ6W[43],BJ6X[43],BJ7A[43],
+    BJ7B[43],BJ7C[43],BJ7D[43],BJ7E[43],BJ7F[43],BJ7G[43],BJ7H[43],BJ7Q[43],
+    BJ7R[43],BJ7S[43],BJ7T[43],BJ7U[43],BJ7V[43],BJ7W[43],BJ7X[43],BJ8A[43],
+    BJ8B[43],BJ8C[43],BJ8D[43],BJ8E[43],BJ8F[43],BJ8G[43],BJ8H[43],BJ8I[43],
+    BJ8J[43],BJ8K[43],BJ8L[43],BJ8M[43],BJ8N[43],BJ8O[43],BJ8P[43],BJ8Q[43],
+    BJ8R[43],BJ8S[43],BJ8T[43],BJ8U[43],BJ8V[43],BJ8W[43],BJ8X[43],
+    BJ9A(24)[43],BJ9B(24)[43],BJ9C(24)[43],BJ9D(24)[43],BJ9E(24)[43],
+    BJ9F(24)[43],BJ9S(23)[42],BJ9T(23)[42],BJ9U(23)[42],BJ9V(23)[42],
+    BJ9W(23)[42],BJ9X(23)[42],BL2A[33],BL2B[33],BL2C[33],BL2D[33],BL2E[33],
+    BL2F[33],BL2G[33],BL2H[33],BL2I[33],BL2J[33],BL2K[33],BL2L[33],BL2M[33],
+    BL2N[33],BL2O[33],BL2P[33],BL3G(23)[33],BL3H(23)[33],BL3I(23)[33],
+    BL3J(23)[33],BL3K(23)[33],BL3L(23)[33],BL6Q[43],BL6R[43],BL6S[43],
+    BL6T[43],BL6U[43],BL6V[43],BL6W[43],BL6X[43],BL7A[43],BL7B[43],BL7C[43],
+    BL7D[43],BL7E[43],BL7F[43],BL7G[43],BL7H[43],BL7Q[43],BL7R[43],BL7S[43],
+    BL7T[43],BL7U[43],BL7V[43],BL7W[43],BL7X[43],BL8A[43],BL8B[43],BL8C[43],
+    BL8D[43],BL8E[43],BL8F[43],BL8G[43],BL8H[43],BL8I[43],BL8J[43],BL8K[43],
+    BL8L[43],BL8M[43],BL8N[43],BL8O[43],BL8P[43],BL8Q[43],BL8R[43],BL8S[43],
+    BL8T[43],BL8U[43],BL8V[43],BL8W[43],BL8X[43],BL9A(24)[43],BL9B(24)[43],
+    BL9C(24)[43],BL9D(24)[43],BL9E(24)[43],BL9F(24)[43],BL9S(23)[42],
+    BL9T(23)[42],BL9U(23)[42],BL9V(23)[42],BL9W(23)[42],BL9X(23)[42],BT2A[33],
+    BT2B[33],BT2C[33],BT2D[33],BT2E[33],BT2F[33],BT2G[33],BT2H[33],BT2I[33],
+    BT2J[33],BT2K[33],BT2L[33],BT2M[33],BT2N[33],BT2O[33],BT2P[33],
+    BT3G(23)[33],BT3H(23)[33],BT3I(23)[33],BT3J(23)[33],BT3K(23)[33],
+    BT3L(23)[33],BT6Q[43],BT6R[43],BT6S[43],BT6T[43],BT6U[43],BT6V[43],
+    BT6W[43],BT6X[43],BT7A[43],BT7B[43],BT7C[43],BT7D[43],BT7E[43],BT7F[43],
+    BT7G[43],BT7H[43],BT7Q[43],BT7R[43],BT7S[43],BT7T[43],BT7U[43],BT7V[43],
+    BT7W[43],BT7X[43],BT8A[43],BT8B[43],BT8C[43],BT8D[43],BT8E[43],BT8F[43],
+    BT8G[43],BT8H[43],BT8I[43],BT8J[43],BT8K[43],BT8L[43],BT8M[43],BT8N[43],
+    BT8O[43],BT8P[43],BT8Q[43],BT8R[43],BT8S[43],BT8T[43],BT8U[43],BT8V[43],
+    BT8W[43],BT8X[43],BT9A(24)[43],BT9B(24)[43],BT9C(24)[43],BT9D(24)[43],
+    BT9E(24)[43],BT9F(24)[43],BT9S(23)[42],BT9T(23)[42],BT9U(23)[42],
+    BT9V(23)[42],BT9W(23)[42],BT9X(23)[42],BY2A[33],BY2B[33],BY2C[33],
+    BY2D[33],BY2E[33],BY2F[33],BY2G[33],BY2H[33],BY2I[33],BY2J[33],BY2K[33],
+    BY2L[33],BY2M[33],BY2N[33],BY2O[33],BY2P[33],BY3G(23)[33],BY3H(23)[33],
+    BY3I(23)[33],BY3J(23)[33],BY3K(23)[33],BY3L(23)[33],BY6Q[43],BY6R[43],
+    BY6S[43],BY6T[43],BY6U[43],BY6V[43],BY6W[43],BY6X[43],BY7A[43],BY7B[43],
+    BY7C[43],BY7D[43],BY7E[43],BY7F[43],BY7G[43],BY7H[43],BY7Q[43],BY7R[43],
+    BY7S[43],BY7T[43],BY7U[43],BY7V[43],BY7W[43],BY7X[43],BY8A[43],BY8B[43],
+    BY8C[43],BY8D[43],BY8E[43],BY8F[43],BY8G[43],BY8H[43],BY8I[43],BY8J[43],
+    BY8K[43],BY8L[43],BY8M[43],BY8N[43],BY8O[43],BY8P[43],BY8Q[43],BY8R[43],
+    BY8S[43],BY8T[43],BY8U[43],BY8V[43],BY8W[43],BY8X[43],BY9A(24)[43],
+    BY9B(24)[43],BY9C(24)[43],BY9D(24)[43],BY9E(24)[43],BY9F(24)[43],
+    BY9S(23)[42],BY9T(23)[42],BY9U(23)[42],BY9V(23)[42],BY9W(23)[42],
+    BY9X(23)[42],BZ2A[33],BZ2B[33],BZ2C[33],BZ2D[33],BZ2E[33],BZ2F[33],
+    BZ2G[33],BZ2H[33],BZ2I[33],BZ2J[33],BZ2K[33],BZ2L[33],BZ2M[33],BZ2N[33],
+    BZ2O[33],BZ2P[33],BZ3G(23)[33],BZ3H(23)[33],BZ3I(23)[33],BZ3J(23)[33],
+    BZ3K(23)[33],BZ3L(23)[33],BZ6Q[43],BZ6R[43],BZ6S[43],BZ6T[43],BZ6U[43],
+    BZ6V[43],BZ6W[43],BZ6X[43],BZ7A[43],BZ7B[43],BZ7C[43],BZ7D[43],BZ7E[43],
+    BZ7F[43],BZ7G[43],BZ7H[43],BZ7Q[43],BZ7R[43],BZ7S[43],BZ7T[43],BZ7U[43],
+    BZ7V[43],BZ7W[43],BZ7X[43],BZ8A[43],BZ8B[43],BZ8C[43],BZ8D[43],BZ8E[43],
+    BZ8F[43],BZ8G[43],BZ8H[43],BZ8I[43],BZ8J[43],BZ8K[43],BZ8L[43],BZ8M[43],
+    BZ8N[43],BZ8O[43],BZ8P[43],BZ8Q[43],BZ8R[43],BZ8S[43],BZ8T[43],BZ8U[43],
+    BZ8V[43],BZ8W[43],BZ8X[43],BZ9A(24)[43],BZ9B(24)[43],BZ9C(24)[43],
+    BZ9D(24)[43],BZ9E(24)[43],BZ9F(24)[43],BZ9S(23)[42],BZ9T(23)[42],
+    BZ9U(23)[42],BZ9V(23)[42],BZ9W(23)[42],BZ9X(23)[42];
+Nauru:                    31:  65:  OC:   -0.52:  -166.92:   -12.0:  C2:
+    C2;
+Andorra:                  14:  27:  EU:   42.58:    -1.62:    -1.0:  C3:
+    C3;
+The Gambia:               35:  46:  AF:   13.40:    16.38:     0.0:  C5:
+    C5;
+Bahamas:                  08:  11:  NA:   24.25:    76.00:     5.0:  C6:
+    C6;
+Mozambique:               37:  53:  AF:  -18.25:   -35.00:    -2.0:  C9:
+    C8,C9;
+Chile:                    12:  14:  SA:  -30.00:    71.00:     4.0:  CE:
+    3G,CA,CB,CC,CD,CE,XQ,XR,3G7[16],3G8[16],CA7[16],CA8[16],CB7[16],CB8[16],
+    CC7[16],CC8[16],CD7[16],CD8[16],CE7[16],CE8[16],XQ7[16],XQ8[16],XR7[16],
+    XR8[16];
+San Felix & San Ambrosio: 12:  14:  SA:  -26.28:    80.07:     4.0:  CE0X:
+    3G0X,CA0X,CB0X,CC0X,CD0X,CE0X,XQ0X,XR0X;
+Easter Island:            12:  63:  SA:  -27.10:   109.37:     6.0:  CE0Y:
+    3G0,CA0,CB0,CC0,CD0,CE0,XQ0,XR0;
+Juan Fernandez Islands:   12:  14:  SA:  -33.60:    78.85:     4.0:  CE0Z:
+    3G0Z,CA0Z,CB0Z,CC0Z,CD0Z,CE0Z,XQ0Z,XR0Z;
+Antarctica:               13:  74:  SA:  -90.00:     0.00:     0.0:  CE9:
+    3Y[73],ANT(29)[69],AX0(39)[69],AY1Z[73],AY2Z[73],AY3Z[73],AY4Z[73],
+    AY5Z[73],AY6Z[73],AY7Z[73],AY8Z[73],AY9Z[73],FT0Y(30)[70],FT1Y(30)[70],
+    FT2Y(30)[70],FT4Y(30)[70],FT5Y(30)[70],FT8Y(30)[70],LU1Z[73],LU2Z[73],
+    LU3Z[73],LU4Z[73],LU5Z[73],LU6Z[73],LU7Z[73],LU8Z[73],LU9Z[73],
+    R1AN(29)[69],RI1AN(29)[69],VI0(39)[69],VK0(39)[69],ZL5(30)[71],
+    ZM5(30)[71],ZS7(38)[67],=K9PET/KC4,=8J1RL(39)[67],=DP0GVN(38)[67],
+    =DP1POL(38)[67],=KC4AAA(39),=KC4AAC[73],=KC4USA(30)[71],=KC4USV(30)[71],
+    =OJ1ABOA(38)[67],=RI1ANP(39)[69],=RI1ANR(38)[67],=VP8ADE/B[73],
+    =VP8DLM[73];
+Cuba:                     08:  11:  NA:   21.50:    80.00:     5.0:  CM:
+    CL,CM,CO,T4;
+Morocco:                  33:  37:  AF:   32.00:     5.00:     0.0:  CN:
+    5C,5D,5E,5F,5G,CN;
+Bolivia:                  10:  12:  SA:  -17.00:    65.00:     4.0:  CP:
+    CP,CP2[14],CP3[14],CP4[14],CP5[14],CP6[14],CP7[14];
+Portugal:                 14:  37:  EU:   39.50:     8.00:     0.0:  CT:
+    CQ,CR,CS,CT;
+Madeira Islands:          33:  36:  AF:   32.75:    16.95:     0.0:  CT3:
+    CQ2,CQ3,CQ9,CR3,CR9,CS3,CS9,CT3,CT9;
+Azores:                   14:  36:  EU:   38.70:    27.23:     1.0:  CU:
+    CQ1,CQ8,CR1,CR2,CR8,CS4,CS8,CT8,CU;
+Uruguay:                  13:  14:  SA:  -33.00:    56.00:     3.0:  CX:
+    CV,CW,CX;
+Sable Island:             05:  09:  NA:   43.93:    59.90:     4.0:  CY0:
+    CY0;
+St. Paul Island:          05:  09:  NA:   47.00:    60.00:     4.0:  CY9:
+    CY9;
+Angola:                   36:  52:  AF:  -12.50:   -18.50:    -1.0:  D2:
+    D2,D3;
+Cape Verde:               35:  46:  AF:   16.00:    24.00:     1.0:  D4:
+    D4;
+Comoros:                  39:  53:  AF:  -11.63:   -43.30:    -3.0:  D6:
+    D6;
+Fed. Rep. of Germany:     14:  28:  EU:   51.00:   -10.00:    -1.0:  DL:
+    DA,DB,DC,DD,DE,DF,DG,DH,DI,DJ,DK,DL,DM,DN,DO,DP,DQ,DR;
+Philippines:              27:  50:  OC:   13.00:  -122.00:    -8.0:  DU:
+    4D,4E,4F,4G,4H,4I,DU,DV,DW,DX,DY,DZ;
+Eritrea:                  37:  48:  AF:   15.00:   -39.00:    -3.0:  E3:
+    E3;
+Palestine:                20:  39:  AS:   31.28:   -34.27:    -2.0:  E4:
+    E4;
+North Cook Islands:       32:  62:  OC:  -10.02:   161.08:    10.0:  E5/n:
+    =E51WL[63];
+South Cook Islands:       32:  63:  OC:  -21.90:   157.93:    10.0:  E5/s:
+    E5;
+Niue:                     32:  62:  OC:  -19.03:   169.85:    11.0:  E6:
+    E6;
+Bosnia-Herzegovina:       15:  28:  EU:   44.32:   -17.57:    -1.0:  E7:
+    E7;
+Spain:                    14:  37:  EU:   40.37:     4.88:    -1.0:  EA:
+    AM,AN,AO,EA,EB,EC,ED,EE,EF,EG,EH;
+Balearic Islands:         14:  37:  EU:   39.60:    -2.95:    -1.0:  EA6:
+    AM6,AN6,AO6,EA6,EB6,EC6,ED6,EE6,EF6,EG6,EH6;
+Canary Islands:           33:  36:  AF:   28.10:    15.40:     0.0:  EA8:
+    AM8,AN8,AO8,EA8,EB8,EC8,ED8,EE8,EF8,EG8,EH8,=EA5RKL/8;
+Ceuta & Melilla:          33:  37:  AF:   35.90:     5.27:    -1.0:  EA9:
+    AM9,AN9,AO9,EA9,EB9,EC9,ED9,EE9,EF9,EG9,EH9;
+Ireland:                  14:  27:  EU:   53.13:     8.02:     0.0:  EI:
+    EI,EJ;
+Armenia:                  21:  29:  AS:   40.40:   -44.90:    -4.0:  EK:
+    EK;
+Liberia:                  35:  46:  AF:    6.50:     9.50:     0.0:  EL:
+    5L,5M,6Z,A8,D5,EL;
+Iran:                     21:  40:  AS:   32.00:   -53.00:    -3.5:  EP:
+    9B,9C,9D,EP,EQ;
+Moldova:                  16:  29:  EU:   47.00:   -29.00:    -2.0:  ER:
+    ER;
+Estonia:                  15:  29:  EU:   59.00:   -25.00:    -2.0:  ES:
+    ES;
+Ethiopia:                 37:  48:  AF:    9.00:   -39.00:    -3.0:  ET:
+    9E,9F,ET;
+Belarus:                  16:  29:  EU:   54.00:   -28.00:    -2.0:  EU:
+    EU,EV,EW;
+Kyrgyzstan:               17:  30:  AS:   41.70:   -74.13:    -6.0:  EX:
+    EX,EX2P[31],EX2Q[31],EX6P[31],EX6Q[31],EX7P[31],EX7Q[31],EX8P[31],
+    EX8Q[31];
+Tajikistan:               17:  30:  AS:   38.82:   -71.22:    -5.0:  EY:
+    EY;
+Turkmenistan:             17:  30:  AS:   38.00:   -58.00:    -5.0:  EZ:
+    EZ;
+France:                   14:  27:  EU:   46.00:    -2.00:    -1.0:  F:
+    F,HW,HX,HY,TH,TM,TP,TQ,TV,=F6KBG/MSW;
+Guadeloupe:               08:  11:  NA:   16.13:    61.67:     4.0:  FG:
+    FG;
+Mayotte:                  39:  53:  AF:  -12.88:   -45.15:    -3.0:  FH:
+    FH;
+St. Barthelemy:           08:  11:  NA:   17.90:    62.83:     4.0:  FJ:
+    FJ;
+New Caledonia:            32:  56:  OC:  -21.50:  -165.50:   -11.0:  FK:
+    FK;
+Chesterfield Islands:     30:  56:  OC:  -19.87:  -158.32:   -11.0:  FK/c:
+    =FK8IK/C;
+Martinique:               08:  11:  NA:   14.70:    61.03:     4.0:  FM:
+    FM,=TO5A,=TO5K,=TO5T,=TO7A;
+French Polynesia:         32:  63:  OC:  -17.65:   149.40:    10.0:  FO:
+    FO;
+Austral Islands:          32:  63:  OC:  -23.37:   149.48:    10.0:  FO/a:
+    =FO/KH0PR;
+Clipperton Island:        07:  10:  NA:   10.28:   109.22:     8.0:  FO/c:
+    =TX5K;
+Marquesas Islands:        31:  63:  OC:   -8.92:   140.07:     9.5:  FO/m:
+    =FO/UT6UD;
+St. Pierre & Miquelon:    05:  09:  NA:   46.77:    56.20:     3.0:  FP:
+    FP;
+Reunion Island:           39:  53:  AF:  -21.12:   -55.48:    -4.0:  FR:
+    FR,=TO1PF,=TO1PF/P;
+Glorioso Islands:         39:  53:  AF:  -11.55:   -47.28:    -4.0:  FR/g:
+    FT5G;
+Juan de Nova, Europa:     39:  53:  AF:  -17.05:   -42.72:    -3.0:  FR/j:
+    FT5E,FT5J;
+Tromelin Island:          39:  53:  AF:  -15.88:   -54.50:    -4.0:  FR/t:
+    FT5T;
+St. Martin:               08:  11:  NA:   18.08:    63.03:     4.0:  FS:
+    FS;
+Crozet Island:            39:  68:  AF:  -46.42:   -51.75:    -5.0:  FT5W:
+    FT0W,FT1W,FT2W,FT4W,FT5W,FT8W;
+Kerguelen Islands:        39:  68:  AF:  -49.00:   -69.27:    -5.0:  FT5X:
+    FT0X,FT1X,FT2X,FT4X,FT5X,FT8X;
+Amsterdam & St. Paul Is.: 39:  68:  AF:  -37.85:   -77.53:    -5.0:  FT5Z:
+    FT0Z,FT1Z,FT2Z,FT4Z,FT5Z,FT8Z;
+Wallis & Futuna Islands:  32:  62:  OC:  -13.30:   176.20:   -12.0:  FW:
+    FW,TW;
+French Guiana:            09:  12:  SA:    4.00:    53.00:     3.0:  FY:
+    FY;
+England:                  14:  27:  EU:   52.77:     1.47:     0.0:  G:
+    2,G,M,ZH,ZI,ZJ,=GB2SNM/MILL,=GB6MW/MILL;
+Isle of Man:              14:  27:  EU:   54.20:     4.53:     0.0:  GD:
+    2D,2T,GD,GT,MD,MT,=2V0IOM,=2V0YLX,=GB4JDF,=GV6AFB;
+Northern Ireland:         14:  27:  EU:   54.73:     6.68:     0.0:  GI:
+    2I,2N,GI,GN,MI,MN,=2V0CSB,=2V0IVG,=GB0GPF,=GB0REL,=GB1SPD,=GB2DMR,=GB2LOL,
+    =GB2MAC,=GB2UAS,=GB4SPD,=GB5SPD,=GV3KVD,=GV3SG,=GV4FUE,=GV4GUH,=GV4JTF,
+    =GV4SRQ,=GV7THH,=MV0ALS,=MV0GGB,=MV0JFC,=MV0JLC,=MV0MOD,=MV0MSR,=MV0VAX,
+    =MV0WGM,=MV1VOX,=MV6DTE,=MV6NIR,=MV6TLG;
+Jersey:                   14:  27:  EU:   49.22:     2.18:     0.0:  GJ:
+    2H,2J,GH,GJ,MH,MJ,=MV0ASP;
+Scotland:                 14:  27:  EU:   56.82:     4.18:     0.0:  GM:
+    2A,2M,2S,GA,GM,GS,MA,MM,MS,=2V0JCH,=2V0KAU,=GB0BSS,=GB0GDS,=GB0GGR,
+    =GB0NHL,=GB0POS,=GB1AJ,=GB1FHS,=GB1OL,=GB1RB,=GB2ATC,=GB2BHM,=GB2CHC,
+    =GB2EPC,=GB2GKR,=GB2GNL,=GB2LBN,=GB2LT,=GB2MOF,=GB2OL,=GB2OWM,=GB2SQN,
+    =GB2SR,=GB2VCB,=GB3ANG,=GB4GS,=GB5AG,=GM4WSB/P,=GV0DBW,=GV0GMN,=GV0GRD,
+    =GV0OBX,=GV0OGN,=GV1BAN,=GV3NNZ,=GV4BLO,=GV4EMX,=GV4HRJ,=GV4JOJ,=GV4XQJ,
+    =GV7DHA,=GV7GMC,=GV8AVM,=GV8DPV,=MV0FMF,=MV0GHM,=MV0LGS,=MV0NFC,=MV0NJS,
+    =MV0XXW,=MV3BRR,=MV3YHA,=MV5PSL,=MV6BJJ,=MV6KSJ;
+Shetland and Fair Isle:   14:  27:  EU:   60.50:     1.50:     0.0:  *GM/s:
+    2Z,GZ,MZ,=2M0ZET,=2M1ANT,=2M1ASQ,=2M1ODL,=G0FBJ,=GB2ELH,=GB2QM,=GB2SB,
+    =GB2ZET,=GB3LER,=GB3LER/B,=GB4LER,=GB4SI,=GM0CXQ,=GM0CYJ,=GM0DJI,=GM0EKM,
+    =GM0ILB,=GM0JDB,=GM0MZD,=GM0OMV,=GM0VFA,=GM1BYL,=GM1CBQ,=GM1KKI,=GM1MXN,
+    =GM1ZNR,=GM3KLA,=GM3KZH,=GM3RFR,=GM3SJA,=GM3STU,=GM3UPU,=GM3WCH,=GM3WHT,
+    =GM3XPQ,=GM3ZET,=GM3ZNM,=GM3ZXH,=GM4AGX,=GM4CAQ,=GM4DQD,=GM4ENK,=GM4FNA,
+    =GM4FNE,=GM4GPN,=GM4GPP,=GM4GQD,=GM4GQM,=GM4IPK,=GM4JPI,=GM4KJQ,=GM4LBE,
+    =GM4LER,=GM4PXG,=GM4SLV,=GM4SRU,=GM4SSA,=GM4SWU,=GM4WXQ,=GM4YEL,=GM4ZHL,
+    =GM6RTO,=GM6VZB,=GM6WVI,=GM6YQA,=GM7AFE,=GM7GWW,=GM7RKD,=GM8LNH,=GM8MMA,
+    =GM8YEC,=GS3ZET,=MA1FJM,=MM0LSM,=MM0XAU,=MM0ZAL,=MM0ZCG,=MM1FJM,=MM3ZET,
+    =MM5PSL,=MM6ACW,=MM6BDU,=MM6SJK,=MS0ZCG,=MS0ZET;
+Guernsey:                 14:  27:  EU:   49.45:     2.58:     0.0:  GU:
+    2P,2U,GP,GU,MP,MU,=GB2JTA;
+Wales:                    14:  27:  EU:   52.28:     3.73:     0.0:  GW:
+    2C,2W,2X,2Y,GC,GW,MC,MW,=2V0CDY,=2V0CGM,=2V0KED,=2V0WDS,=GB0APS,=GB0AWS,
+    =GB0CFD,=GB0MPA,=GB0TS,=GB1BW,=GB1PD,=GB2FLB,=GB2GGM,=GB2IMD,=GB2LSA,
+    =GB4MBC,=GB4MDI,=GB4OST,=GB4PAT,=GB4SDD,=GB5GEO,=GB6BLB,=GB8CCC,=GV0ANA,
+    =GV0DIV,=GV0FRE,=GV0MNP,=GV0NPL,=GV1IOT,=GV1JFV,=GV1YQM,=GV3ATZ,=GV3UOF,
+    =GV3XQJ,=GV4BKG,=GV4NQJ,=GV7UNV,=GV8IQC,=MV0EDX,=MV0GWT,=MV0TDQ,=MV0UAA,
+    =MV0USK,=MV0WYN,=MV1CFN,=MV3RNI,=MV6GWR,=MV6URC,=MV6ZOL;
+Solomon Islands:          28:  51:  OC:   -9.00:  -160.00:   -11.0:  H4:
+    H4;
+Temotu Province:          32:  51:  OC:  -10.72:  -165.80:   -11.0:  H40:
+    H40;
+Hungary:                  15:  28:  EU:   47.12:   -19.28:    -1.0:  HA:
+    HA,HG;
+Switzerland:              14:  28:  EU:   46.87:    -8.12:    -1.0:  HB:
+    HB,HE;
+Liechtenstein:            14:  28:  EU:   47.13:    -9.57:    -1.0:  HB0:
+    HB0,HE0;
+Ecuador:                  10:  12:  SA:   -1.40:    78.40:     6.0:  HC:
+    HC,HD;
+Galapagos Islands:        10:  12:  SA:   -0.78:    91.03:     6.0:  HC8:
+    HC8,HD8,=HC2AO/8,=HC2IWM/8;
+Haiti:                    08:  11:  NA:   19.02:    72.18:     5.0:  HH:
+    4V,HH;
+Dominican Republic:       08:  11:  NA:   19.13:    70.68:     4.0:  HI:
+    HI;
+Colombia:                 09:  12:  SA:    5.00:    74.00:     5.0:  HK:
+    5J,5K,HJ,HK;
+San Andres & Providencia: 07:  11:  NA:   12.55:    81.72:     5.0:  HK0/a:
+    5J0,5K0,HJ0,HK0;
+Malpelo Island:           09:  12:  SA:    3.98:    81.58:     5.0:  HK0/m:
+    5J0M,5K0M,HJ0M,HK0M,=HK0TU;
+Republic of Korea:        25:  44:  AS:   36.23:  -127.90:    -9.0:  HL:
+    6K,6L,6M,6N,D7,D8,D9,DS,DT,HL,KL9K;
+Panama:                   07:  11:  NA:    9.00:    80.00:     5.0:  HP:
+    3E,3F,H3,H8,H9,HO,HP;
+Honduras:                 07:  11:  NA:   15.00:    87.00:     6.0:  HR:
+    HQ,HR;
+Thailand:                 26:  49:  AS:   12.60:   -99.70:    -7.0:  HS:
+    E2,HS;
+Vatican City:             15:  28:  EU:   41.90:   -12.47:    -1.0:  HV:
+    HV;
+Saudi Arabia:             21:  39:  AS:   24.20:   -43.83:    -3.0:  HZ:
+    7Z,8Z,HZ;
+Italy:                    15:  28:  EU:   42.82:   -12.58:    -1.0:  I:
+    I,=4U1GSC;
+African Italy:            33:  37:  AF:   35.67:   -12.67:    -1.0:  *IG9:
+    IG9,IH9;
+Sardinia:                 15:  28:  EU:   40.15:    -9.27:    -1.0:  IS:
+    IM0,IS,IW0U,IW0V,IW0W,IW0X,IW0Y,IW0Z,=IQ0AH,=IQ0ID,=IQ0SS,=IY0GA;
+Sicily:                   15:  28:  EU:   37.50:   -14.00:    -1.0:  *IT9:
+    IB9,ID9,IE9,IF9,II9,IJ9,IO9,IQ9,IR9,IT9,IU9,IW9;
+Djibouti:                 37:  48:  AF:   11.75:   -42.35:    -3.0:  J2:
+    J2;
+Grenada:                  08:  11:  NA:   12.13:    61.68:     4.0:  J3:
+    J3;
+Guinea-Bissau:            35:  46:  AF:   12.02:    14.80:     0.0:  J5:
+    J5;
+St. Lucia:                08:  11:  NA:   13.87:    61.00:     4.0:  J6:
+    J6;
+Dominica:                 08:  11:  NA:   15.43:    61.35:     4.0:  J7:
+    J7;
+St. Vincent:              08:  11:  NA:   13.23:    61.20:     4.0:  J8:
+    J8;
+Japan:                    25:  45:  AS:   36.40:  -138.38:    -9.0:  JA:
+    7J,7K,7L,7M,7N,8J,8K,8L,8M,8N,JA,JE,JF,JG,JH,JI,JJ,JK,JL,JM,JN,JO,JP,JQ,
+    JR,JS;
+Minami Torishima:         27:  90:  OC:   24.28:  -153.97:   -10.0:  JD/m:
+    =JD1BMM,=JD1YAA;
+Ogasawara:                27:  45:  AS:   27.05:  -142.20:    -9.0:  JD/o:
+    JD1;
+Mongolia:                 23:  32:  AS:   46.77:  -102.17:    -7.0:  JT:
+    JT,JU,JV,JT2[33],JT3[33],JU2[33],JU3[33],JV2[33],JV3[33];
+Svalbard:                 40:  18:  EU:   78.00:   -16.00:    -1.0:  JW:
+    JW;
+Bear Island:              40:  18:  EU:   74.43:   -19.08:    -1.0:  *JW/b:
+    =JW9JKA;
+Jan Mayen:                40:  18:  EU:   71.05:     8.28:     1.0:  JX:
+    JX;
+Jordan:                   20:  39:  AS:   31.18:   -36.42:    -2.0:  JY:
+    JY;
+United States:            05:  08:  NA:   37.53:    91.67:     5.0:  K:
+    AA,AB,AC,AD,AE,AF,AG,AI,AJ,AK,K,N,W,=4U1WB(5)[8],=AA4DD(4)[8],=AA4R(4)[8],
+    =AA4YL(4)[8],=AB4GG(4)[8],=AB4IQ(4)[8],=AB9DU(5)[8],=AC4CA(4)[7],
+    =AC4G(4)[8],=AC4YD(4)[8],=AC8DU(5)[8],=AC8Y(5)[8],=AD1C(4)[7],
+    =AD4EB(4)[8],=AD7MQ(4)[6],=AD8J(5)[8],=AE7AP(4)[6],=AF4AI(4)[8],
+    =AG4W(4)[8],=AI4DB(4)[8],=AJ4A(4)[8],=AK4QU(4)[8],=AL7RF(3)[6],
+    =K0DQ(5)[8],=K0IP(3)[6],=K0JJ(3)[6],=K0LUZ(5)[8],=K0NW(3)[6],=K0TQ(4)[8],
+    =K0TV(5)[8],=K0ZR(5)[8],=K1DW(4)[7],=K1GU(4)[8],=K1KD(4)[7],=K1LT(4)[8],
+    =K1TN(4)[8],=K2AVI(3)[6],=K2FF(4)[7],=K2HT(4)[7],=K2PO(3)[6],=K2RD(3)[6],
+    =K2RP(3)[6],=K2UR(4)[8],=K3FIV(3)[6],=K3GP(4)[8],=K3IE(4)[8],=K3WA(4)[8],
+    =K3WT(4)[7],=K3YP(4)[8],=K4AB(4)[8],=K4AMC(4)[8],=K4BP(4)[8],=K4BX(4)[8],
+    =K4CX(4)[8],=K4DZR(4)[8],=K4EDI(4)[8],=K4EJQ(4)[8],=K4FT(4)[8],
+    =K4FXN(4)[8],=K4HAL(4)[8],=K4IE(4)[8],=K4IQJ(4)[8],=K4IU(4)[7],
+    =K4LTA(4)[8],=K4MCK(4)[8],=K4MGE(4)[8],=K4RO(4)[8],=K4SPO(4)[8],
+    =K4TD(4)[8],=K4WI(4)[8],=K4WW(4)[8],=K4ZGB(4)[8],=K4ZHM(4)[8],
+    =K5AUP(5)[8],=K5EK(5)[8],=K5KG(5)[8],=K5OA(3)[6],=K5RQ(5)[8],=K5RR(3)[6],
+    =K5VIP(5)[8],=K5WP(4)[8],=K5ZD(5)[8],=K6ND(5)[8],=K6SXA(4)[7],=K6XT(4)[7],
+    =K7ABV(4)[6],=K7BG(4)[6],=K7CS(5)[8],=K7IA(4)[7],=K7KU(4)[7],=K7OM(5)[8],
+    =K7RB(4)[7],=K7RE(4)[7],=K7SCX(4)[7],=K7SV(5)[8],=K7TD(4)[7],=K7VK(4)[6],
+    =K7VU(4)[7],=K8CN(5)[8],=K8GU(5)[8],=K8IA(3)[6],=K8JQ(5)[8],=K8LF(5)[8],
+    =K8MN(5)[8],=K8NYG(5)[8],=K8PO(5)[8],=K8TE(4)[7],=K8WT(5)[8],=K8YC(5)[8],
+    =K9AIH(5)[8],=K9BWI(4)[7],=K9CHP(5)[8],=K9DR(4)[7],=K9DU(4)[7],
+    =K9FY(5)[8],=K9JF(3)[6],=K9JM(3)[6],=K9JWV(3)[6],=K9MWM(4)[7],=K9OM(5)[8],
+    =K9RS(5)[8],=K9SG(3)[6],=K9WZB(3)[6],=K9YC(3)[6],=KA3DRR(3)[6],
+    =KA4OTB(4)[8],=KA4PKB(4)[8],=KA4R(4)[8],=KA8HDE(4)[7],=KA8Q(5)[8],
+    =KB5EZ(4)[8],=KB5JC(5)[8],=KB7FSC(4)[6],=KB7Q(4)[6],=KB8V(5)[8],
+    =KC4HW(4)[8],=KC4SAW(4)[8],=KC4WQ(4)[8],=KC6X(4)[7],=KC8GCR(5)[8],
+    =KD4POJ(4)[7],=KD7DCR(4)[6],=KD8EZS(5)[8],=KE1B(3)[6],=KE2VB(3)[6],
+    =KE3D(4)[7],=KE4ETY(4)[8],=KE4KY(4)[8],=KE7X(4)[6],=KE8UN(5)[8],
+    =KG0F(3)[6],=KG4CUY(4)[8],=KG9JP(3)[6],=KH0WJ(5)[8],=KH2D(5)[8],
+    =KH6GN(4)[8],=KH6IDF(4)[7],=KH6OU(5)[8],=KI4EEY(4)[8],=KI4EZC(4)[8],
+    =KI4SP(4)[8],=KI6DY(4)[7],=KI7MT(4)[6],=KJ4AOM(4)[8],=KK4BJV(4)[8],
+    =KK6MC(4)[7],=KK9A(5)[8],=KK9O(5)[8],=KL0ET(4)[8],=KL7FDQ(3)[6],
+    =KL7HM(3)[6],=KL7QW(4)[7],=KL7WP(3)[6],=KL7WV(5)[8],=KM4DR(4)[7],
+    =KM4JA(4)[8],=KM7W(4)[6],=KO4OL(4)[8],=KO4PU(4)[8],=KO4XJ(4)[8],
+    =KO7X(4)[7],=KP4MM(5)[8],=KR2E(3)[6],=KR4F(4)[8],=KR7C(4)[7],=KS4L(4)[8],
+    =KS4X(4)[8],=KS5A(3)[6],=KS7T(4)[6],=KT0P(5)[8],=KT4TX(4)[8],=KU1CW(4)[7],
+    =KU1YL(4)[7],=KU4A(4)[8],=KU8E(5)[8],=KV1E(4)[7],=KX2P(4)[7],=KX9X(5)[8],
+    =KY0W(3)[6],=KY4F(4)[8],=KZ1W(3)[6],=KZ2V(3)[6],=N0RZT(4)[8],=N1CC(4)[7],
+    =N1JM(3)[6],=N1WQ(4)[7],=N2BJ(4)[8],=N2IC(4)[7],=N2NS(3)[6],=N2OPW(4)[8],
+    =N2WN(4)[8],=N3BUO(4)[7],=N3PV(3)[6],=N3RC(4)[6],=N3ZZ(3)[6],=N4AAI(4)[8],
+    =N4ARO(4)[8],=N4ART(4)[8],=N4AU(4)[8],=N4BCB(4)[8],=N4BCD(4)[8],
+    =N4DW(4)[8],=N4FZ(4)[8],=N4HAI(4)[8],=N4IJ(4)[7],=N4IR(4)[8],=N4JF(4)[8],
+    =N4KG(4)[8],=N4KH(4)[8],=N4NM(4)[8],=N4NO(4)[8],=N4OGW(4)[8],=N4QS(4)[8],
+    =N4TZ(4)[8],=N4UC(4)[8],=N4UW(4)[8],=N4VV(4)[8],=N4ZI(4)[8],=N4ZZ(4)[8],
+    =N5IE(5)[8],=N5KO(3)[6],=N5LZ(3)[6],=N5ZO(3)[6],=N6AR(5)[8],=N7DR(4)[7],
+    =N7EO(5)[8],=N7FLT(4)[6],=N7FUL(4)[7],=N7IP(4)[6],=N7IV(4)[7],=N7IX(4)[7],
+    =N7KA(4)[7],=N7MB(4)[8],=N7MZW(4)[7],=N7NG(4)[7],=N7US(4)[8],=N8CL(5)[8],
+    =N8DEZ(3)[6],=N8HM(5)[8],=N8II(5)[8],=N8NA(5)[8],=N8PR(5)[8],=N8RA(5)[8],
+    =N9ADG(3)[6],=N9CM(5)[8],=N9DFD(5)[8],=N9HDE(4)[7],=N9MM(4)[7],
+    =N9NB(5)[8],=N9NC(5)[8],=N9TX(4)[7],=N9UY(5)[8],=NA2U(3)[6],=NA4C(4)[8],
+    =NA4K(4)[8],=NB4M(4)[8],=ND2T(3)[6],=ND4X(4)[8],=NE4M(4)[8],=NG7A(5)[8],
+    =NH6Z(3)[6],=NH7RO(4)[7],=NI5O(4)[8],=NJ4I(4)[8],=NJ8J(5)[8],=NK4P(4)[8],
+    =NL7CO(4)[7],=NL7CQ(4)[7],=NL7XM(5)[8],=NN3V(3)[6],=NN4MM(4)[8],
+    =NN7A(4)[7],=NO9E(5)[8],=NP2B(5)[8],=NP2MR(5)[8],=NP3D(5)[8],=NP3ST(5)[8],
+    =NQ6N(5)[8],=NR7DX(4)[6],=NS2X(4)[8],=NS4X(4)[8],=NU4B(4)[8],=NV4B(4)[8],
+    =NW8U(5)[8],=NX1P(3)[6],=NY4N(4)[8],=NY6DX(5)[8],=W0BR(5)[8],=W0IZ(4)[8],
+    =W0PAN(3)[6],=W0PV(5)[8],=W0QQG(5)[8],=W0UCE(5)[8],=W0YK(3)[6],
+    =W0YR(5)[8],=W1NN(4)[8],=W1RH(3)[6],=W1SRD(3)[6],=W1ZD(3)[6],=W2OO(4)[8],
+    =W2UP(4)[7],=W2VJN(3)[6],=W2VKT(3)[6],=W3HDH(4)[8],=W3IQ(4)[8],
+    =W3TUA(4)[7],=W4BCG(4)[8],=W4BCU(4)[8],=W4BK(4)[8],=W4DAN(4)[8],
+    =W4DVG(4)[8],=W4EEH(4)[8],=W4EF(3)[6],=W4GHD(4)[8],=W4GKM(4)[8],
+    =W4HK(4)[8],=W4HOD(4)[8],=W4JHC(4)[7],=W4JSI(4)[8],=W4KW(4)[8],
+    =W4LC(4)[8],=W4NBS(4)[8],=W4NZ(4)[8],=W4PV(4)[8],=W4RK(4)[7],=W4RYW(4)[8],
+    =W4TTM(4)[8],=W4UAL(4)[8],=W4UAT(3)[6],=W4UT(4)[8],=W5DQ(3)[6],
+    =W5JR(5)[8],=W5MX(4)[8],=W5NZ(4)[8],=W5XB(5)[8],=W6AAN(5)[8],=W6DVS(5)[8],
+    =W6GMT(4)[7],=W6HGF(5)[8],=W6IHG(5)[8],=W6KGP(4)[7],=W6LFB(4)[7],
+    =W6NWS(5)[8],=W6UB(4)[8],=W7DO(5)[8],=W7HJ(5)[8],=W7IY(5)[8],=W7KAM(4)[7],
+    =W7RTX(4)[7],=W7WZ(5)[8],=W8AKS(5)[8],=W8BFX(3)[6],=W8FJ(5)[8],
+    =W8FN(4)[7],=W8HGH(5)[8],=W8HY(5)[8],=W8KA(3)[6],=W8MHW(4)[7],
+    =W8OHT(5)[8],=W8WEJ(5)[8],=W8ZA(5)[8],=W9CF(3)[6],=W9DKC(5)[8],
+    =W9GE(5)[8],=W9KB(5)[8],=W9LHG(4)[7],=W9NGA(3)[6],=W9PL(3)[6],
+    =WA0WWW(3)[6],=WA1FCN(4)[8],=WA1PMA(3)[6],=WA1UJU(4)[8],=WA3C(4)[8],
+    =WA4SM(4)[8],=WA5VGI(3)[6],=WA8KAN(5)[8],=WA8OJR(5)[8],=WA8QYJ(5)[8],
+    =WA8ZBT(4)[7],=WB3JFS(3)[6],=WB4KDI(4)[8],=WB4YDL(4)[8],=WB4YDY(4)[8],
+    =WB8CQV(5)[8],=WB8IMY(5)[8],=WB8YQJ(3)[6],=WB8YYY(5)[8],=WB9G(5)[8],
+    =WB9JPS(3)[6],=WB9KPT(4)[7],=WC7S(4)[7],=WE6EZ(4)[7],=WF4U(3)[6],
+    =WF7T(4)[8],=WG7Y(4)[7],=WG8Y(5)[8],=WJ9B(3)[6],=WL7OU(4)[7],=WP2NN(3)[6],
+    =WP3ME(5)[8],=WR5G(3)[6],=WS6K(4)[8],=WS7X(4)[7],=WS9M(5)[8],=WU9B(3)[6],
+    =WW4R(4)[8],=WY7SS(4)[7],=WZ4F(4)[8],=WZ7I(5)[8];
+Guantanamo Bay:           08:  11:  NA:   20.00:    75.00:     5.0:  KG4:
+    KG4;
+Mariana Islands:          27:  64:  OC:   15.18:  -145.72:   -10.0:  KH0:
+    AH0,KH0,NH0,WH0,=AB9HF,=AE6OG,=AJ6K,=KB5UAB,=N3QD,=NC6W,=WA6AC,=WE1J;
+Baker & Howland Islands:  31:  61:  OC:    0.00:   176.00:    12.0:  KH1:
+    AH1,KH1,NH1,WH1;
+Guam:                     27:  64:  OC:   13.37:  -144.70:   -10.0:  KH2:
+    AH2,KH2,NH2,WH2,=KF5ULC,=KG6DX,=KG6JDX,=KG6SAD,=KJ6KCJ,=NH7TL,=WD6DGS;
+Johnston Island:          31:  61:  OC:   16.72:   169.53:    10.0:  KH3:
+    AH3,KH3,NH3,WH3,=KJ6BZ;
+Midway Island:            31:  61:  OC:   28.20:   177.37:    11.0:  KH4:
+    AH4,KH4,NH4,WH4;
+Palmyra & Jarvis Islands: 31:  61:  OC:    5.87:   162.07:    11.0:  KH5:
+    AH5,KH5,NH5,WH5;
+Kingman Reef:             31:  61:  OC:    6.40:   162.40:    11.0:  KH5K:
+    AH5K,KH5K,NH5K,WH5K;
+Hawaii:                   31:  61:  OC:   19.67:   155.57:    10.0:  KH6:
+    AH6,AH7,KH6,KH7,NH6,NH7,WH6,WH7,=AA6MS,=K4EVR,=K6JAE,=K6TR,=K7ZAR,=K9AGI,
+    =KB0PXK,=KB2MRY,=KB6EGA,=KB7QKJ,=KC2ZSG,=KC2ZSH,=KC2ZSI,=KC4FUE,=KC4HHS,
+    =KC7EJC,=KC9AUA,=KD0QLQ,=KD6EPD,=KD7UAV,=KD7UZG,=KD8QML,=KE6CQE,=KE6TIS,
+    =KF5AHW,=KF5LBQ,=KF6FAY,=KG4SGV,=KG6HRX,=KG6JJP,=KG6NNF,=KG6NQI,=KG6OOB,
+    =KG6RJI,=KG6SDD,=KG7CJI,=KI6CRL,=KI6NOC,=KI6VYB,=KI6ZRV,=KI7OS,=KJ4KND,
+    =KJ6GYD,=KK4EEC,=KM6RM,=KN6ZU,=KO6QT,=N5NNK,=N6CGA,=N6QBK,=N7CLW,=NH2JO,
+    =NY7Z,=W7PEA,=W8JAY,=W8WH,=WB4JTT,=WB5C,=WB6SAA,=WB7BOR,=WD6GHJ,=WU0H;
+Kure Island:              31:  61:  OC:   29.00:   178.00:    10.0:  KH7K:
+    AH7K,KH7K,NH7K,WH7K;
+American Samoa:           32:  62:  OC:  -14.32:   170.78:    11.0:  KH8:
+    AH8,KH8,NH8,WH8,=AB9OH,=KD8TFY,=WH6BAR;
+Swains Island:            32:  62:  OC:  -11.05:   171.25:    11.0:  KH8/s:
+    =NH8S;
+Wake Island:              31:  65:  OC:   19.28:  -166.63:   -12.0:  KH9:
+    AH9,KH9,NH9,WH9;
+Alaska:                   01:  01:  NA:   63.87:   153.78:     8.0:  KL:
+    AL,KL,NL,WL,=AD7VV,=AE7LN,=K2NPS,=KB5UWU,=KB7DEL,=KB7QLB,=KC0OKQ,=KC9CMY,
+    =KD4KSB,=KD5WEV,=KD7TWB,=KD7VXE,=KD8GMS,=KD8JOU,=KE5HHR,=KE6TCE,=KE7EOP,
+    =KF5FJQ,=KF5NDT,=KF5NHR,=KF6LGK,=KG4WNZ,=KG6RJE,=KJ4PSV,=KJ4WDI,=KJ6KRG,
+    =KK4CLS,=KK4LRE,=KP4X,=KR4WV,=KW1W,=KY7J,=N0XCW,=N1KNK,=N6SPP,=N7UWT,
+    =N7XNM,=N7ZYS,=NH2GZ,=W5TLB,=W8OES,=WA2BIW,=WA7PXH,=WB6COP,=WT5T;
+Navassa Island:           08:  11:  NA:   18.40:    75.00:     5.0:  KP1:
+    KP1,NP1,WP1;
+US Virgin Islands:        08:  11:  NA:   17.73:    64.80:     4.0:  KP2:
+    KP2,NP2,WP2,=KH2XQ,=KH2XR,=KI4FOE,=KV2AA,=KV4BT,=KV4CF,=KV4FZ,=N1TKK,
+    =NQ3X,=WB4WFU;
+Puerto Rico:              08:  11:  NA:   18.18:    66.55:     4.0:  KP4:
+    KP3,KP4,NP3,NP4,WP3,WP4,=AF5IZ,=KB1IJU,=KB1KDP,=KB2NMT,=KB2OIF,=KB2OPM,
+    =KB2RYP,=KC2CYJ,=KC2LET,=KC2TE,=KC5DKT,=KE4WUE,=KF5PWC,=KH2RU,=KI5EEE,
+    =KP2Z,=N1VCW,=N2PGO,=N4JZD,=NB0G;
+Desecheo Island:          08:  11:  NA:   18.08:    67.88:     4.0:  KP5:
+    KP5,NP5,WP5;
+Norway:                   14:  18:  EU:   61.00:    -9.00:    -1.0:  LA:
+    LA,LB,LC,LD,LE,LF,LG,LH,LI,LJ,LK,LL,LM,LN;
+Argentina:                13:  14:  SA:  -34.80:    65.92:     3.0:  LU:
+    AY,AZ,L1,L2,L3,L4,L5,L6,L7,L8,L9,LO,LP,LQ,LR,LS,LT,LU,LV,LW,AY0V[16],
+    AY0W[16],AY0X[16],AY0Y[16],AY1V[16],AY1W[16],AY1X[16],AY1Y[16],AY2V[16],
+    AY2W[16],AY2X[16],AY2Y[16],AY3V[16],AY3W[16],AY3X[16],AY3Y[16],AY4V[16],
+    AY4W[16],AY4X[16],AY4Y[16],AY5V[16],AY5W[16],AY5X[16],AY5Y[16],AY6V[16],
+    AY6W[16],AY6X[16],AY6Y[16],AY7V[16],AY7W[16],AY7X[16],AY7Y[16],AY8V[16],
+    AY8W[16],AY8X[16],AY8Y[16],AY9V[16],AY9W[16],AY9X[16],AY9Y[16],AZ0V[16],
+    AZ0W[16],AZ0X[16],AZ0Y[16],AZ1V[16],AZ1W[16],AZ1X[16],AZ1Y[16],AZ2V[16],
+    AZ2W[16],AZ2X[16],AZ2Y[16],AZ3V[16],AZ3W[16],AZ3X[16],AZ3Y[16],AZ4V[16],
+    AZ4W[16],AZ4X[16],AZ4Y[16],AZ5V[16],AZ5W[16],AZ5X[16],AZ5Y[16],AZ6V[16],
+    AZ6W[16],AZ6X[16],AZ6Y[16],AZ7V[16],AZ7W[16],AZ7X[16],AZ7Y[16],AZ8V[16],
+    AZ8W[16],AZ8X[16],AZ8Y[16],AZ9V[16],AZ9W[16],AZ9X[16],AZ9Y[16],L20V[16],
+    L20W[16],L20X[16],L20Y[16],L21V[16],L21W[16],L21X[16],L21Y[16],L22V[16],
+    L22W[16],L22X[16],L22Y[16],L23V[16],L23W[16],L23X[16],L23Y[16],L24V[16],
+    L24W[16],L24X[16],L24Y[16],L25V[16],L25W[16],L25X[16],L25Y[16],L26V[16],
+    L26W[16],L26X[16],L26Y[16],L27V[16],L27W[16],L27X[16],L27Y[16],L28V[16],
+    L28W[16],L28X[16],L28Y[16],L29V[16],L29W[16],L29X[16],L29Y[16],L30V[16],
+    L30W[16],L30X[16],L30Y[16],L31V[16],L31W[16],L31X[16],L31Y[16],L32V[16],
+    L32W[16],L32X[16],L32Y[16],L33V[16],L33W[16],L33X[16],L33Y[16],L34V[16],
+    L34W[16],L34X[16],L34Y[16],L35V[16],L35W[16],L35X[16],L35Y[16],L36V[16],
+    L36W[16],L36X[16],L36Y[16],L37V[16],L37W[16],L37X[16],L37Y[16],L38V[16],
+    L38W[16],L38X[16],L38Y[16],L39V[16],L39W[16],L39X[16],L39Y[16],L40V[16],
+    L40W[16],L40X[16],L40Y[16],L41V[16],L41W[16],L41X[16],L41Y[16],L42V[16],
+    L42W[16],L42X[16],L42Y[16],L43V[16],L43W[16],L43X[16],L43Y[16],L44V[16],
+    L44W[16],L44X[16],L44Y[16],L45V[16],L45W[16],L45X[16],L45Y[16],L46V[16],
+    L46W[16],L46X[16],L46Y[16],L47V[16],L47W[16],L47X[16],L47Y[16],L48V[16],
+    L48W[16],L48X[16],L48Y[16],L49V[16],L49W[16],L49X[16],L49Y[16],L50V[16],
+    L50W[16],L50X[16],L50Y[16],L51V[16],L51W[16],L51X[16],L51Y[16],L52V[16],
+    L52W[16],L52X[16],L52Y[16],L53V[16],L53W[16],L53X[16],L53Y[16],L54V[16],
+    L54W[16],L54X[16],L54Y[16],L55V[16],L55W[16],L55X[16],L55Y[16],L56V[16],
+    L56W[16],L56X[16],L56Y[16],L57V[16],L57W[16],L57X[16],L57Y[16],L58V[16],
+    L58W[16],L58X[16],L58Y[16],L59V[16],L59W[16],L59X[16],L59Y[16],L60V[16],
+    L60W[16],L60X[16],L60Y[16],L61V[16],L61W[16],L61X[16],L61Y[16],L62V[16],
+    L62W[16],L62X[16],L62Y[16],L63V[16],L63W[16],L63X[16],L63Y[16],L64V[16],
+    L64W[16],L64X[16],L64Y[16],L65V[16],L65W[16],L65X[16],L65Y[16],L66V[16],
+    L66W[16],L66X[16],L66Y[16],L67V[16],L67W[16],L67X[16],L67Y[16],L68V[16],
+    L68W[16],L68X[16],L68Y[16],L69V[16],L69W[16],L69X[16],L69Y[16],L70V[16],
+    L70W[16],L70X[16],L70Y[16],L71V[16],L71W[16],L71X[16],L71Y[16],L72V[16],
+    L72W[16],L72X[16],L72Y[16],L73V[16],L73W[16],L73X[16],L73Y[16],L74V[16],
+    L74W[16],L74X[16],L74Y[16],L75V[16],L75W[16],L75X[16],L75Y[16],L76V[16],
+    L76W[16],L76X[16],L76Y[16],L77V[16],L77W[16],L77X[16],L77Y[16],L78V[16],
+    L78W[16],L78X[16],L78Y[16],L79V[16],L79W[16],L79X[16],L79Y[16],L80V[16],
+    L80W[16],L80X[16],L80Y[16],L81V[16],L81W[16],L81X[16],L81Y[16],L82V[16],
+    L82W[16],L82X[16],L82Y[16],L83V[16],L83W[16],L83X[16],L83Y[16],L84V[16],
+    L84W[16],L84X[16],L84Y[16],L85V[16],L85W[16],L85X[16],L85Y[16],L86V[16],
+    L86W[16],L86X[16],L86Y[16],L87V[16],L87W[16],L87X[16],L87Y[16],L88V[16],
+    L88W[16],L88X[16],L88Y[16],L89V[16],L89W[16],L89X[16],L89Y[16],L90V[16],
+    L90W[16],L90X[16],L90Y[16],L91V[16],L91W[16],L91X[16],L91Y[16],L92V[16],
+    L92W[16],L92X[16],L92Y[16],L93V[16],L93W[16],L93X[16],L93Y[16],L94V[16],
+    L94W[16],L94X[16],L94Y[16],L95V[16],L95W[16],L95X[16],L95Y[16],L96V[16],
+    L96W[16],L96X[16],L96Y[16],L97V[16],L97W[16],L97X[16],L97Y[16],L98V[16],
+    L98W[16],L98X[16],L98Y[16],L99V[16],L99W[16],L99X[16],L99Y[16],LO0V[16],
+    LO0W[16],LO0X[16],LO0Y[16],LO1V[16],LO1W[16],LO1X[16],LO1Y[16],LO2V[16],
+    LO2W[16],LO2X[16],LO2Y[16],LO3V[16],LO3W[16],LO3X[16],LO3Y[16],LO4V[16],
+    LO4W[16],LO4X[16],LO4Y[16],LO5V[16],LO5W[16],LO5X[16],LO5Y[16],LO6V[16],
+    LO6W[16],LO6X[16],LO6Y[16],LO7V[16],LO7W[16],LO7X[16],LO7Y[16],LO8V[16],
+    LO8W[16],LO8X[16],LO8Y[16],LO9V[16],LO9W[16],LO9X[16],LO9Y[16],LP0V[16],
+    LP0W[16],LP0X[16],LP0Y[16],LP1V[16],LP1W[16],LP1X[16],LP1Y[16],LP2V[16],
+    LP2W[16],LP2X[16],LP2Y[16],LP3V[16],LP3W[16],LP3X[16],LP3Y[16],LP4V[16],
+    LP4W[16],LP4X[16],LP4Y[16],LP5V[16],LP5W[16],LP5X[16],LP5Y[16],LP6V[16],
+    LP6W[16],LP6X[16],LP6Y[16],LP7V[16],LP7W[16],LP7X[16],LP7Y[16],LP8V[16],
+    LP8W[16],LP8X[16],LP8Y[16],LP9V[16],LP9W[16],LP9X[16],LP9Y[16],LQ0V[16],
+    LQ0W[16],LQ0X[16],LQ0Y[16],LQ1V[16],LQ1W[16],LQ1X[16],LQ1Y[16],LQ2V[16],
+    LQ2W[16],LQ2X[16],LQ2Y[16],LQ3V[16],LQ3W[16],LQ3X[16],LQ3Y[16],LQ4V[16],
+    LQ4W[16],LQ4X[16],LQ4Y[16],LQ5V[16],LQ5W[16],LQ5X[16],LQ5Y[16],LQ6V[16],
+    LQ6W[16],LQ6X[16],LQ6Y[16],LQ7V[16],LQ7W[16],LQ7X[16],LQ7Y[16],LQ8V[16],
+    LQ8W[16],LQ8X[16],LQ8Y[16],LQ9V[16],LQ9W[16],LQ9X[16],LQ9Y[16],LR0V[16],
+    LR0W[16],LR0X[16],LR0Y[16],LR1V[16],LR1W[16],LR1X[16],LR1Y[16],LR2V[16],
+    LR2W[16],LR2X[16],LR2Y[16],LR3V[16],LR3W[16],LR3X[16],LR3Y[16],LR4V[16],
+    LR4W[16],LR4X[16],LR4Y[16],LR5V[16],LR5W[16],LR5X[16],LR5Y[16],LR6V[16],
+    LR6W[16],LR6X[16],LR6Y[16],LR7V[16],LR7W[16],LR7X[16],LR7Y[16],LR8V[16],
+    LR8W[16],LR8X[16],LR8Y[16],LR9V[16],LR9W[16],LR9X[16],LR9Y[16],LS0V[16],
+    LS0W[16],LS0X[16],LS0Y[16],LS1V[16],LS1W[16],LS1X[16],LS1Y[16],LS2V[16],
+    LS2W[16],LS2X[16],LS2Y[16],LS3V[16],LS3W[16],LS3X[16],LS3Y[16],LS4V[16],
+    LS4W[16],LS4X[16],LS4Y[16],LS5V[16],LS5W[16],LS5X[16],LS5Y[16],LS6V[16],
+    LS6W[16],LS6X[16],LS6Y[16],LS7V[16],LS7W[16],LS7X[16],LS7Y[16],LS8V[16],
+    LS8W[16],LS8X[16],LS8Y[16],LS9V[16],LS9W[16],LS9X[16],LS9Y[16],LT0V[16],
+    LT0W[16],LT0X[16],LT0Y[16],LT1V[16],LT1W[16],LT1X[16],LT1Y[16],LT2V[16],
+    LT2W[16],LT2X[16],LT2Y[16],LT3V[16],LT3W[16],LT3X[16],LT3Y[16],LT4V[16],
+    LT4W[16],LT4X[16],LT4Y[16],LT5V[16],LT5W[16],LT5X[16],LT5Y[16],LT6V[16],
+    LT6W[16],LT6X[16],LT6Y[16],LT7V[16],LT7W[16],LT7X[16],LT7Y[16],LT8V[16],
+    LT8W[16],LT8X[16],LT8Y[16],LT9V[16],LT9W[16],LT9X[16],LT9Y[16],LU0V[16],
+    LU0W[16],LU0X[16],LU0Y[16],LU1V[16],LU1W[16],LU1X[16],LU1Y[16],LU2V[16],
+    LU2W[16],LU2X[16],LU2Y[16],LU3V[16],LU3W[16],LU3X[16],LU3Y[16],LU4V[16],
+    LU4W[16],LU4X[16],LU4Y[16],LU5V[16],LU5W[16],LU5X[16],LU5Y[16],LU6V[16],
+    LU6W[16],LU6X[16],LU6Y[16],LU7V[16],LU7W[16],LU7X[16],LU7Y[16],LU8V[16],
+    LU8W[16],LU8X[16],LU8Y[16],LU9V[16],LU9W[16],LU9X[16],LU9Y[16],LV0V[16],
+    LV0W[16],LV0X[16],LV0Y[16],LV1V[16],LV1W[16],LV1X[16],LV1Y[16],LV2V[16],
+    LV2W[16],LV2X[16],LV2Y[16],LV3V[16],LV3W[16],LV3X[16],LV3Y[16],LV4V[16],
+    LV4W[16],LV4X[16],LV4Y[16],LV5V[16],LV5W[16],LV5X[16],LV5Y[16],LV6V[16],
+    LV6W[16],LV6X[16],LV6Y[16],LV7V[16],LV7W[16],LV7X[16],LV7Y[16],LV8V[16],
+    LV8W[16],LV8X[16],LV8Y[16],LV9V[16],LV9W[16],LV9X[16],LV9Y[16],LW0V[16],
+    LW0W[16],LW0X[16],LW0Y[16],LW1V[16],LW1W[16],LW1X[16],LW1Y[16],LW2V[16],
+    LW2W[16],LW2X[16],LW2Y[16],LW3V[16],LW3W[16],LW3X[16],LW3Y[16],LW4V[16],
+    LW4W[16],LW4X[16],LW4Y[16],LW5V[16],LW5W[16],LW5X[16],LW5Y[16],LW6V[16],
+    LW6W[16],LW6X[16],LW6Y[16],LW7V[16],LW7W[16],LW7X[16],LW7Y[16],LW8V[16],
+    LW8W[16],LW8X[16],LW8Y[16],LW9V[16],LW9W[16],LW9X[16],LW9Y[16],
+    =LU/UA4WHX/X[16],=LU1DU/D,=LU1EUU/D,=LU1EY/D,=LU1FHE/F,=LU1FSE/F,
+    =LU1HCG/H,=LU1HPW/H,=LU1KWC/K,=LU1LT/L,=LU1QAH/Q,=LU1QHC/Q,=LU1QR/Q,
+    =LU1XB/XA[16],=LU1YDC/Y[16],=LU2AGQ/D,=LU2FP/F,=LU2HJ/H,=LU2HNV/H,
+    =LU2KLC/K,=LU2WA/W[16],=LU3ARE/D,=LU3AYE/D,=LU3FCI/F,=LU3HKA/H,
+    =LU3VMB/V[16],=LU3YEP/Y[16],=LU4DBT/D,=LU4EET/D,=LU4ETN/D,=LU4HTD/H,
+    =LU4LAD/L,=LU4LBU/L,=LU4QQ/Q,=LU4VAU/V[16],=LU4VBW/V[16],=LU4VMB/V[16],
+    =LU4VMG/V[16],=LU4YAB/Y[16],=LU5AHN/D,=LU5EAO/D,=LU5FYX/F,=LU5HR/H,
+    =LU5HTA/H,=LU5JU/J,=LU5QAJ/Q,=LU5VAI/V[16],=LU5VFL/V[16],=LU5VLB/V[16],
+    =LU5YF/V[16],=LU6FE/F,=LU6HCA/H,=LU6KAQ/K,=LU6QAN/Q,=LU6QB/Q,=LU6QER/Q,
+    =LU6QI/Q,=LU6VAC/V[16],=LU6VDT/V[16],=LU6VFL/V[16],=LU6VR/V[16],
+    =LU6YBK/Y[16],=LU7DOT/D,=LU7DSY/D,=LU7FCU/F,=LU7FM/F,=LU7FOE/F,=LU7HW/H,
+    =LU7KT/K,=LU7QBE/Q,=LU7VBT/V[16],=LU7VFG/V[16],=LU7YCL/Y[16],=LU8ATM/D,
+    =LU8DCH/D,=LU8DWR/D,=LU8DZE/D,=LU8FAB/F,=LU8IEZ/I,=LU8YMP/Y[16],=LU9AOS/D,
+    =LU9EI/D,=LU9QRV/Q,=LW3DG/D,=LW3DN/D,=LW4HTA/H,=LW5DUS/D,=LW6EGE/D,
+    =LW7EDH/D;
+Luxembourg:               14:  27:  EU:   50.00:    -6.00:    -1.0:  LX:
+    LX;
+Lithuania:                15:  29:  EU:   55.45:   -23.63:    -2.0:  LY:
+    LY;
+Bulgaria:                 20:  28:  EU:   42.83:   -25.08:    -2.0:  LZ:
+    LZ;
+Peru:                     10:  12:  SA:  -10.00:    76.00:     5.0:  OA:
+    4T,OA,OB,OC;
+Lebanon:                  20:  39:  AS:   33.83:   -35.83:    -2.0:  OD:
+    OD;
+Austria:                  15:  28:  EU:   47.33:   -13.33:    -1.0:  OE:
+    4U1V,OE;
+Finland:                  15:  18:  EU:   63.78:   -27.08:    -2.0:  OH:
+    OF,OG,OH,OI,OJ;
+Aland Islands:            15:  18:  EU:   60.13:   -20.37:    -2.0:  OH0:
+    OF0,OG0,OH0,OI0;
+Market Reef:              15:  18:  EU:   60.00:   -19.00:    -2.0:  OJ0:
+    OJ0;
+Czech Republic:           15:  28:  EU:   50.00:   -16.00:    -1.0:  OK:
+    OK,OL;
+Slovak Republic:          15:  28:  EU:   49.00:   -20.00:    -1.0:  OM:
+    OM;
+Belgium:                  14:  27:  EU:   50.70:    -4.85:    -1.0:  ON:
+    ON,OO,OP,OQ,OR,OS,OT;
+Greenland:                40:  05:  NA:   74.00:    42.78:     3.0:  OX:
+    OX,XP;
+Faroe Islands:            14:  18:  EU:   62.07:     6.93:     0.0:  OY:
+    OW,OY;
+Denmark:                  14:  18:  EU:   56.00:   -10.00:    -1.0:  OZ:
+    5P,5Q,OU,OV,OZ;
+Papua New Guinea:         28:  51:  OC:   -9.50:  -147.12:   -10.0:  P2:
+    P2;
+Aruba:                    09:  11:  SA:   12.53:    69.98:     4.0:  P4:
+    P4;
+DPR of Korea:             25:  44:  AS:   39.78:  -126.30:    -9.0:  P5:
+    HM,P5,P6,P7,P8,P9;
+Netherlands:              14:  27:  EU:   52.28:    -5.47:    -1.0:  PA:
+    PA,PB,PC,PD,PE,PF,PG,PH,PI,=PA3BXR/MILL,=PA6KMS/MILL,=PA6MZD/MILL,
+    =PA6STAR/MILL,=PD0ARI/MILL,=PD1JL/MILL,=PH4RTM/MILL,=PI4ET/MILL,
+    =PI4ETL/MILL;
+Curacao:                  09:  11:  SA:   12.17:    69.00:     4.0:  PJ2:
+    PJ2;
+Bonaire:                  09:  11:  SA:   12.20:    68.25:     4.0:  PJ4:
+    PJ4;
+Saba & St. Eustatius:     08:  11:  NA:   17.57:    63.10:     4.0:  PJ5:
+    PJ5,PJ6;
+Sint Maarten:             08:  11:  NA:   18.07:    63.07:     4.0:  PJ7:
+    PJ7;
+Brazil:                   11:  12:  SA:  -10.00:    53.00:     3.0:  PY:
+    PP,PQ,PR,PS,PT,PU,PV,PW,PX,PY,ZV,ZW,ZX,ZY,ZZ,PP1[15],PP2[15],PP3[15],
+    PP4[15],PP5[15],PP6[13],PP7[13],PQ2[13],PQ3[15],PQ4[15],PQ8[13],PR3[15],
+    PR4[15],PR7[13],PR8[13],PS3[15],PS4[15],PS7[13],PS8[13],PT2[13],PT3[15],
+    PT4[15],PT7[13],PT9[15],PU3[15],PU4[15],PV3[15],PV4[15],PW3[15],PW4[15],
+    PX3[15],PX4[15],PY1[15],PY2[15],PY3[15],PY4[15],PY5[15],PY6[13],PY7[13],
+    PY8[13],PY9[13],ZV3[15],ZV4[15],ZW3[15],ZW4[15],ZX3[15],ZX4[15],ZY3[15],
+    ZY4[15],ZZ3[15],ZZ4[15];
+Fernando de Noronha:      11:  13:  SA:   -3.85:    32.43:     2.0:  PY0F:
+    PP0F,PP0R,PQ0F,PQ0R,PR0F,PR0R,PS0F,PS0R,PT0F,PT0R,PU0F,PU0R,PV0F,PV0R,
+    PW0F,PW0R,PX0F,PX0R,PY0F,PY0R,PY0Z,ZV0F,ZV0R,ZW0F,ZW0R,ZX0F,ZX0R,ZY0F,
+    ZY0R,ZY0Z,ZZ0F,ZZ0R;
+St. Peter & St. Paul:     11:  13:  SA:    0.00:    29.00:     2.0:  PY0S:
+    PP0S,PQ0S,PR0S,PS0S,PT0S,PU0S,PV0S,PW0S,PX0S,PY0S,ZV0S,ZW0S,ZX0S,ZY0S,
+    ZZ0S;
+Trindade & Martim Vaz:    11:  15:  SA:  -20.50:    29.32:     2.0:  PY0T:
+    PP0M,PP0T,PQ0M,PQ0T,PR0M,PR0T,PS0M,PS0T,PT0M,PT0T,PU0M,PU0T,PV0M,PV0T,
+    PW0M,PW0T,PX0M,PX0T,PY0M,PY0T,ZV0M,ZV0T,ZW0M,ZW0T,ZX0M,ZX0T,ZY0M,ZY0T,
+    ZZ0M,ZZ0T;
+Suriname:                 09:  12:  SA:    4.00:    56.00:     3.0:  PZ:
+    PZ;
+Franz Josef Land:         40:  75:  EU:   80.68:   -49.92:    -3.0:  R1FJ:
+    FJL,R1FJ,RI1FJ;
+Western Sahara:           33:  46:  AF:   24.82:    13.85:     0.0:  S0:
+    S0;
+Bangladesh:               22:  41:  AS:   24.12:   -89.65:    -6.0:  S2:
+    S2,S3;
+Slovenia:                 15:  28:  EU:   46.00:   -14.00:    -1.0:  S5:
+    S5;
+Seychelles:               39:  53:  AF:   -4.67:   -55.47:    -4.0:  S7:
+    S7;
+Sao Tome & Principe:      36:  47:  AF:    0.22:    -6.57:     0.0:  S9:
+    S9;
+Sweden:                   14:  18:  EU:   61.20:   -14.57:    -1.0:  SM:
+    7S,8S,SA,SB,SC,SD,SE,SF,SG,SH,SI,SJ,SK,SL,SM;
+Poland:                   15:  28:  EU:   52.28:   -18.67:    -1.0:  SP:
+    3Z,HF,SN,SO,SP,SQ,SR;
+Sudan:                    34:  48:  AF:   14.47:   -28.62:    -3.0:  ST:
+    6T,6U,ST;
+Egypt:                    34:  38:  AF:   26.28:   -28.60:    -2.0:  SU:
+    6A,6B,SS,SU;
+Greece:                   20:  28:  EU:   39.78:   -21.78:    -2.0:  SV:
+    J4,SV,SW,SX,SY,SZ,=SV54FF;
+Mount Athos:              20:  28:  EU:   40.00:   -24.00:    -2.0:  SV/a:
+    =SV2ASP/A;
+Dodecanese:               20:  28:  EU:   36.17:   -27.93:    -2.0:  SV5:
+    J45,SV5,SW5,SX5,SY5,SZ5,=SV0XCA/5;
+Crete:                    20:  28:  EU:   35.23:   -24.78:    -2.0:  SV9:
+    J49,SV9,SW9,SX9,SY9,SZ9,=SV0XBN/9,=SV0XCC/9;
+Tuvalu:                   31:  65:  OC:   -8.50:  -179.20:   -12.0:  T2:
+    T2;
+Western Kiribati:         31:  65:  OC:    1.42:  -173.00:   -12.0:  T30:
+    T30;
+Central Kiribati:         31:  62:  OC:   -2.83:   171.72:   -13.0:  T31:
+    T31;
+Eastern Kiribati:         31:  61:  OC:    1.80:   157.35:   -14.0:  T32:
+    T32;
+Banaba Island:            31:  65:  OC:   -0.88:  -169.53:   -12.0:  T33:
+    T33;
+Somalia:                  37:  48:  AF:    2.03:   -45.35:    -3.0:  T5:
+    6O,T5;
+San Marino:               15:  28:  EU:   43.95:   -12.45:    -1.0:  T7:
+    T7;
+Palau:                    27:  64:  OC:    7.45:  -134.53:    -9.0:  T8:
+    T8;
+Asiatic Turkey:           20:  39:  AS:   39.18:   -35.65:    -2.0:  TA:
+    TA,TB,TC,YM,=TA1BM/3,=TA1BZ/2,=TA1D/3,=TA1FA/2;
+European Turkey:          20:  39:  EU:   41.02:   -28.97:    -2.0:  *TA1:
+    TA1,TB1,TC1,YM1;
+Iceland:                  40:  17:  EU:   64.80:    18.73:     0.0:  TF:
+    TF;
+Guatemala:                07:  11:  NA:   15.50:    90.30:     6.0:  TG:
+    TD,TG;
+Costa Rica:               07:  11:  NA:   10.00:    84.00:     6.0:  TI:
+    TE,TI;
+Cocos Island:             07:  11:  NA:    5.52:    87.05:     6.0:  TI9:
+    TE9,TI9;
+Cameroon:                 36:  47:  AF:    5.38:   -11.87:    -1.0:  TJ:
+    TJ;
+Corsica:                  15:  28:  EU:   42.00:    -9.00:    -1.0:  TK:
+    TK;
+Central African Republic: 36:  47:  AF:    6.75:   -20.33:    -1.0:  TL:
+    TL;
+Republic of the Congo:    36:  52:  AF:   -1.02:   -15.37:    -1.0:  TN:
+    TN;
+Gabon:                    36:  52:  AF:   -0.37:   -11.73:    -1.0:  TR:
+    TR;
+Chad:                     36:  47:  AF:   15.80:   -18.17:    -1.0:  TT:
+    TT;
+Cote d'Ivoire:            35:  46:  AF:    7.58:     5.80:     0.0:  TU:
+    TU;
+Benin:                    35:  46:  AF:    9.87:    -2.25:    -1.0:  TY:
+    TY;
+Mali:                     35:  46:  AF:   18.00:     2.58:     0.0:  TZ:
+    TZ;
+European Russia:          16:  29:  EU:   53.65:   -41.37:    -4.0:  UA:
+    R,RA27,U,R1N[19],R1O[19],R1P[20],R1Z[19],R290(17)[30],R4H[30],R4I[30],
+    R4W[30],R8F(17)[30],R8G(17)[30],R8X(17)[19],R9F(17)[30],R9G(17)[30],
+    R9X(17)[19],RA1N[19],RA1O[19],RA1P[20],RA1Z[19],RA4H[30],RA4I[30],
+    RA4W[30],RA8F(17)[30],RA8G(17)[30],RA8X(17)[19],RA9F(17)[30],RA9G(17)[30],
+    RA9X(17)[19],RC1N[19],RC1O[19],RC1P[20],RC1Z[19],RC4H[30],RC4I[30],
+    RC4W[30],RC8F(17)[30],RC8G(17)[30],RC8X(17)[19],RC9F(17)[30],RC9G(17)[30],
+    RC9X(17)[19],RD1N[19],RD1O[19],RD1P[20],RD1Z[19],RD4H[30],RD4I[30],
+    RD4W[30],RD8F(17)[30],RD8G(17)[30],RD8X(17)[19],RD9F(17)[30],RD9G(17)[30],
+    RD9X(17)[19],RF1N[19],RF1O[19],RF1P[20],RF1Z[19],RF4H[30],RF4I[30],
+    RF4W[30],RF8F(17)[30],RF8G(17)[30],RF8X(17)[19],RF9F(17)[30],RF9G(17)[30],
+    RF9X(17)[19],RG1N[19],RG1O[19],RG1P[20],RG1Z[19],RG4H[30],RG4I[30],
+    RG4W[30],RG8F(17)[30],RG8G(17)[30],RG8X(17)[19],RG9F(17)[30],RG9G(17)[30],
+    RG9X(17)[19],RI1N[19],RI1O[19],RI1P[20],RI1Z[19],RI4H[30],RI4I[30],
+    RI4W[30],RI8F(17)[30],RI8G(17)[30],RI8X(17)[19],RI9F(17)[30],RI9G(17)[30],
+    RI9X(17)[19],RJ1N[19],RJ1O[19],RJ1P[20],RJ1Z[19],RJ4H[30],RJ4I[30],
+    RJ4W[30],RJ8F(17)[30],RJ8G(17)[30],RJ8X(17)[19],RJ9F(17)[30],RJ9G(17)[30],
+    RJ9X(17)[19],RK1N[19],RK1O[19],RK1P[20],RK1Z[19],RK4H[30],RK4I[30],
+    RK4W[30],RK8F(17)[30],RK8G(17)[30],RK8X(17)[19],RK9F(17)[30],RK9G(17)[30],
+    RK9X(17)[19],RL1N[19],RL1O[19],RL1P[20],RL1Z[19],RL4H[30],RL4I[30],
+    RL4W[30],RL8F(17)[30],RL8G(17)[30],RL8X(17)[19],RL9F(17)[30],RL9G(17)[30],
+    RL9X(17)[19],RM1N[19],RM1O[19],RM1P[20],RM1Z[19],RM4H[30],RM4I[30],
+    RM4W[30],RM8F(17)[30],RM8G(17)[30],RM8X(17)[19],RM9F(17)[30],RM9G(17)[30],
+    RM9X(17)[19],RN1N[19],RN1O[19],RN1P[20],RN1Z[19],RN4H[30],RN4I[30],
+    RN4W[30],RN8F(17)[30],RN8G(17)[30],RN8X(17)[19],RN9F(17)[30],RN9G(17)[30],
+    RN9X(17)[19],RO1N[19],RO1O[19],RO1P[20],RO1Z[19],RO4H[30],RO4I[30],
+    RO4W[30],RO8F(17)[30],RO8G(17)[30],RO8X(17)[19],RO9F(17)[30],RO9G(17)[30],
+    RO9X(17)[19],RP1N[19],RP1O[19],RP1P[20],RP1Z[19],RP4H[30],RP4I[30],
+    RP4W[30],RP8F(17)[30],RP8G(17)[30],RP8X(17)[19],RP9F(17)[30],RP9G(17)[30],
+    RP9X(17)[19],RQ1N[19],RQ1O[19],RQ1P[20],RQ1Z[19],RQ4H[30],RQ4I[30],
+    RQ4W[30],RQ8F(17)[30],RQ8G(17)[30],RQ8X(17)[19],RQ9F(17)[30],RQ9G(17)[30],
+    RQ9X(17)[19],RR1N[19],RR1O[19],RR1P[20],RR1Z[19],RR4H[30],RR4I[30],
+    RR4W[30],RR8F(17)[30],RR8G(17)[30],RR8X(17)[19],RR9F(17)[30],RR9G(17)[30],
+    RR9X(17)[19],RT1N[19],RT1O[19],RT1P[20],RT1Z[19],RT4H[30],RT4I[30],
+    RT4W[30],RT8F(17)[30],RT8G(17)[30],RT8X(17)[19],RT9F(17)[30],RT9G(17)[30],
+    RT9X(17)[19],RU1N[19],RU1O[19],RU1P[20],RU1Z[19],RU4H[30],RU4I[30],
+    RU4W[30],RU8F(17)[30],RU8G(17)[30],RU8X(17)[19],RU9F(17)[30],RU9G(17)[30],
+    RU9X(17)[19],RV1N[19],RV1O[19],RV1P[20],RV1Z[19],RV4H[30],RV4I[30],
+    RV4W[30],RV8F(17)[30],RV8G(17)[30],RV8X(17)[19],RV9F(17)[30],RV9G(17)[30],
+    RV9X(17)[19],RW1N[19],RW1O[19],RW1P[20],RW1Z[19],RW4H[30],RW4I[30],
+    RW4W[30],RW8F(17)[30],RW8G(17)[30],RW8X(17)[19],RW9F(17)[30],RW9G(17)[30],
+    RW9X(17)[19],RX1N[19],RX1O[19],RX1P[20],RX1Z[19],RX4H[30],RX4I[30],
+    RX4W[30],RX8F(17)[30],RX8G(17)[30],RX8X(17)[19],RX9F(17)[30],RX9G(17)[30],
+    RX9X(17)[19],RY1N[19],RY1O[19],RY1P[20],RY1Z[19],RY4H[30],RY4I[30],
+    RY4W[30],RY8F(17)[30],RY8G(17)[30],RY8X(17)[19],RY9F(17)[30],RY9G(17)[30],
+    RY9X(17)[19],RZ1N[19],RZ1O[19],RZ1P[20],RZ1Z[19],RZ4H[30],RZ4I[30],
+    RZ4W[30],RZ8F(17)[30],RZ8G(17)[30],RZ8X(17)[19],RZ9F(17)[30],RZ9G(17)[30],
+    RZ9X(17)[19],U1N[19],U1O[19],U1P[20],U1Z[19],U4H[30],U4I[30],U4W[30],
+    U8F(17)[30],U8G(17)[30],U8X(17)[19],U9F(17)[30],U9G(17)[30],U9X(17)[19],
+    UA1N[19],UA1O[19],UA1P[20],UA1Z[19],UA4H[30],UA4I[30],UA4W[30],
+    UA8F(17)[30],UA8G(17)[30],UA8X(17)[19],UA9F(17)[30],UA9G(17)[30],
+    UA9X(17)[19],UB1N[19],UB1O[19],UB1P[20],UB1Z[19],UB4H[30],UB4I[30],
+    UB4W[30],UB8F(17)[30],UB8G(17)[30],UB8X(17)[19],UB9F(17)[30],UB9G(17)[30],
+    UB9X(17)[19],UC1N[19],UC1O[19],UC1P[20],UC1Z[19],UC4H[30],UC4I[30],
+    UC4W[30],UC8F(17)[30],UC8G(17)[30],UC8X(17)[19],UC9F(17)[30],UC9G(17)[30],
+    UC9X(17)[19],UD1N[19],UD1O[19],UD1P[20],UD1Z[19],UD4H[30],UD4I[30],
+    UD4W[30],UD8F(17)[30],UD8G(17)[30],UD8X(17)[19],UD9F(17)[30],UD9G(17)[30],
+    UD9X(17)[19],UE1N[19],UE1O[19],UE1P[20],UE1Z[19],UE4H[30],UE4I[30],
+    UE4W[30],UE8F(17)[30],UE8G(17)[30],UE8X(17)[19],UE9F(17)[30],UE9G(17)[30],
+    UE9X(17)[19],UF1N[19],UF1O[19],UF1P[20],UF1Z[19],UF4H[30],UF4I[30],
+    UF4W[30],UF8F(17)[30],UF8G(17)[30],UF8X(17)[19],UF9F(17)[30],UF9G(17)[30],
+    UF9X(17)[19],UG1N[19],UG1O[19],UG1P[20],UG1Z[19],UG4H[30],UG4I[30],
+    UG4W[30],UG8F(17)[30],UG8G(17)[30],UG8X(17)[19],UG9F(17)[30],UG9G(17)[30],
+    UG9X(17)[19],UH1N[19],UH1O[19],UH1P[20],UH1Z[19],UH4H[30],UH4I[30],
+    UH4W[30],UH8F(17)[30],UH8G(17)[30],UH8X(17)[19],UH9F(17)[30],UH9G(17)[30],
+    UH9X(17)[19],UI1N[19],UI1O[19],UI1P[20],UI1Z[19],UI4H[30],UI4I[30],
+    UI4W[30],UI8F(17)[30],UI8G(17)[30],UI8X(17)[19],UI9F(17)[30],UI9G(17)[30],
+    UI9X(17)[19],=R863LC,=R88EPC,=R95PW,=RA27FM(17)[30],=RU27FQ(17)[30],
+    =RU27FW(17)[30],=RU2FB/6/P,=RW9WJ/4/P[30];
+Kaliningrad:              15:  29:  EU:   54.72:   -20.52:    -3.0:  UA2:
+    R2F,R2K,RA2,RC2F,RC2K,RD2F,RD2K,RF2F,RF2K,RG2F,RG2K,RI2F,RI2K,RJ2F,RJ2K,
+    RK2F,RK2K,RL2F,RL2K,RM2F,RM2K,RN2F,RN2K,RO2F,RO2K,RP2F,RP2K,RQ2F,RQ2K,
+    RR2F,RR2K,RT2F,RT2K,RU2F,RU2K,RV2F,RV2K,RW2F,RW2K,RX2F,RX2K,RY2F,RY2K,
+    RZ2F,RZ2K,U2F,U2K,UA2,UB2,UC2,UD2,UE2,UF2,UG2,UH2,UI2,=R2MWO;
+Asiatic Russia:           17:  30:  AS:   55.88:   -84.08:    -7.0:  UA9:
+    R0,R8(17)[30],R9,RA0,RA8(17)[30],RA9,RB0,RB8(17)[30],RB9,RC0,RC8(17)[30],
+    RC9,RD0,RD8(17)[30],RD9,RE0,RE8(17)[30],RE9,RF0,RF8(17)[30],RF9,RG0,
+    RG8(17)[30],RG9,RH0,RH8(17)[30],RH9,RI0,RI8(17)[30],RI9,RJ0,RJ8(17)[30],
+    RJ9,RK0,RK8(17)[30],RK9,RL0,RL8(17)[30],RL9,RM0,RM8(17)[30],RM9,RN0,
+    RN8(17)[30],RN9,RO0,RO8(17)[30],RO9,RP0,RP8(17)[30],RP9,RQ0,RQ8(17)[30],
+    RQ9,RR0,RR8(17)[30],RR9,RS0,RS8(17)[30],RS9,RT0,RT8(17)[30],RT9,RU0,
+    RU8(17)[30],RU9,RV0,RV8(17)[30],RV9,RW0,RW8(17)[30],RW9,RX0,RX8(17)[30],
+    RX9,RY0,RY8(17)[30],RY9,RZ0,RZ8(17)[30],RZ9,U0,U8(17)[30],U9,UA0,
+    UA8(17)[30],UA9,UB0,UB8(17)[30],UB9,UC0,UC8(17)[30],UC9,UD0,UD8(17)[30],
+    UD9,UE0,UE8(17)[30],UE9,UF0,UF8(17)[30],UF9,UG0,UG8(17)[30],UG9,UH0,
+    UH8(17)[30],UH9,UI0,UI8(17)[30],UI9,R0T(18)[32],R8H(18)[31],R8I(18)[31],
+    R8O(18)[31],R8P(18)[31],R8S(16)[30],R8T(16)[30],R8U(18)[31],R8V(18)[31],
+    R8W(16)[30],R8Y(18)[31],R8Z(18)[31],R9I(18)[31],R9M(17)[30],R9P(18)[31],
+    R9S(16),R9T(16),R9V(18)[31],R9W(16),RA0T(18)[32],RA8H(18)[31],
+    RA8I(18)[31],RA8O(18)[31],RA8P(18)[31],RA8S(16)[30],RA8T(16)[30],
+    RA8U(18)[31],RA8V(18)[31],RA8W(16)[30],RA8Y(18)[31],RA8Z(18)[31],
+    RA9I(18)[31],RA9M(17)[30],RA9P(18)[31],RA9S(16),RA9T(16),RA9V(18)[31],
+    RA9W(16),RC0T(18)[32],RC8H(18)[31],RC8I(18)[31],RC8O(18)[31],RC8P(18)[31],
+    RC8S(16)[30],RC8T(16)[30],RC8U(18)[31],RC8V(18)[31],RC8W(16)[30],
+    RC8Y(18)[31],RC8Z(18)[31],RC9I(18)[31],RC9M(17)[30],RC9P(18)[31],RC9S(16),
+    RC9T(16),RC9V(18)[31],RC9W(16),RD0T(18)[32],RD8H(18)[31],RD8I(18)[31],
+    RD8O(18)[31],RD8P(18)[31],RD8S(16)[30],RD8T(16)[30],RD8U(18)[31],
+    RD8V(18)[31],RD8W(16)[30],RD8Y(18)[31],RD8Z(18)[31],RD9I(18)[31],
+    RD9M(17)[30],RD9P(18)[31],RD9S(16),RD9T(16),RD9V(18)[31],RD9W(16),
+    RF0T(18)[32],RF8H(18)[31],RF8I(18)[31],RF8O(18)[31],RF8P(18)[31],
+    RF8S(16)[30],RF8T(16)[30],RF8U(18)[31],RF8V(18)[31],RF8W(16)[30],
+    RF8Y(18)[31],RF8Z(18)[31],RF9I(18)[31],RF9M(17)[30],RF9P(18)[31],RF9S(16),
+    RF9T(16),RF9V(18)[31],RF9W(16),RG0T(18)[32],RG8H(18)[31],RG8I(18)[31],
+    RG8O(18)[31],RG8P(18)[31],RG8S(16)[30],RG8T(16)[30],RG8U(18)[31],
+    RG8V(18)[31],RG8W(16)[30],RG8Y(18)[31],RG8Z(18)[31],RG9I(18)[31],
+    RG9M(17)[30],RG9P(18)[31],RG9S(16),RG9T(16),RG9V(18)[31],RG9W(16),
+    RI0T(18)[32],RI8H(18)[31],RI8I(18)[31],RI8O(18)[31],RI8P(18)[31],
+    RI8S(16)[30],RI8T(16)[30],RI8U(18)[31],RI8V(18)[31],RI8W(16)[30],
+    RI8Y(18)[31],RI8Z(18)[31],RI9I(18)[31],RI9M(17)[30],RI9P(18)[31],RI9S(16),
+    RI9T(16),RI9V(18)[31],RI9W(16),RJ0T(18)[32],RJ8H(18)[31],RJ8I(18)[31],
+    RJ8O(18)[31],RJ8P(18)[31],RJ8S(16)[30],RJ8T(16)[30],RJ8U(18)[31],
+    RJ8V(18)[31],RJ8W(16)[30],RJ8Y(18)[31],RJ8Z(18)[31],RJ9I(18)[31],
+    RJ9M(17)[30],RJ9P(18)[31],RJ9S(16),RJ9T(16),RJ9V(18)[31],RJ9W(16),
+    RK0T(18)[32],RK8H(18)[31],RK8I(18)[31],RK8O(18)[31],RK8P(18)[31],
+    RK8S(16)[30],RK8T(16)[30],RK8U(18)[31],RK8V(18)[31],RK8W(16)[30],
+    RK8Y(18)[31],RK8Z(18)[31],RK9I(18)[31],RK9M(17)[30],RK9P(18)[31],RK9S(16),
+    RK9T(16),RK9V(18)[31],RK9W(16),RL0T(18)[32],RL8H(18)[31],RL8I(18)[31],
+    RL8O(18)[31],RL8P(18)[31],RL8S(16)[30],RL8T(16)[30],RL8U(18)[31],
+    RL8V(18)[31],RL8W(16)[30],RL8Y(18)[31],RL8Z(18)[31],RL9I(18)[31],
+    RL9M(17)[30],RL9P(18)[31],RL9S(16),RL9T(16),RL9V(18)[31],RL9W(16),
+    RM0T(18)[32],RM8H(18)[31],RM8I(18)[31],RM8O(18)[31],RM8P(18)[31],
+    RM8S(16)[30],RM8T(16)[30],RM8U(18)[31],RM8V(18)[31],RM8W(16)[30],
+    RM8Y(18)[31],RM8Z(18)[31],RM9I(18)[31],RM9M(17)[30],RM9P(18)[31],RM9S(16),
+    RM9T(16),RM9V(18)[31],RM9W(16),RN0T(18)[32],RN8H(18)[31],RN8I(18)[31],
+    RN8O(18)[31],RN8P(18)[31],RN8S(16)[30],RN8T(16)[30],RN8U(18)[31],
+    RN8V(18)[31],RN8W(16)[30],RN8Y(18)[31],RN8Z(18)[31],RN9I(18)[31],
+    RN9M(17)[30],RN9P(18)[31],RN9S(16),RN9T(16),RN9V(18)[31],RN9W(16),
+    RO0T(18)[32],RO8H(18)[31],RO8I(18)[31],RO8O(18)[31],RO8P(18)[31],
+    RO8S(16)[30],RO8T(16)[30],RO8U(18)[31],RO8V(18)[31],RO8W(16)[30],
+    RO8Y(18)[31],RO8Z(18)[31],RO9I(18)[31],RO9M(17)[30],RO9P(18)[31],RO9S(16),
+    RO9T(16),RO9V(18)[31],RO9W(16),RP0T(18)[32],RP8H(18)[31],RP8I(18)[31],
+    RP8O(18)[31],RP8P(18)[31],RP8S(16)[30],RP8T(16)[30],RP8U(18)[31],
+    RP8V(18)[31],RP8W(16)[30],RP8Y(18)[31],RP8Z(18)[31],RP9I(18)[31],
+    RP9M(17)[30],RP9P(18)[31],RP9S(16),RP9T(16),RP9V(18)[31],RP9W(16),
+    RQ0T(18)[32],RQ8H(18)[31],RQ8I(18)[31],RQ8O(18)[31],RQ8P(18)[31],
+    RQ8S(16)[30],RQ8T(16)[30],RQ8U(18)[31],RQ8V(18)[31],RQ8W(16)[30],
+    RQ8Y(18)[31],RQ8Z(18)[31],RQ9I(18)[31],RQ9M(17)[30],RQ9P(18)[31],RQ9S(16),
+    RQ9T(16),RQ9V(18)[31],RQ9W(16),RR0T(18)[32],RR8H(18)[31],RR8I(18)[31],
+    RR8O(18)[31],RR8P(18)[31],RR8S(16)[30],RR8T(16)[30],RR8U(18)[31],
+    RR8V(18)[31],RR8W(16)[30],RR8Y(18)[31],RR8Z(18)[31],RR9I(18)[31],
+    RR9M(17)[30],RR9P(18)[31],RR9S(16),RR9T(16),RR9V(18)[31],RR9W(16),
+    RT0T(18)[32],RT8H(18)[31],RT8I(18)[31],RT8O(18)[31],RT8P(18)[31],
+    RT8S(16)[30],RT8T(16)[30],RT8U(18)[31],RT8V(18)[31],RT8W(16)[30],
+    RT8Y(18)[31],RT8Z(18)[31],RT9I(18)[31],RT9M(17)[30],RT9P(18)[31],RT9S(16),
+    RT9T(16),RT9V(18)[31],RT9W(16),RU0T(18)[32],RU8H(18)[31],RU8I(18)[31],
+    RU8O(18)[31],RU8P(18)[31],RU8S(16)[30],RU8T(16)[30],RU8U(18)[31],
+    RU8V(18)[31],RU8W(16)[30],RU8Y(18)[31],RU8Z(18)[31],RU9I(18)[31],
+    RU9M(17)[30],RU9P(18)[31],RU9S(16),RU9T(16),RU9V(18)[31],RU9W(16),
+    RV0T(18)[32],RV8H(18)[31],RV8I(18)[31],RV8O(18)[31],RV8P(18)[31],
+    RV8S(16)[30],RV8T(16)[30],RV8U(18)[31],RV8V(18)[31],RV8W(16)[30],
+    RV8Y(18)[31],RV8Z(18)[31],RV9I(18)[31],RV9M(17)[30],RV9P(18)[31],RV9S(16),
+    RV9T(16),RV9V(18)[31],RV9W(16),RW0T(18)[32],RW8H(18)[31],RW8I(18)[31],
+    RW8O(18)[31],RW8P(18)[31],RW8S(16)[30],RW8T(16)[30],RW8U(18)[31],
+    RW8V(18)[31],RW8W(16)[30],RW8Y(18)[31],RW8Z(18)[31],RW9I(18)[31],
+    RW9M(17)[30],RW9P(18)[31],RW9S(16),RW9T(16),RW9V(18)[31],RW9W(16),
+    RX0T(18)[32],RX8H(18)[31],RX8I(18)[31],RX8O(18)[31],RX8P(18)[31],
+    RX8S(16)[30],RX8T(16)[30],RX8U(18)[31],RX8V(18)[31],RX8W(16)[30],
+    RX8Y(18)[31],RX8Z(18)[31],RX9I(18)[31],RX9M(17)[30],RX9P(18)[31],RX9S(16),
+    RX9T(16),RX9V(18)[31],RX9W(16),RY0T(18)[32],RY8H(18)[31],RY8I(18)[31],
+    RY8O(18)[31],RY8P(18)[31],RY8S(16)[30],RY8T(16)[30],RY8U(18)[31],
+    RY8V(18)[31],RY8W(16)[30],RY8Y(18)[31],RY8Z(18)[31],RY9I(18)[31],
+    RY9M(17)[30],RY9P(18)[31],RY9S(16),RY9T(16),RY9V(18)[31],RY9W(16),
+    RZ0T(18)[32],RZ8H(18)[31],RZ8I(18)[31],RZ8O(18)[31],RZ8P(18)[31],
+    RZ8S(16)[30],RZ8T(16)[30],RZ8U(18)[31],RZ8V(18)[31],RZ8W(16)[30],
+    RZ8Y(18)[31],RZ8Z(18)[31],RZ9I(18)[31],RZ9M(17)[30],RZ9P(18)[31],RZ9S(16),
+    RZ9T(16),RZ9V(18)[31],RZ9W(16),U0T(18)[32],U8H(18)[31],U8I(18)[31],
+    U8O(18)[31],U8P(18)[31],U8S(16)[30],U8T(16)[30],U8U(18)[31],U8V(18)[31],
+    U8W(16)[30],U8Y(18)[31],U8Z(18)[31],U9I(18)[31],U9M(17)[30],U9P(18)[31],
+    U9S(16),U9T(16),U9V(18)[31],U9W(16),UA0T(18)[32],UA8H(18)[31],
+    UA8I(18)[31],UA8O(18)[31],UA8P(18)[31],UA8S(16)[30],UA8T(16)[30],
+    UA8U(18)[31],UA8V(18)[31],UA8W(16)[30],UA8Y(18)[31],UA8Z(18)[31],
+    UA9I(18)[31],UA9M(17)[30],UA9P(18)[31],UA9S(16),UA9T(16),UA9V(18)[31],
+    UA9W(16),UB0T(18)[32],UB8H(18)[31],UB8I(18)[31],UB8O(18)[31],UB8P(18)[31],
+    UB8S(16)[30],UB8T(16)[30],UB8U(18)[31],UB8V(18)[31],UB8W(16)[30],
+    UB8Y(18)[31],UB8Z(18)[31],UB9I(18)[31],UB9M(17)[30],UB9P(18)[31],UB9S(16),
+    UB9T(16),UB9V(18)[31],UB9W(16),UC0T(18)[32],UC8H(18)[31],UC8I(18)[31],
+    UC8O(18)[31],UC8P(18)[31],UC8S(16)[30],UC8T(16)[30],UC8U(18)[31],
+    UC8V(18)[31],UC8W(16)[30],UC8Y(18)[31],UC8Z(18)[31],UC9I(18)[31],
+    UC9M(17)[30],UC9P(18)[31],UC9S(16),UC9T(16),UC9V(18)[31],UC9W(16),
+    UD0T(18)[32],UD8H(18)[31],UD8I(18)[31],UD8O(18)[31],UD8P(18)[31],
+    UD8S(16)[30],UD8T(16)[30],UD8U(18)[31],UD8V(18)[31],UD8W(16)[30],
+    UD8Y(18)[31],UD8Z(18)[31],UD9I(18)[31],UD9M(17)[30],UD9P(18)[31],UD9S(16),
+    UD9T(16),UD9V(18)[31],UD9W(16),UE0T(18)[32],UE8H(18)[31],UE8I(18)[31],
+    UE8O(18)[31],UE8P(18)[31],UE8S(16)[30],UE8T(16)[30],UE8U(18)[31],
+    UE8V(18)[31],UE8W(16)[30],UE8Y(18)[31],UE8Z(18)[31],UE9I(18)[31],
+    UE9M(17)[30],UE9P(18)[31],UE9S(16),UE9T(16),UE9V(18)[31],UE9W(16),
+    UF0T(18)[32],UF8H(18)[31],UF8I(18)[31],UF8O(18)[31],UF8P(18)[31],
+    UF8S(16)[30],UF8T(16)[30],UF8U(18)[31],UF8V(18)[31],UF8W(16)[30],
+    UF8Y(18)[31],UF8Z(18)[31],UF9I(18)[31],UF9M(17)[30],UF9P(18)[31],UF9S(16),
+    UF9T(16),UF9V(18)[31],UF9W(16),UG0T(18)[32],UG8H(18)[31],UG8I(18)[31],
+    UG8O(18)[31],UG8P(18)[31],UG8S(16)[30],UG8T(16)[30],UG8U(18)[31],
+    UG8V(18)[31],UG8W(16)[30],UG8Y(18)[31],UG8Z(18)[31],UG9I(18)[31],
+    UG9M(17)[30],UG9P(18)[31],UG9S(16),UG9T(16),UG9V(18)[31],UG9W(16),
+    UH0T(18)[32],UH8H(18)[31],UH8I(18)[31],UH8O(18)[31],UH8P(18)[31],
+    UH8S(16)[30],UH8T(16)[30],UH8U(18)[31],UH8V(18)[31],UH8W(16)[30],
+    UH8Y(18)[31],UH8Z(18)[31],UH9I(18)[31],UH9M(17)[30],UH9P(18)[31],UH9S(16),
+    UH9T(16),UH9V(18)[31],UH9W(16),UI0T(18)[32],UI8H(18)[31],UI8I(18)[31],
+    UI8O(18)[31],UI8P(18)[31],UI8S(16)[30],UI8T(16)[30],UI8U(18)[31],
+    UI8V(18)[31],UI8W(16)[30],UI8Y(18)[31],UI8Z(18)[31],UI9I(18)[31],
+    UI9M(17)[30],UI9P(18)[31],UI9S(16),UI9T(16),UI9V(18)[31],UI9W(16),
+    =R27UFA(16),=R4WAB/9/P,=R8OA/9/P(18)[31],=R9OOO/9/P(23)[32],
+    =R9OY/9/P(23)[32],=RA/DL6XK,=RA/KE5JA(19)[34],=RA/UR5HVR(18)[32],
+    =RA27TR(16),=RU27WB(16),=RU27WF(16),=RU27WN(16),=RU27WO(16),
+    =RZ9DX/9/P(18)[22];
+Uzbekistan:               17:  30:  AS:   41.40:   -63.97:    -5.0:  UK:
+    UJ,UK,UL,UM;
+Kazakhstan:               17:  30:  AS:   48.17:   -65.18:    -5.0:  UN:
+    UN,UO,UP,UQ,UN0D[31],UN0F[31],UN0G[31],UN0J[31],UN0Q[31],UN0V[31],
+    UN1D[31],UN1F[31],UN1G[31],UN1J[31],UN1Q[31],UN1V[31],UN2D[31],UN2F[31],
+    UN2G[31],UN2J[31],UN2Q[31],UN2V[31],UN3D[31],UN3F[31],UN3G[31],UN3J[31],
+    UN3Q[31],UN3V[31],UN4D[31],UN4F[31],UN4G[31],UN4J[31],UN4Q[31],UN4V[31],
+    UN5D[31],UN5F[31],UN5G[31],UN5J[31],UN5Q[31],UN5V[31],UN6D[31],UN6F[31],
+    UN6G[31],UN6J[31],UN6Q[31],UN6V[31],UN7D[31],UN7F[31],UN7G[31],UN7J[31],
+    UN7Q[31],UN7V[31],UN8D[31],UN8F[31],UN8G[31],UN8J[31],UN8Q[31],UN8V[31],
+    UN9D[31],UN9F[31],UN9G[31],UN9J[31],UN9Q[31],UN9V[31],UO0D[31],UO0F[31],
+    UO0G[31],UO0J[31],UO0Q[31],UO0V[31],UO1D[31],UO1F[31],UO1G[31],UO1J[31],
+    UO1Q[31],UO1V[31],UO2D[31],UO2F[31],UO2G[31],UO2J[31],UO2Q[31],UO2V[31],
+    UO3D[31],UO3F[31],UO3G[31],UO3J[31],UO3Q[31],UO3V[31],UO4D[31],UO4F[31],
+    UO4G[31],UO4J[31],UO4Q[31],UO4V[31],UO5D[31],UO5F[31],UO5G[31],UO5J[31],
+    UO5Q[31],UO5V[31],UO6D[31],UO6F[31],UO6G[31],UO6J[31],UO6Q[31],UO6V[31],
+    UO7D[31],UO7F[31],UO7G[31],UO7J[31],UO7Q[31],UO7V[31],UO8D[31],UO8F[31],
+    UO8G[31],UO8J[31],UO8Q[31],UO8V[31],UO9D[31],UO9F[31],UO9G[31],UO9J[31],
+    UO9Q[31],UO9V[31],UP0D[31],UP0F[31],UP0G[31],UP0J[31],UP0Q[31],UP0V[31],
+    UP1D[31],UP1F[31],UP1G[31],UP1J[31],UP1Q[31],UP1V[31],UP2D[31],UP2F[31],
+    UP2G[31],UP2J[31],UP2Q[31],UP2V[31],UP3D[31],UP3F[31],UP3G[31],UP3J[31],
+    UP3Q[31],UP3V[31],UP4D[31],UP4F[31],UP4G[31],UP4J[31],UP4Q[31],UP4V[31],
+    UP5D[31],UP5F[31],UP5G[31],UP5J[31],UP5Q[31],UP5V[31],UP6D[31],UP6F[31],
+    UP6G[31],UP6J[31],UP6Q[31],UP6V[31],UP7D[31],UP7F[31],UP7G[31],UP7J[31],
+    UP7Q[31],UP7V[31],UP8D[31],UP8F[31],UP8G[31],UP8J[31],UP8Q[31],UP8V[31],
+    UP9D[31],UP9F[31],UP9G[31],UP9J[31],UP9Q[31],UP9V[31],UQ0D[31],UQ0F[31],
+    UQ0G[31],UQ0J[31],UQ0Q[31],UQ0V[31],UQ1D[31],UQ1F[31],UQ1G[31],UQ1J[31],
+    UQ1Q[31],UQ1V[31],UQ2D[31],UQ2F[31],UQ2G[31],UQ2J[31],UQ2Q[31],UQ2V[31],
+    UQ3D[31],UQ3F[31],UQ3G[31],UQ3J[31],UQ3Q[31],UQ3V[31],UQ4D[31],UQ4F[31],
+    UQ4G[31],UQ4J[31],UQ4Q[31],UQ4V[31],UQ5D[31],UQ5F[31],UQ5G[31],UQ5J[31],
+    UQ5Q[31],UQ5V[31],UQ6D[31],UQ6F[31],UQ6G[31],UQ6J[31],UQ6Q[31],UQ6V[31],
+    UQ7D[31],UQ7F[31],UQ7G[31],UQ7J[31],UQ7Q[31],UQ7V[31],UQ8D[31],UQ8F[31],
+    UQ8G[31],UQ8J[31],UQ8Q[31],UQ8V[31],UQ9D[31],UQ9F[31],UQ9G[31],UQ9J[31],
+    UQ9Q[31],UQ9V[31];
+Ukraine:                  16:  29:  EU:   50.00:   -30.00:    -2.0:  UR:
+    EM,EN,EO,U5,UR,US,UT,UU,UV,UW,UX,UY,UZ;
+Antigua & Barbuda:        08:  11:  NA:   17.07:    61.80:     4.0:  V2:
+    V2;
+Belize:                   07:  11:  NA:   16.97:    88.67:     6.0:  V3:
+    V3;
+St. Kitts & Nevis:        08:  11:  NA:   17.37:    62.78:     4.0:  V4:
+    V4;
+Namibia:                  38:  57:  AF:  -22.00:   -17.00:    -1.0:  V5:
+    V5;
+Micronesia:               27:  65:  OC:    6.88:  -158.20:   -10.0:  V6:
+    V6;
+Marshall Islands:         31:  65:  OC:    9.08:  -167.33:   -12.0:  V7:
+    V7;
+Brunei Darussalam:        28:  54:  OC:    4.50:  -114.60:    -8.0:  V8:
+    V8;
+Canada:                   05:  09:  NA:   44.35:    78.75:     5.0:  VE:
+    CF,CG,CJ,CK,VA,VB,VC,VE,VG,VX,XL,XM,CF2[4],CG2[4],CH1,CH2(2),CI0(2)[4],
+    CI1(1)[2],CI2,CJ2[4],CK2[4],CY1,CY2(2),CZ0(2)[4],CZ1(1)[2],CZ2,VA2[4],
+    VB2[4],VC2[4],VD1,VD2(2),VE2[4],VF0(2)[4],VF1(1)[2],VF2,VG2[4],VO1,VO2(2),
+    VX2[4],VY0(2)[4],VY1(1)[2],VY2,XJ1,XJ2(2),XK0(2)[4],XK1(1)[2],XK2,XL2[4],
+    XM2[4],XN1,XN2(2),XO0(2)[4],XO1(1)[2],XO2,=VER20130625,=VA2PL(2)[4],
+    =VE2DXY(2)[4],=VE2EKA(2)[4],=VE2ENB(2)[4],=VE2EW(2)[4],=VE2FK[9],
+    =VE2GSO(2)[4],=VE2IM(2)[4],=VE2KK(2)[4],=VE3GNO/2[4],=VY0PW(4)[3];
+Australia:                30:  59:  OC:  -23.70:  -132.33:   -10.0:  VK:
+    AX,VH,VI,VJ,VK,VL,VM,VN,VZ,AX4[55],VH4[55],VI4[55],VJ4[55],VK4[55],
+    VL4[55],VM4[55],VN4[55],VZ4[55],=VI103WIA(29)[58];
+Heard Island:             39:  68:  AF:  -53.08:   -73.50:    -5.0:  VK0H:
+    =VK0IR;
+Macquarie Island:         30:  60:  OC:  -54.60:  -158.88:   -10.0:  VK0M:
+    =AX/VK0TH;
+Cocos (Keeling) Islands:  29:  54:  OC:  -12.15:   -96.82:    -6.5:  VK9C:
+    AX9C,AX9Y,VH9C,VH9Y,VI9C,VI9Y,VJ9C,VJ9Y,VK9C,VK9Y,VL9C,VL9Y,VM9C,VM9Y,
+    VN9C,VN9Y,VZ9C,VZ9Y;
+Lord Howe Island:         30:  60:  OC:  -31.55:  -159.08:   -10.5:  VK9L:
+    AX9L,VH9L,VI9L,VJ9L,VK9L,VL9L,VM9L,VN9L,VZ9L;
+Mellish Reef:             30:  56:  OC:  -17.40:  -155.85:   -10.0:  VK9M:
+    AX9M,VH9M,VI9M,VJ9M,VK9M,VL9M,VM9M,VN9M,VZ9M;
+Norfolk Island:           32:  60:  OC:  -29.03:  -167.93:   -11.5:  VK9N:
+    AX9,VH9,VI9,VJ9,VK9,VL9,VM9,VN9,VZ9;
+Willis Island:            30:  55:  OC:  -16.22:  -150.02:   -10.0:  VK9W:
+    AX9W,AX9Z,VH9W,VH9Z,VI9W,VI9Z,VJ9W,VJ9Z,VK9W,VK9Z,VL9W,VL9Z,VM9W,VM9Z,
+    VN9W,VN9Z,VZ9W,VZ9Z;
+Christmas Island:         29:  54:  OC:  -10.48:  -105.63:    -7.0:  VK9X:
+    AX9X,VH9X,VI9X,VJ9X,VK9X,VL9X,VM9X,VN9X,VZ9X,=VK9DAC;
+Anguilla:                 08:  11:  NA:   18.23:    63.00:     4.0:  VP2E:
+    VP2E;
+Montserrat:               08:  11:  NA:   16.75:    62.18:     4.0:  VP2M:
+    VP2M;
+British Virgin Islands:   08:  11:  NA:   18.33:    64.75:     4.0:  VP2V:
+    VP2V;
+Turks & Caicos Islands:   08:  11:  NA:   21.77:    71.75:     5.0:  VP5:
+    VP5,VQ5;
+Pitcairn Island:          32:  63:  OC:  -24.35:   128.32:     8.0:  VP6:
+    VP6;
+Ducie Island:             32:  63:  OC:  -24.70:   124.80:     8.0:  VP6/d:
+    =VP6DX;
+Falkland Islands:         13:  16:  SA:  -51.63:    58.72:     4.0:  VP8:
+    VP8;
+South Georgia Island:     13:  73:  SA:  -54.48:    37.08:     2.0:  VP8/g:
+    =VP8SGK;
+South Shetland Islands:   13:  73:  SA:  -62.08:    58.67:     4.0:  VP8/h:
+    CE9,XR9,=DT8A,=HF0POL,=RI1ANA,=RI1ANF,=RI1ANF/P,=RI1ANU;
+South Orkney Islands:     13:  73:  SA:  -60.60:    45.55:     3.0:  VP8/o:
+    =LU1ZA;
+South Sandwich Islands:   13:  73:  SA:  -58.43:    26.33:     2.0:  VP8/s:
+    =VP8THU;
+Bermuda:                  05:  11:  NA:   32.32:    64.73:     4.0:  VP9:
+    VP9;
+Chagos Islands:           39:  41:  AF:   -7.32:   -72.42:    -6.0:  VQ9:
+    VQ9;
+Hong Kong:                24:  44:  AS:   22.28:  -114.18:    -8.0:  VR:
+    VR;
+India:                    22:  41:  AS:   22.50:   -77.58:    -5.5:  VU:
+    8T,8U,8V,8W,8X,8Y,AT,AU,AV,AW,VT,VU,VV,VW;
+Andaman & Nicobar Is.:    26:  49:  AS:   12.37:   -92.78:    -5.5:  VU4:
+    VU4;
+Lakshadweep Islands:      22:  41:  AS:   11.23:   -72.78:    -5.5:  VU7:
+    VU7;
+Mexico:                   06:  10:  NA:   21.32:   100.23:     6.0:  XE:
+    4A,4B,4C,6D,6E,6F,6G,6H,6I,6J,XA,XB,XC,XD,XE,XF,XG,XH,XI;
+Revillagigedo:            06:  10:  NA:   18.77:   110.97:     7.0:  XF4:
+    4A4,4B4,4C4,6D4,6E4,6F4,6G4,6H4,6I4,6J4,XA4,XB4,XC4,XD4,XE4,XF0,XF4,XG4,
+    XH4,XI4;
+Burkina Faso:             35:  46:  AF:   12.00:     2.00:     0.0:  XT:
+    XT;
+Cambodia:                 26:  49:  AS:   12.93:  -105.13:    -7.0:  XU:
+    XU;
+Laos:                     26:  49:  AS:   18.20:  -104.55:    -7.0:  XW:
+    XW;
+Macao:                    24:  44:  AS:   22.10:  -113.50:    -8.0:  XX9:
+    XX9;
+Myanmar:                  26:  49:  AS:   20.00:   -96.37:    -6.5:  XZ:
+    XY,XZ;
+Afghanistan:              21:  40:  AS:   34.70:   -65.80:    -4.5:  YA:
+    T6,YA;
+Indonesia:                28:  51:  OC:   -7.30:  -109.88:    -7.0:  YB:
+    7A,7B,7C,7D,7E,7F,7G,7H,7I,8A,8B,8C,8D,8E,8F,8G,8H,8I,JZ,PK,PL,PM,PN,PO,
+    YB,YC,YD,YE,YF,YG,YH,YB0[54],YB1[54],YB2[54],YB3[54],YB4[54],YB5[54],
+    YB6[54],YB7[54],YB8[54],YC0[54],YC1[54],YC2[54],YC3[54],YC4[54],YC5[54],
+    YC6[54],YC7[54],YC8[54],YD0[54],YD1[54],YD2[54],YD3[54],YD4[54],YD5[54],
+    YD6[54],YD7[54],YD8[54],YE0[54],YE1[54],YE2[54],YE3[54],YE4[54],YE5[54],
+    YE6[54],YE7[54],YE8[54],YF0[54],YF1[54],YF2[54],YF3[54],YF4[54],YF5[54],
+    YF6[54],YF7[54],YF8[54],YG0[54],YG1[54],YG2[54],YG3[54],YG4[54],YG5[54],
+    YG6[54],YG7[54],YG8[54],YH0[54],YH1[54],YH2[54],YH3[54],YH4[54],YH5[54],
+    YH6[54],YH7[54],YH8[54];
+Iraq:                     21:  39:  AS:   33.92:   -42.78:    -3.0:  YI:
+    HN,YI;
+Vanuatu:                  32:  56:  OC:  -17.67:  -168.38:   -11.0:  YJ:
+    YJ;
+Syria:                    20:  39:  AS:   35.38:   -38.20:    -2.0:  YK:
+    6C,YK;
+Latvia:                   15:  29:  EU:   57.03:   -24.65:    -2.0:  YL:
+    YL;
+Nicaragua:                07:  11:  NA:   12.88:    85.05:     6.0:  YN:
+    H6,H7,HT,YN;
+Romania:                  20:  28:  EU:   45.78:   -24.70:    -2.0:  YO:
+    YO,YP,YQ,YR;
+El Salvador:              07:  11:  NA:   14.00:    89.00:     6.0:  YS:
+    HU,YS;
+Serbia:                   15:  28:  EU:   44.00:   -21.00:    -1.0:  YU:
+    YT,YU;
+Venezuela:                09:  12:  SA:    8.00:    66.00:     4.5:  YV:
+    4M,YV,YW,YX,YY;
+Aves Island:              08:  11:  NA:   15.67:    63.60:     4.0:  YV0:
+    4M0,YV0,YW0,YX0,YY0;
+Zimbabwe:                 38:  53:  AF:  -18.00:   -31.00:    -2.0:  Z2:
+    Z2;
+Macedonia:                15:  28:  EU:   41.60:   -21.65:    -1.0:  Z3:
+    Z3;
+Kosovo:                   15:  28:  EU:   42.67:   -21.17:    -1.0:  *Z6:
+    Z6,=YU8/IV3LAR;
+Republic of South Sudan:  34:  48:  AF:    4.85:   -31.60:    -3.0:  Z8:
+    Z8;
+Albania:                  15:  28:  EU:   41.00:   -20.00:    -1.0:  ZA:
+    ZA;
+Gibraltar:                14:  37:  EU:   36.15:     5.37:    -1.0:  ZB:
+    ZB,ZG;
+UK Base Areas on Cyprus:  20:  39:  AS:   35.32:   -33.57:    -2.0:  ZC4:
+    ZC4;
+St. Helena:               36:  66:  AF:  -15.97:     5.72:     0.0:  ZD7:
+    ZD7;
+Ascension Island:         36:  66:  AF:   -7.93:    14.37:     0.0:  ZD8:
+    ZD8;
+Tristan da Cunha & Gough: 38:  66:  AF:  -37.13:    12.30:     0.0:  ZD9:
+    ZD9;
+Cayman Islands:           08:  11:  NA:   19.32:    81.22:     5.0:  ZF:
+    ZF;
+Tokelau Islands:          31:  62:  OC:   -9.40:   171.20:   -13.0:  ZK3:
+    ZK3;
+New Zealand:              32:  60:  OC:  -41.83:  -173.27:   -12.0:  ZL:
+    ZK,ZL,ZM;
+Chatham Islands:          32:  60:  OC:  -43.85:   176.48:  -12.75:  ZL7:
+    ZL7,ZM7;
+Kermadec Islands:         32:  60:  OC:  -29.25:   177.92:   -12.0:  ZL8:
+    ZL8,ZM8;
+Auckland & Campbell Is.:  32:  60:  OC:  -51.62:  -167.62:   -12.0:  ZL9:
+    ZL9,ZM9;
+Paraguay:                 11:  14:  SA:  -25.27:    57.67:     4.0:  ZP:
+    ZP;
+South Africa:             38:  57:  AF:  -29.07:   -22.63:    -2.0:  ZS:
+    H5,S4,S8,V9,ZR,ZS,ZT,ZU;
+Pr. Edward & Marion Is.:  38:  57:  AF:  -46.88:   -37.72:    -3.0:  ZS8:
+    ZR8,ZS8,ZT8,ZU8;
diff --git a/debian/CMakeLists.txt b/debian/CMakeLists.txt
new file mode 100644
index 0000000..8a27273
--- /dev/null
+++ b/debian/CMakeLists.txt
@@ -0,0 +1,39 @@
+find_program (GZIP_EXECUTABLE NAMES gzip)
+
+string (TIMESTAMP ts "%w, %d [%m] %Y %H:%M:%S +0000" UTC)
+
+set (__days Sun Mon Tue Wed Thu Fri Sat)
+string (SUBSTRING ${ts} 0 1 __index)
+list (GET __days ${__index} __day)
+string (REPLACE "${__index}," "${__day}," ts ${ts})
+
+set (__months Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec)
+string (SUBSTRING ${ts} 9 2 __month_index)
+math (EXPR __index "${__month_index} - 1")
+list (GET __months "${__index}" __month)
+string (REPLACE "[${__month_index}]" "${__month}" ts ${ts})
+
+set (deb_changelog changelog.Debian)
+configure_file (
+  "${CMAKE_CURRENT_SOURCE_DIR}/${deb_changelog}.in"
+  "${CMAKE_CURRENT_BINARY_DIR}/${deb_changelog}"
+  @ONLY)
+
+add_custom_target (debian
+  COMMAND ${GZIP_EXECUTABLE} -cf9 ${deb_changelog} > ${deb_changelog}.gz
+  DEPENDS ${deb_changelog}.in
+  WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+  COMMENT "Compressing Debian changelog"
+  )
+
+configure_file (
+  "${CMAKE_CURRENT_SOURCE_DIR}/copyright.in"
+  "${CMAKE_CURRENT_BINARY_DIR}/copyright"
+  @ONLY)
+
+install (FILES
+  ${CMAKE_CURRENT_BINARY_DIR}/${deb_changelog}.gz
+  ${CMAKE_CURRENT_BINARY_DIR}/copyright
+  DESTINATION ${WSJT_SHARE_DESTINATION}/${WSJT_DOC_DESTINATION}
+  #COMPONENT Debian
+  )
diff --git a/debian/changelog.Debian.in b/debian/changelog.Debian.in
new file mode 100644
index 0000000..c001624
--- /dev/null
+++ b/debian/changelog.Debian.in
@@ -0,0 +1,6 @@
+ at CMAKE_PROJECT_NAME@ (@wsjtx_VERSION@) experimental; urgency=low
+
+  * wsjtx Debian maintainer and upstream author are identical.
+    Therefore see also normal changelog file for Debian changes.
+
+ -- @PROJECT_CONTACT@  @ts@
diff --git a/debian/copyright.in b/debian/copyright.in
new file mode 100644
index 0000000..110219a
--- /dev/null
+++ b/debian/copyright.in
@@ -0,0 +1,10 @@
+Format-Specification: http://wiki.debian.org/Proposals/CopyrightFormat
+Upstream-Name: @CMAKE_PROJECT_NAME@
+Upstream-Maintainer: @PROJECT_CONTACT@
+Upstream-Source: @PROJECT_HOMEPAGE@
+
+Files: *
+Copyright: @PROJECT_COPYRIGHT at .
+License: GPL v3
+ The full text of the GPL is distributed in
+ /usr/share/common-licenses/GPL-3 on Debian systems.
diff --git a/decodedtext.cpp b/decodedtext.cpp
new file mode 100644
index 0000000..0e90440
--- /dev/null
+++ b/decodedtext.cpp
@@ -0,0 +1,166 @@
+#include <QStringList>
+#include <QDebug>
+#include "decodedtext.h"
+
+QString DecodedText::CQersCall()
+{
+    // extract the CQer's call   TODO: does this work with all call formats?
+  int s1 {0};
+  int position;
+  if ((position = _string.indexOf (" CQ DX ")) >= 0)
+    {
+      s1 = 7 + position;
+    }
+  else if ((position = _string.indexOf (" CQ ")) >= 0)
+    {
+      s1 = 4 + position;
+    }
+  else if ((position = _string.indexOf (" DE ")) >= 0)
+    {
+      s1 = 4 + position;
+    }
+  else if ((position = _string.indexOf (" QRZ ")) >= 0)
+    {
+      s1 = 5 + position;
+    }
+  auto s2 = _string.indexOf (" ", s1);
+  return _string.mid (s1, s2 - s1);
+}
+
+
+bool DecodedText::isJT65()
+{
+    return _string.indexOf("#") == column_mode;
+}
+
+bool DecodedText::isJT9()
+{
+    return _string.indexOf("@") == column_mode;
+}
+
+bool DecodedText::isTX()
+{
+    int i = _string.indexOf("Tx");
+    return (i >= 0 && i < 15); // TODO guessing those numbers. Does Tx ever move?
+}
+
+int DecodedText::frequencyOffset()
+{
+    return _string.mid(column_freq,4).toInt();
+}
+
+int DecodedText::snr()
+{
+    return _string.mid(column_snr,3).toInt();
+}
+
+/*
+2343 -11  0.8 1259 # YV6BFE F6GUU R-08
+2343 -19  0.3  718 # VE6WQ SQ2NIJ -14
+2343  -7  0.3  815 # KK4DSD W7VP -16
+2343 -13  0.1 3627 @ CT1FBK IK5YZT R+02
+
+0605  Tx      1259 # CQ VK3ACF QF22
+*/
+
+// find and extract any report. Returns true if this is a standard message
+bool DecodedText::report(QString const& myBaseCall, QString const& dxBaseCall, /*mod*/QString& report)
+{
+    QString msg=_string.mid(column_qsoText);
+    int i1=msg.indexOf("\r");
+    if (i1>0)
+        msg=msg.mid(0,i1-1) + "                      ";
+    bool b = stdmsg_(msg.mid(0,22).toLatin1().constData(),22);  // stdmsg is a fortran routine that packs the text, unpacks it and compares the result
+
+    QStringList w=msg.split(" ",QString::SkipEmptyParts);
+    if(b && (w[0] == myBaseCall
+             || w[0].endsWith ("/" + myBaseCall)
+             || w[0].startsWith (myBaseCall + "/")
+             || (w.size () > 1 && !dxBaseCall.isEmpty ()
+                 && (w[1] == dxBaseCall
+                     || w[1].endsWith ("/" + dxBaseCall)
+                     || w[1].startsWith (dxBaseCall + "/")))))
+    {
+        QString tt="";
+        if(w.size() > 2) tt=w[2];
+        bool ok;
+        i1=tt.toInt(&ok);
+        if (ok and i1>=-50 and i1<50)
+        {
+            report = tt;
+//            qDebug() << "report for " << _string << "::" << report;
+        }
+        else
+        {
+            if (tt.mid(0,1)=="R")
+            {
+                i1=tt.mid(1).toInt(&ok);
+                if(ok and i1>=-50 and i1<50)
+                {
+                    report = tt.mid(1);
+//                    qDebug() << "report for " << _string << "::" << report;
+                }
+            }
+        }
+    }
+    return b;
+}
+
+// get the first text word, usually the call
+QString DecodedText::call()
+{
+  auto call = _string;
+  call = call.replace (" CQ DX ", " CQ_DX ").mid (column_qsoText);
+  int i = call.indexOf(" ");
+  return call.mid(0,i);
+}
+
+// get the second word, most likely the de call and the third word, most likely grid
+void DecodedText::deCallAndGrid(/*out*/QString& call, QString& grid)
+{
+  auto msg = _string;
+  msg = msg.replace (" CQ DX ", " CQ_DX ").mid (column_qsoText);
+  int i1 = msg.indexOf(" ");
+  call = msg.mid(i1+1);
+  int i2 = call.indexOf(" ");
+  grid = call.mid(i2+1,4);
+  call = call.mid(0,i2);
+}
+
+int DecodedText::timeInSeconds()
+{
+    return 60*_string.mid(column_time,2).toInt() + _string.mid(2,2).toInt();
+}
+
+/*
+2343 -11  0.8 1259 # YV6BFE F6GUU R-08
+2343 -19  0.3  718 # VE6WQ SQ2NIJ -14
+2343  -7  0.3  815 # KK4DSD W7VP -16
+2343 -13  0.1 3627 @ CT1FBK IK5YZT R+02
+
+0605  Tx      1259 # CQ VK3ACF QF22
+*/
+
+QString DecodedText::report()  // returns a string of the SNR field with a leading + or - followed by two digits
+{
+    int sr = snr();
+    if (sr<-50)
+        sr = -50;
+    else
+        if (sr > 49)
+            sr = 49;
+
+    QString rpt;
+    rpt.sprintf("%d",abs(sr));
+    if (sr > 9)
+        rpt = "+" + rpt;
+    else
+        if (sr >= 0)
+            rpt = "+0" + rpt;
+        else
+            if (sr >= -9)
+                rpt = "-0" + rpt;
+            else
+                rpt = "-" + rpt;
+    return rpt;
+}
diff --git a/decodedtext.h b/decodedtext.h
new file mode 100644
index 0000000..6d2639a
--- /dev/null
+++ b/decodedtext.h
@@ -0,0 +1,91 @@
+// -*- Mode: C++ -*-
+/*
+ * Class to handle the formatted string as returned from the fortran decoder
+ *
+ * VK3ACF August 2013
+ */
+
+
+#ifndef DECODEDTEXT_H
+#define DECODEDTEXT_H
+
+#include <QString>
+
+
+
+/*
+0123456789012345678901234567890123456789
+^    ^    ^   ^    ^ ^
+2343 -11  0.8 1259 # YV6BFE F6GUU R-08
+2343 -19  0.3  718 # VE6WQ SQ2NIJ -14
+2343  -7  0.3  815 # KK4DSD W7VP -16
+2343 -13  0.1 3627 @ CT1FBK IK5YZT R+02
+
+0605  Tx      1259 # CQ VK3ACF QF22
+*/
+
+class DecodedText
+{
+public:
+     // These define the columns in the decoded text where fields are to be found.
+     // We rely on these columns being the same in the fortran code (lib/decode.f90) that formats the decoded text
+     enum Columns { column_time    = 0,
+                    column_snr     = 5,
+                    column_freq    = 14,
+                    column_mode    = 19,
+                    column_qsoText = 21 };
+
+    void operator=(const QString &rhs)
+    {
+        _string = rhs;
+    };
+    void operator=(const QByteArray &rhs)
+    {
+        _string = rhs;
+    };
+
+    void operator+=(const QString &rhs)
+    {
+        _string += rhs;
+    };
+
+    QString string() { return _string; };
+
+    int indexOf(QString s) { return _string.indexOf(s); };
+    int indexOf(QString s, int i) { return _string.indexOf(s,i); };
+    QString mid(int f, int t) { return _string.mid(f,t); };
+    QString left(int i) { return _string.left(i); };
+
+    void clear() { _string.clear(); };
+
+    QString CQersCall();
+
+    bool isJT65();
+    bool isJT9();
+    bool isTX();
+    int frequencyOffset();  // hertz offset from the tuned dial or rx frequency, aka audio frequency
+    int snr();
+
+    // find and extract any report. Returns true if this is a standard message
+  bool report(QString const& myBaseCall, QString const& dxBaseCall, /*mod*/QString& report);
+
+    // get the first text word, usually the call
+    QString call();
+
+    // get the second word, most likely the de call and the third word, most likely grid
+    void deCallAndGrid(/*out*/QString& call, QString& grid);
+
+    int timeInSeconds();
+
+    // returns a string of the SNR field with a leading + or - followed by two digits
+    QString report();
+
+private:
+    QString _string;
+    
+};
+
+
+extern "C" {  bool stdmsg_(const char* msg, int len); }
+
+#endif // DECODEDTEXT_H
diff --git a/devsetup.cpp b/devsetup.cpp
deleted file mode 100644
index 018a188..0000000
--- a/devsetup.cpp
+++ /dev/null
@@ -1,595 +0,0 @@
-#include "devsetup.h"
-#include <QDebug>
-#include <QSettings>
-#include <portaudio.h>
-
-#define MAXDEVICES 100
-
-extern double dFreq[16];
-qint32  g2_iptt;
-qint32  g2_COMportOpen;
-
-//----------------------------------------------------------- DevSetup()
-DevSetup::DevSetup(QWidget *parent) :	QDialog(parent)
-{
-  ui.setupUi(this);	                              //setup the dialog form
-  m_restartSoundIn=false;
-  m_restartSoundOut=false;
-  m_firstCall=true;
-  g2_iptt=0;
-  m_test=0;
-  m_bRigOpen=false;
-  g2_COMportOpen=0;
-}
-
-DevSetup::~DevSetup()
-{
-}
-
-void DevSetup::initDlg()
-{
-  QString m_appDir = QApplication::applicationDirPath();
-  QString inifile = m_appDir + "/wsjtx.ini";
-  QSettings settings(inifile, QSettings::IniFormat);
-  settings.beginGroup("Common");
-  QString catPortDriver = settings.value("CATdriver","None").toString();
-  settings.endGroup();
-
-  int k,id;
-  int numDevices=Pa_GetDeviceCount();
-
-  const PaDeviceInfo *pdi;
-  int nchin;
-  int nchout;
-  char pa_device_name[128];
-  char pa_device_hostapi[128];
-
-  k=0;
-  for(id=0; id<numDevices; id++ )  {
-    pdi=Pa_GetDeviceInfo(id);
-    nchin=pdi->maxInputChannels;
-    if(nchin>0) {
-      m_inDevList[k]=id;
-      if (id == m_paInDevice)
-        m_nDevIn = k;
-      k++;
-      sprintf((char*)(pa_device_name),"%s",pdi->name);
-      sprintf((char*)(pa_device_hostapi),"%s",
-              Pa_GetHostApiInfo(pdi->hostApi)->name);
-
-#ifdef WIN32
-      char *p,*p1;
-      char p2[50];
-      p1=(char*)"";
-      p=strstr(pa_device_hostapi,"MME");
-      if(p!=NULL) p1=(char*)"MME";
-      p=strstr(pa_device_hostapi,"Direct");
-      if(p!=NULL) p1=(char*)"DirectX";
-      p=strstr(pa_device_hostapi,"WASAPI");
-      if(p!=NULL) p1=(char*)"WASAPI";
-      p=strstr(pa_device_hostapi,"ASIO");
-      if(p!=NULL) p1=(char*)"ASIO";
-      p=strstr(pa_device_hostapi,"WDM-KS");
-      if(p!=NULL) p1=(char*)"WDM-KS";
-
-      sprintf(p2,"%2d   %d   %-8s  %-39s",id,nchin,p1,pa_device_name);
-      QString t(p2);
-#else
-      QString t;
-      t.sprintf("%2d   %d   %-8s  %-39s",id,nchin,
-                Pa_GetHostApiInfo(pdi->hostApi)->name,pdi->name);
-#endif
-      ui.comboBoxSndIn->addItem(t);
-    }
-  }
-
-  k=0;
-  for(id=0; id<numDevices; id++ )  {
-    pdi=Pa_GetDeviceInfo(id);
-    nchout=pdi->maxOutputChannels;
-    if(nchout>0) {
-      m_outDevList[k]=id;
-      if (id == m_paOutDevice)
-        m_nDevOut = k;
-      k++;
-      sprintf((char*)(pa_device_name),"%s",pdi->name);
-      sprintf((char*)(pa_device_hostapi),"%s",
-              Pa_GetHostApiInfo(pdi->hostApi)->name);
-
-#ifdef WIN32
-      char *p,*p1;
-      char p2[50];
-      p1=(char*)"";
-      p=strstr(pa_device_hostapi,"MME");
-      if(p!=NULL) p1=(char*)"MME";
-      p=strstr(pa_device_hostapi,"Direct");
-      if(p!=NULL) p1=(char*)"DirectX";
-      p=strstr(pa_device_hostapi,"WASAPI");
-      if(p!=NULL) p1=(char*)"WASAPI";
-      p=strstr(pa_device_hostapi,"ASIO");
-      if(p!=NULL) p1=(char*)"ASIO";
-      p=strstr(pa_device_hostapi,"WDM-KS");
-      if(p!=NULL) p1=(char*)"WDM-KS";
-      sprintf(p2,"%2d   %d   %-8s  %-39s",id,nchout,p1,pa_device_name);
-      QString t(p2);
-#else
-      QString t;
-      t.sprintf("%2d   %d   %-8s  %-39s",id,nchout,
-                Pa_GetHostApiInfo(pdi->hostApi)->name,pdi->name);
-#endif
-      ui.comboBoxSndOut->addItem(t);
-    }
-  }
-
-  connect(&p4, SIGNAL(readyReadStandardOutput()),
-                    this, SLOT(p4ReadFromStdout()));
-  connect(&p4, SIGNAL(readyReadStandardError()),
-          this, SLOT(p4ReadFromStderr()));
-  connect(&p4, SIGNAL(error(QProcess::ProcessError)),
-          this, SLOT(p4Error()));
-  p4.start("rigctl -l");
-  p4.waitForFinished(1000);
-  ui.rigComboBox->addItem("  9998 Commander");
-  ui.rigComboBox->addItem("  9999 Ham Radio Deluxe");
-
-  QPalette pal(ui.myCallEntry->palette());
-  if(m_myCall=="") {
-    pal.setColor(QPalette::Base,"#ffccff");
-  } else {
-    pal.setColor(QPalette::Base,Qt::white);
-  }
-  ui.myCallEntry->setPalette(pal);
-  ui.myGridEntry->setPalette(pal);
-  ui.myCallEntry->setText(m_myCall);
-  ui.myGridEntry->setText(m_myGrid);
-  ui.pskReporterAntenna->setText(m_pskAntenna);
-
-  ui.idIntSpinBox->setValue(m_idInt);
-  ui.pttMethodComboBox->setCurrentIndex(m_pttMethodIndex);
-  ui.saveDirEntry->setText(m_saveDir);
-  ui.comboBoxSndIn->setCurrentIndex(m_nDevIn);
-  ui.comboBoxSndOut->setCurrentIndex(m_nDevOut);
-  ui.cbID73->setChecked(m_After73);
-  ui.cbPSKReporter->setChecked(m_pskReporter);
-  ui.cbSplit->setChecked(m_bSplit and m_catEnabled);
-  ui.cbXIT->setChecked(m_bXIT);
-  ui.cbXIT->setVisible(false);
-
-  enableWidgets();
-
-  ui.rigComboBox->setCurrentIndex(m_rigIndex);
-  ui.catPortComboBox->setCurrentIndex(m_catPortIndex);
-  ui.serialRateComboBox->setCurrentIndex(m_serialRateIndex);
-  ui.dataBitsComboBox->setCurrentIndex(m_dataBitsIndex);
-  ui.stopBitsComboBox->setCurrentIndex(m_stopBitsIndex);
-  ui.handshakeComboBox->setCurrentIndex(m_handshakeIndex);
-  ui.rbData->setChecked(m_pttData);
-  ui.pollSpinBox->setValue(m_poll);
-
-  // PY2SDR -- Per OS serial port names
-  m_tmp=m_pttPort;
-  ui.pttComboBox->clear();
-  ui.catPortComboBox->clear();
-  ui.pttComboBox->addItem("None");
-  ui.catPortComboBox->addItem("None");
-#ifdef WIN32
-  for ( int i = 1; i < 100; i++ ) {
-    ui.pttComboBox->addItem("COM" + QString::number(i));
-    ui.catPortComboBox->addItem("COM" + QString::number(i));
-  }
-  ui.pttComboBox->addItem("USB");
-  ui.catPortComboBox->addItem("USB");
-#else
-  ui.catPortComboBox->addItem("/dev/ttyS0");
-  ui.catPortComboBox->addItem("/dev/ttyS1");
-  ui.catPortComboBox->addItem("/dev/ttyS2");
-  ui.catPortComboBox->addItem("/dev/ttyS3");
-  ui.catPortComboBox->addItem("/dev/ttyS4");
-  ui.catPortComboBox->addItem("/dev/ttyS5");
-  ui.catPortComboBox->addItem("/dev/ttyS6");
-  ui.catPortComboBox->addItem("/dev/ttyS7");
-  ui.catPortComboBox->addItem("/dev/ttyUSB0");
-  ui.catPortComboBox->addItem("/dev/ttyUSB1");
-  ui.catPortComboBox->addItem("/dev/ttyUSB2");
-  ui.catPortComboBox->addItem("/dev/ttyUSB3");
-  ui.catPortComboBox->addItem(catPortDriver);
-
-  ui.pttComboBox->addItem("/dev/ttyS0");
-  ui.pttComboBox->addItem("/dev/ttyS1");
-  ui.pttComboBox->addItem("/dev/ttyS2");
-  ui.pttComboBox->addItem("/dev/ttyS3");
-  ui.pttComboBox->addItem("/dev/ttyS4");
-  ui.pttComboBox->addItem("/dev/ttyS5");
-  ui.pttComboBox->addItem("/dev/ttyS6");
-  ui.pttComboBox->addItem("/dev/ttyS7");
-  ui.pttComboBox->addItem("/dev/ttyUSB0");
-  ui.pttComboBox->addItem("/dev/ttyUSB1");
-  ui.pttComboBox->addItem("/dev/ttyUSB2");
-  ui.pttComboBox->addItem("/dev/ttyUSB3");
-#endif
-  ui.pttComboBox->setCurrentIndex(m_tmp);
-  ui.catPortComboBox->setCurrentIndex(m_catPortIndex);
-
-  int n=m_macro.length();
-  if(n>=1) ui.macro1->setText(m_macro[0].toUpper());
-  if(n>=2) ui.macro2->setText(m_macro[1].toUpper());
-  if(n>=3) ui.macro3->setText(m_macro[2].toUpper());
-  if(n>=4) ui.macro4->setText(m_macro[3].toUpper());
-  if(n>=5) ui.macro5->setText(m_macro[4].toUpper());
-  if(n>=6) ui.macro6->setText(m_macro[5].toUpper());
-  if(n>=7) ui.macro7->setText(m_macro[6].toUpper());
-  if(n>=8) ui.macro8->setText(m_macro[7].toUpper());
-  if(n>=8) ui.macro9->setText(m_macro[8].toUpper());
-  if(n>=10) ui.macro10->setText(m_macro[9].toUpper());
-
-  ui.f1->setText(m_dFreq[0]);
-  ui.f2->setText(m_dFreq[1]);
-  ui.f3->setText(m_dFreq[2]);
-  ui.f4->setText(m_dFreq[3]);
-  ui.f5->setText(m_dFreq[4]);
-  ui.f6->setText(m_dFreq[5]);
-  ui.f7->setText(m_dFreq[6]);
-  ui.f8->setText(m_dFreq[7]);
-  ui.f9->setText(m_dFreq[8]);
-  ui.f10->setText(m_dFreq[9]);
-  ui.f11->setText(m_dFreq[10]);
-  ui.f12->setText(m_dFreq[11]);
-  ui.f13->setText(m_dFreq[12]);
-  ui.f14->setText(m_dFreq[13]);
-  ui.f15->setText(m_dFreq[14]);
-  ui.f16->setText(m_dFreq[15]);
-}
-
-//------------------------------------------------------- accept()
-void DevSetup::accept()
-{
-  // Called when OK button is clicked.
-  // Check to see whether SoundInThread must be restarted,
-  // and save user parameters.
-
-  if(m_nDevIn!=ui.comboBoxSndIn->currentIndex() or
-     m_paInDevice!=m_inDevList[m_nDevIn]) m_restartSoundIn=true;
-
-  if(m_nDevOut!=ui.comboBoxSndOut->currentIndex() or
-     m_paOutDevice!=m_outDevList[m_nDevOut]) m_restartSoundOut=true;
-
-  m_myCall=ui.myCallEntry->text();
-  m_myGrid=ui.myGridEntry->text();
-  m_pskAntenna=ui.pskReporterAntenna->text();
-  m_idInt=ui.idIntSpinBox->value();
-  m_pttMethodIndex=ui.pttMethodComboBox->currentIndex();
-  m_pttPort=ui.pttComboBox->currentIndex();
-  m_saveDir=ui.saveDirEntry->text();
-  m_nDevIn=ui.comboBoxSndIn->currentIndex();
-  m_paInDevice=m_inDevList[m_nDevIn];
-  m_nDevOut=ui.comboBoxSndOut->currentIndex();
-  m_paOutDevice=m_outDevList[m_nDevOut];
-
-  m_macro.clear();
-  m_macro.append(ui.macro1->text());
-  m_macro.append(ui.macro2->text());
-  m_macro.append(ui.macro3->text());
-  m_macro.append(ui.macro4->text());
-  m_macro.append(ui.macro5->text());
-  m_macro.append(ui.macro6->text());
-  m_macro.append(ui.macro7->text());
-  m_macro.append(ui.macro8->text());
-  m_macro.append(ui.macro9->text());
-  m_macro.append(ui.macro10->text());
-
-  m_dFreq.clear();
-  m_dFreq.append(ui.f1->text());
-  m_dFreq.append(ui.f2->text());
-  m_dFreq.append(ui.f3->text());
-  m_dFreq.append(ui.f4->text());
-  m_dFreq.append(ui.f5->text());
-  m_dFreq.append(ui.f6->text());
-  m_dFreq.append(ui.f7->text());
-  m_dFreq.append(ui.f8->text());
-  m_dFreq.append(ui.f9->text());
-  m_dFreq.append(ui.f10->text());
-  m_dFreq.append(ui.f11->text());
-  m_dFreq.append(ui.f12->text());
-  m_dFreq.append(ui.f13->text());
-  m_dFreq.append(ui.f14->text());
-  m_dFreq.append(ui.f15->text());
-  m_dFreq.append(ui.f16->text());
-
-  if(m_bRigOpen) {
-    rig->close();
-    if(m_rig<9900) delete rig;
-    m_bRigOpen=false;
-  }
-
-  QDialog::accept();
-}
-
-//------------------------------------------------------- reject()
-void DevSetup::reject()
-{
-  if(m_bRigOpen) rig->close();
-  QDialog::reject();
-}
-
-void DevSetup::p4ReadFromStdout()                        //p4readFromStdout
-{
-  while(p4.canReadLine()) {
-    QString t(p4.readLine());
-    QString t1,t2,t3;
-    if(t.mid(0,6)!=" Rig #") {
-      t1=t.mid(0,6);
-      t2=t.mid(8,22).trimmed();
-      t3=t.mid(31,23).trimmed();
-      t=t1 + "  " + t2 + "  " + t3;
-      ui.rigComboBox->addItem(t);
-    }
-  }
-}
-
-void DevSetup::p4ReadFromStderr()                        //p4readFromStderr
-{
-  QByteArray t=p4.readAllStandardError();
-  if(t.length()>0) {
-    msgBox(t);
-  }
-}
-
-void DevSetup::p4Error()                                     //p4rror
-{
-  msgBox("Error running 'rigctl -l'.");
-}
-
-void DevSetup::msgBox(QString t)                             //msgBox
-{
-  msgBox0.setText(t);
-  msgBox0.exec();
-}
-
-void DevSetup::on_myCallEntry_editingFinished()
-{
-  QString t=ui.myCallEntry->text();
-  ui.myCallEntry->setText(t.toUpper());
-}
-
-void DevSetup::on_myGridEntry_editingFinished()
-{
-  QString t=ui.myGridEntry->text();
-  t=t.mid(0,4).toUpper()+t.mid(4,2).toLower();
-  ui.myGridEntry->setText(t);
-}
-
-void DevSetup::on_cbPSKReporter_clicked(bool b)
-{
-  m_pskReporter=b;
-  ui.label_8->setEnabled(m_pskReporter);
-  ui.pskReporterAntenna->setEnabled(m_pskReporter);
-}
-
-void DevSetup::on_pttMethodComboBox_activated(int index)
-{
-  m_pttMethodIndex=index;
-  enableWidgets();
-}
-
-void DevSetup::on_catPortComboBox_activated(int index)
-{
-  m_catPortIndex=index;
-  m_catPort=ui.catPortComboBox->itemText(index);
-}
-
-void DevSetup::on_cbEnableCAT_toggled(bool b)
-{
-  m_catEnabled=b;
-  enableWidgets();
-  ui.cbSplit->setChecked(m_bSplit and m_catEnabled);
-}
-
-void DevSetup::on_serialRateComboBox_activated(int index)
-{
-  m_serialRateIndex=index;
-  m_serialRate=ui.serialRateComboBox->itemText(index).toInt();
-}
-
-void DevSetup::on_handshakeComboBox_activated(int index)
-{
-  m_handshakeIndex=index;
-  m_handshake=ui.handshakeComboBox->itemText(index);
-}
-
-void DevSetup::on_dataBitsComboBox_activated(int index)
-{
-  m_dataBitsIndex=index;
-  m_dataBits=ui.dataBitsComboBox->itemText(index).toInt();
-}
-
-void DevSetup::on_stopBitsComboBox_activated(int index)
-{
-  m_stopBitsIndex=index;
-  m_stopBits=ui.stopBitsComboBox->itemText(index).toInt();
-}
-
-void DevSetup::on_rigComboBox_activated(int index)
-{
-  m_rigIndex=index;
-  QString t=ui.rigComboBox->itemText(index);
-  m_rig=t.mid(0,7).toInt();
-  enableWidgets();
-}
-
-void DevSetup::on_cbID73_toggled(bool checked)
-{
-  m_After73=checked;
-}
-
-void DevSetup::on_testCATButton_clicked()
-{
-  openRig();
-  if(!m_catEnabled) return;
-  QString t;
-  double fMHz=rig->getFreq(RIG_VFO_CURR)/1000000.0;
-  if(fMHz>0.0) {
-    t.sprintf("Rig control appears to be working.\nDial Frequency:  %.6f MHz",
-              fMHz);
-  } else {
-    t.sprintf("Rig control error %d\nFailed to read frequency.",
-              int(1000000.0*fMHz));
-    if(m_poll>0) {
-      m_catEnabled=false;
-      ui.cbEnableCAT->setChecked(false);
-    }
-  }
-  msgBox(t);
-}
-
-void DevSetup::openRig()
-{
-  QString t;
-  int ret;
-
-  if(!m_catEnabled) return;
-  if(m_bRigOpen) {
-    rig->close();
-    if(m_rig<9900) delete rig;
-    m_bRigOpen=false;
-  }
-
-  rig = new Rig();
-
-  if(m_rig<9900) {
-    if (!rig->init(m_rig)) {
-      msgBox("Rig init failure");
-      m_catEnabled=false;
-      return;
-    }
-    QString sCATport=m_catPort;
-#ifdef WIN32
-    sCATport="\\\\.\\" + m_catPort;    //Allow COM ports above 9
-#endif
-    rig->setConf("rig_pathname", sCATport.toLatin1().data());
-    char buf[80];
-    sprintf(buf,"%d",m_serialRate);
-    rig->setConf("serial_speed",buf);
-    sprintf(buf,"%d",m_dataBits);
-    rig->setConf("data_bits",buf);
-    sprintf(buf,"%d",m_stopBits);
-    rig->setConf("stop_bits",buf);
-    rig->setConf("serial_handshake",m_handshake.toLatin1().data());
-    if(m_bDTRoff) {
-      rig->setConf("rts_state","OFF");
-      rig->setConf("dtr_state","OFF");
-    }
-  }
-
-  ret=rig->open(m_rig);
-  if(ret==RIG_OK) {
-    m_bRigOpen=true;
-  } else {
-    t="Open rig failed";
-    msgBox(t);
-    m_catEnabled=false;
-    ui.cbEnableCAT->setChecked(false);
-    return;
-  }
-}
-
-void DevSetup::on_testPTTButton_clicked()
-{
-  m_test=1-m_test;
-  if(m_pttMethodIndex==1 or m_pttMethodIndex==2) {
-    ptt(m_pttPort,m_test,&g2_iptt,&g2_COMportOpen);
-  }
-  if(m_pttMethodIndex==0 and !m_bRigOpen) {
-//    on_testCATButton_clicked();
-    openRig();
-  }
-  if(m_pttMethodIndex==0 and m_bRigOpen) {
-    if(m_test==0) rig->setPTT(RIG_PTT_OFF, RIG_VFO_CURR);
-    if(m_test==1) {
-      if(m_pttData) rig->setPTT(RIG_PTT_ON_DATA, RIG_VFO_CURR);
-      if(!m_pttData) rig->setPTT(RIG_PTT_ON_MIC, RIG_VFO_CURR);
-    }
-  }
-}
-
-void DevSetup::on_cbDTRoff_toggled(bool checked)
-{
-  m_bDTRoff=checked;
-}
-
-void DevSetup::on_rbData_toggled(bool checked)
-{
-  m_pttData=checked;
-}
-
-void DevSetup::on_pollSpinBox_valueChanged(int n)
-{
-  m_poll=n;
-}
-
-void DevSetup::on_pttComboBox_currentIndexChanged(int index)
-{
-  m_pttPort=index;
-  enableWidgets();
-}
-
-void DevSetup::on_pttMethodComboBox_currentIndexChanged(int index)
-{
-  m_pttMethodIndex=index;
-  bool b=m_pttMethodIndex==1 or m_pttMethodIndex==2;
-  ui.pttComboBox->setEnabled(b);
-}
-
-void DevSetup::enableWidgets()
-{
-  ui.label_8->setEnabled(m_pskReporter);
-  ui.pskReporterAntenna->setEnabled(m_pskReporter);
-
-  ui.cbEnableCAT->setChecked(m_catEnabled);
-  ui.cbDTRoff->setChecked(m_bDTRoff);
-  ui.rigComboBox->setEnabled(m_catEnabled);
-  ui.testCATButton->setEnabled(m_catEnabled);
-  ui.label_4->setEnabled(m_catEnabled);
-  ui.label_47->setEnabled(m_catEnabled);
-  ui.cbSplit->setEnabled(m_catEnabled);
-  if(m_rig==9999) {                    //No Split Tx with HRD
-    ui.cbSplit->setChecked(false);
-    ui.cbSplit->setEnabled(false);
-  }
-  ui.cbXIT->setEnabled(m_catEnabled);
-
-  bool bSerial=m_catEnabled and (m_rig<9900);
-  ui.catPortComboBox->setEnabled(bSerial);
-  ui.serialRateComboBox->setEnabled(bSerial);
-  ui.dataBitsComboBox->setEnabled(bSerial);
-  ui.stopBitsComboBox->setEnabled(bSerial);
-  ui.handshakeComboBox->setEnabled(bSerial);
-  ui.cbDTRoff->setEnabled(bSerial);
-  ui.rbData->setEnabled(bSerial);
-  ui.rbMic->setEnabled(bSerial);
-  ui.label_21->setEnabled(bSerial);
-  ui.label_22->setEnabled(bSerial);
-  ui.label_23->setEnabled(bSerial);
-  ui.label_24->setEnabled(bSerial);
-  ui.label_25->setEnabled(bSerial);
-
-  ui.pollSpinBox->setEnabled(m_catEnabled);
-  bool b1=(m_pttMethodIndex==1 or m_pttMethodIndex==2);
-  ui.pttComboBox->setEnabled(b1);
-  b1=b1 and (m_pttPort!=0);
-  bool b2 = (m_catEnabled and m_pttMethodIndex==1 and m_rig<9900) or
-            (m_catEnabled and m_pttMethodIndex==2 and m_rig<9900);
-  bool b3 = (m_catEnabled and m_pttMethodIndex==0);
-  ui.testPTTButton->setEnabled(b1 or b2 or b3);  //Include PTT via HRD or Commander
-}
-
-void DevSetup::on_cbSplit_toggled(bool checked)
-{
-  m_bSplit=checked;
-  if(m_bSplit and m_bXIT) ui.cbXIT->setChecked(false);
-}
-
-void DevSetup::on_cbXIT_toggled(bool checked)
-{
-  m_bXIT=checked;
-  if(m_bSplit and m_bXIT) ui.cbSplit->setChecked(false);
-}
diff --git a/devsetup.h b/devsetup.h
deleted file mode 100644
index f483470..0000000
--- a/devsetup.h
+++ /dev/null
@@ -1,120 +0,0 @@
-#ifndef DEVSETUP_H
-#define DEVSETUP_H
-
-#include <QDialog>
-#include <QProcess>
-#include <QMessageBox>
-#include "ui_devsetup.h"
-#include "rigclass.h"
-
-class DevSetup : public QDialog
-{
-  Q_OBJECT
-public:
-  DevSetup(QWidget *parent=0);
-  ~DevSetup();
-
-  void initDlg();
-
-  qint32  m_idInt;
-  qint32  m_pttMethodIndex;
-  qint32  m_pttPort;
-  qint32  m_nDevIn;
-  qint32  m_nDevOut;
-  qint32  m_inDevList[100];
-  qint32  m_outDevList[100];
-  qint32  m_paInDevice;
-  qint32  m_paOutDevice;
-  qint32  m_catPortIndex;
-  qint32  m_rig;
-  qint32  m_rigIndex;
-  qint32  m_serialRate;
-  qint32  m_serialRateIndex;
-  qint32  m_dataBits;
-  qint32  m_dataBitsIndex;
-  qint32  m_stopBits;
-  qint32  m_stopBitsIndex;
-  qint32  m_handshakeIndex;
-  qint32  m_test;
-  qint32  m_poll;
-  qint32  m_tmp;
-
-  bool    m_restartSoundIn;
-  bool    m_restartSoundOut;
-  bool    m_pskReporter;
-  bool    m_firstCall;
-  bool    m_catEnabled;
-  bool    m_After73;
-  bool    m_bRigOpen;
-  bool    m_bDTRoff;
-  bool    m_pttData;
-  bool    m_bSplit;
-  bool    m_bXIT;
-
-  QString m_myCall;
-  QString m_myGrid;
-  QString m_saveDir;
-  QString m_azelDir;
-  QString m_catPort;
-  QString m_handshake;
-  QString m_pskAntenna;
-
-  QStringList m_macro;
-  QStringList m_dFreq;
-
-  QProcess p4;
-  QMessageBox msgBox0;
-
-public slots:
-  void accept();
-  void reject();
-  void p4ReadFromStdout();
-  void p4ReadFromStderr();
-  void p4Error();
-
-private slots:
-  void on_myCallEntry_editingFinished();
-  void on_myGridEntry_editingFinished();
-  void on_cbPSKReporter_clicked(bool checked);
-  void on_pttMethodComboBox_activated(int index);
-  void on_catPortComboBox_activated(int index);
-  void on_cbEnableCAT_toggled(bool checked);
-  void on_serialRateComboBox_activated(int index);
-  void on_handshakeComboBox_activated(int index);
-  void on_dataBitsComboBox_activated(int index);
-  void on_stopBitsComboBox_activated(int index);
-  void on_rigComboBox_activated(int index);
-  void on_cbID73_toggled(bool checked);
-  void on_testCATButton_clicked();
-  void on_testPTTButton_clicked();
-  void on_cbDTRoff_toggled(bool checked);
-  void on_rbData_toggled(bool checked);
-  void on_pollSpinBox_valueChanged(int n);
-  void on_pttComboBox_currentIndexChanged(int index);
-  void on_pttMethodComboBox_currentIndexChanged(int index);
-
-  void on_cbSplit_toggled(bool checked);
-
-  void on_cbXIT_toggled(bool checked);
-
-private:
-  Rig* rig;
-  void msgBox(QString t);
-  void enableWidgets();
-  void openRig();
-  Ui::DialogSndCard ui;
-};
-
-extern int ptt(int nport, int ntx, int* iptt, int* nopen);
-
-#ifdef WIN32
-extern "C" {
-  bool HRDInterfaceConnect(const wchar_t *host, const ushort);
-  void HRDInterfaceDisconnect();
-  bool HRDInterfaceIsConnected();
-  wchar_t* HRDInterfaceSendMessage(const wchar_t *msg);
-  void HRDInterfaceFreeString(const wchar_t *lstring);
-}
-#endif
-
-#endif // DEVSETUP_H
diff --git a/devsetup.ui b/devsetup.ui
deleted file mode 100644
index b1a31cd..0000000
--- a/devsetup.ui
+++ /dev/null
@@ -1,2599 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>DialogSndCard</class>
- <widget class="QDialog" name="DialogSndCard">
-  <property name="geometry">
-   <rect>
-    <x>0</x>
-    <y>0</y>
-    <width>569</width>
-    <height>493</height>
-   </rect>
-  </property>
-  <property name="maximumSize">
-   <size>
-    <width>569</width>
-    <height>493</height>
-   </size>
-  </property>
-  <property name="windowTitle">
-   <string>Configuration</string>
-  </property>
-  <layout class="QVBoxLayout" name="verticalLayout_2">
-   <item>
-    <widget class="QTabWidget" name="ioTabWidget">
-     <property name="sizePolicy">
-      <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-       <horstretch>0</horstretch>
-       <verstretch>0</verstretch>
-      </sizepolicy>
-     </property>
-     <property name="currentIndex">
-      <number>0</number>
-     </property>
-     <widget class="QWidget" name="tab">
-      <attribute name="title">
-       <string>Station</string>
-      </attribute>
-      <layout class="QVBoxLayout" name="verticalLayout">
-       <item>
-        <layout class="QHBoxLayout" name="horizontalLayout_5">
-         <item>
-          <widget class="QLabel" name="label">
-           <property name="sizePolicy">
-            <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
-             <horstretch>0</horstretch>
-             <verstretch>0</verstretch>
-            </sizepolicy>
-           </property>
-           <property name="minimumSize">
-            <size>
-             <width>80</width>
-             <height>20</height>
-            </size>
-           </property>
-           <property name="maximumSize">
-            <size>
-             <width>80</width>
-             <height>16777215</height>
-            </size>
-           </property>
-           <property name="text">
-            <string>My Call:</string>
-           </property>
-          </widget>
-         </item>
-         <item>
-          <widget class="QLineEdit" name="myCallEntry">
-           <property name="sizePolicy">
-            <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-             <horstretch>0</horstretch>
-             <verstretch>0</verstretch>
-            </sizepolicy>
-           </property>
-           <property name="minimumSize">
-            <size>
-             <width>90</width>
-             <height>0</height>
-            </size>
-           </property>
-           <property name="maximumSize">
-            <size>
-             <width>90</width>
-             <height>16777215</height>
-            </size>
-           </property>
-           <property name="toolTip">
-            <string>Station callsign</string>
-           </property>
-           <property name="text">
-            <string/>
-           </property>
-          </widget>
-         </item>
-         <item>
-          <layout class="QHBoxLayout" name="horizontalLayout_8"/>
-         </item>
-         <item>
-          <spacer name="verticalSpacer_2">
-           <property name="orientation">
-            <enum>Qt::Horizontal</enum>
-           </property>
-           <property name="sizeHint" stdset="0">
-            <size>
-             <width>40</width>
-             <height>20</height>
-            </size>
-           </property>
-          </spacer>
-         </item>
-         <item>
-          <widget class="QLabel" name="label_2">
-           <property name="sizePolicy">
-            <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
-             <horstretch>0</horstretch>
-             <verstretch>0</verstretch>
-            </sizepolicy>
-           </property>
-           <property name="minimumSize">
-            <size>
-             <width>80</width>
-             <height>20</height>
-            </size>
-           </property>
-           <property name="maximumSize">
-            <size>
-             <width>80</width>
-             <height>16777215</height>
-            </size>
-           </property>
-           <property name="text">
-            <string>My Grid:</string>
-           </property>
-           <property name="alignment">
-            <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
-           </property>
-          </widget>
-         </item>
-         <item>
-          <widget class="QLineEdit" name="myGridEntry">
-           <property name="sizePolicy">
-            <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-             <horstretch>0</horstretch>
-             <verstretch>0</verstretch>
-            </sizepolicy>
-           </property>
-           <property name="minimumSize">
-            <size>
-             <width>100</width>
-             <height>0</height>
-            </size>
-           </property>
-           <property name="maximumSize">
-            <size>
-             <width>60</width>
-             <height>16777215</height>
-            </size>
-           </property>
-           <property name="toolTip">
-            <string>Maidenhead locator</string>
-           </property>
-           <property name="text">
-            <string/>
-           </property>
-          </widget>
-         </item>
-        </layout>
-       </item>
-       <item>
-        <layout class="QHBoxLayout" name="horizontalLayout_2">
-         <item>
-          <widget class="QLabel" name="label_5">
-           <property name="sizePolicy">
-            <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
-             <horstretch>0</horstretch>
-             <verstretch>0</verstretch>
-            </sizepolicy>
-           </property>
-           <property name="minimumSize">
-            <size>
-             <width>80</width>
-             <height>0</height>
-            </size>
-           </property>
-           <property name="maximumSize">
-            <size>
-             <width>80</width>
-             <height>16777215</height>
-            </size>
-           </property>
-           <property name="text">
-            <string>PTT method:</string>
-           </property>
-          </widget>
-         </item>
-         <item>
-          <widget class="QComboBox" name="pttMethodComboBox">
-           <property name="sizePolicy">
-            <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-             <horstretch>0</horstretch>
-             <verstretch>0</verstretch>
-            </sizepolicy>
-           </property>
-           <property name="minimumSize">
-            <size>
-             <width>90</width>
-             <height>0</height>
-            </size>
-           </property>
-           <property name="maximumSize">
-            <size>
-             <width>90</width>
-             <height>16777215</height>
-            </size>
-           </property>
-           <property name="toolTip">
-            <string>Select method for T/R switching</string>
-           </property>
-           <property name="currentIndex">
-            <number>1</number>
-           </property>
-           <item>
-            <property name="text">
-             <string>CAT</string>
-            </property>
-           </item>
-           <item>
-            <property name="text">
-             <string>DTR</string>
-            </property>
-           </item>
-           <item>
-            <property name="text">
-             <string>RTS</string>
-            </property>
-           </item>
-           <item>
-            <property name="text">
-             <string>VOX</string>
-            </property>
-           </item>
-          </widget>
-         </item>
-         <item>
-          <spacer name="horizontalSpacer_2">
-           <property name="orientation">
-            <enum>Qt::Horizontal</enum>
-           </property>
-           <property name="sizeHint" stdset="0">
-            <size>
-             <width>40</width>
-             <height>20</height>
-            </size>
-           </property>
-          </spacer>
-         </item>
-         <item>
-          <widget class="QLabel" name="label_9">
-           <property name="sizePolicy">
-            <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
-             <horstretch>0</horstretch>
-             <verstretch>0</verstretch>
-            </sizepolicy>
-           </property>
-           <property name="minimumSize">
-            <size>
-             <width>80</width>
-             <height>0</height>
-            </size>
-           </property>
-           <property name="maximumSize">
-            <size>
-             <width>80</width>
-             <height>16777215</height>
-            </size>
-           </property>
-           <property name="text">
-            <string>PTT Port:</string>
-           </property>
-           <property name="alignment">
-            <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
-           </property>
-          </widget>
-         </item>
-         <item>
-          <widget class="QComboBox" name="pttComboBox">
-           <property name="sizePolicy">
-            <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-             <horstretch>0</horstretch>
-             <verstretch>0</verstretch>
-            </sizepolicy>
-           </property>
-           <property name="minimumSize">
-            <size>
-             <width>100</width>
-             <height>0</height>
-            </size>
-           </property>
-           <property name="maximumSize">
-            <size>
-             <width>100</width>
-             <height>16777215</height>
-            </size>
-           </property>
-           <property name="toolTip">
-            <string>Select port for hardware T/R switching</string>
-           </property>
-           <item>
-            <property name="text">
-             <string>None</string>
-            </property>
-           </item>
-          </widget>
-         </item>
-        </layout>
-       </item>
-       <item>
-        <layout class="QHBoxLayout" name="horizontalLayout_6">
-         <item>
-          <widget class="QCheckBox" name="cbPSKReporter">
-           <property name="sizePolicy">
-            <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-             <horstretch>0</horstretch>
-             <verstretch>0</verstretch>
-            </sizepolicy>
-           </property>
-           <property name="minimumSize">
-            <size>
-             <width>146</width>
-             <height>0</height>
-            </size>
-           </property>
-           <property name="maximumSize">
-            <size>
-             <width>146</width>
-             <height>16777215</height>
-            </size>
-           </property>
-           <property name="toolTip">
-            <string>Send spots to PSK Reporter web site</string>
-           </property>
-           <property name="text">
-            <string>Enable PSK Reporter</string>
-           </property>
-          </widget>
-         </item>
-         <item>
-          <spacer name="horizontalSpacer_7">
-           <property name="orientation">
-            <enum>Qt::Horizontal</enum>
-           </property>
-           <property name="sizeHint" stdset="0">
-            <size>
-             <width>40</width>
-             <height>20</height>
-            </size>
-           </property>
-          </spacer>
-         </item>
-         <item>
-          <widget class="QCheckBox" name="cbID73">
-           <property name="toolTip">
-            <string>Send CW ID after a message with 73 or free text</string>
-           </property>
-           <property name="text">
-            <string>CW ID after 73</string>
-           </property>
-          </widget>
-         </item>
-         <item>
-          <spacer name="horizontalSpacer_3">
-           <property name="orientation">
-            <enum>Qt::Horizontal</enum>
-           </property>
-           <property name="sizeHint" stdset="0">
-            <size>
-             <width>40</width>
-             <height>20</height>
-            </size>
-           </property>
-          </spacer>
-         </item>
-         <item>
-          <widget class="QLabel" name="label_3">
-           <property name="minimumSize">
-            <size>
-             <width>0</width>
-             <height>20</height>
-            </size>
-           </property>
-           <property name="text">
-            <string>CW ID Interval (min):</string>
-           </property>
-          </widget>
-         </item>
-         <item>
-          <widget class="QSpinBox" name="idIntSpinBox">
-           <property name="enabled">
-            <bool>true</bool>
-           </property>
-           <property name="maximumSize">
-            <size>
-             <width>60</width>
-             <height>16777215</height>
-            </size>
-           </property>
-           <property name="toolTip">
-            <string>Select CW ID interval (0 for none)</string>
-           </property>
-           <property name="minimum">
-            <number>0</number>
-           </property>
-           <property name="maximum">
-            <number>10</number>
-           </property>
-          </widget>
-         </item>
-        </layout>
-       </item>
-       <item>
-        <layout class="QHBoxLayout" name="horizontalLayout_12">
-         <item>
-          <widget class="QLabel" name="label_8">
-           <property name="text">
-            <string>Antenna for PSK Reporter:</string>
-           </property>
-          </widget>
-         </item>
-         <item>
-          <widget class="QLineEdit" name="pskReporterAntenna"/>
-         </item>
-        </layout>
-       </item>
-       <item>
-        <spacer name="verticalSpacer">
-         <property name="orientation">
-          <enum>Qt::Vertical</enum>
-         </property>
-         <property name="sizeHint" stdset="0">
-          <size>
-           <width>20</width>
-           <height>13</height>
-          </size>
-         </property>
-        </spacer>
-       </item>
-       <item>
-        <layout class="QHBoxLayout" name="horizontalLayout_7">
-         <item>
-          <widget class="QCheckBox" name="cbEnableCAT">
-           <property name="sizePolicy">
-            <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-             <horstretch>0</horstretch>
-             <verstretch>0</verstretch>
-            </sizepolicy>
-           </property>
-           <property name="minimumSize">
-            <size>
-             <width>110</width>
-             <height>0</height>
-            </size>
-           </property>
-           <property name="maximumSize">
-            <size>
-             <width>100</width>
-             <height>16777215</height>
-            </size>
-           </property>
-           <property name="toolTip">
-            <string>Enable computer control of transceiver</string>
-           </property>
-           <property name="text">
-            <string>Enable CAT</string>
-           </property>
-          </widget>
-         </item>
-         <item>
-          <widget class="QLabel" name="label_4">
-           <property name="sizePolicy">
-            <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
-             <horstretch>0</horstretch>
-             <verstretch>0</verstretch>
-            </sizepolicy>
-           </property>
-           <property name="minimumSize">
-            <size>
-             <width>20</width>
-             <height>0</height>
-            </size>
-           </property>
-           <property name="maximumSize">
-            <size>
-             <width>20</width>
-             <height>16777215</height>
-            </size>
-           </property>
-           <property name="text">
-            <string>Rig:</string>
-           </property>
-          </widget>
-         </item>
-         <item>
-          <widget class="QComboBox" name="rigComboBox">
-           <property name="sizePolicy">
-            <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
-             <horstretch>0</horstretch>
-             <verstretch>0</verstretch>
-            </sizepolicy>
-           </property>
-           <property name="minimumSize">
-            <size>
-             <width>200</width>
-             <height>0</height>
-            </size>
-           </property>
-           <property name="toolTip">
-            <string>Select radio type</string>
-           </property>
-          </widget>
-         </item>
-        </layout>
-       </item>
-       <item>
-        <layout class="QHBoxLayout" name="horizontalLayout_1">
-         <item>
-          <widget class="QLabel" name="label_21">
-           <property name="sizePolicy">
-            <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
-             <horstretch>0</horstretch>
-             <verstretch>0</verstretch>
-            </sizepolicy>
-           </property>
-           <property name="minimumSize">
-            <size>
-             <width>110</width>
-             <height>0</height>
-            </size>
-           </property>
-           <property name="maximumSize">
-            <size>
-             <width>100</width>
-             <height>16777215</height>
-            </size>
-           </property>
-           <property name="text">
-            <string>CAT port:</string>
-           </property>
-          </widget>
-         </item>
-         <item>
-          <widget class="QComboBox" name="catPortComboBox">
-           <property name="sizePolicy">
-            <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-             <horstretch>0</horstretch>
-             <verstretch>0</verstretch>
-            </sizepolicy>
-           </property>
-           <property name="minimumSize">
-            <size>
-             <width>100</width>
-             <height>0</height>
-            </size>
-           </property>
-           <property name="maximumSize">
-            <size>
-             <width>90</width>
-             <height>16777215</height>
-            </size>
-           </property>
-           <property name="toolTip">
-            <string>Select port for CAT control</string>
-           </property>
-           <property name="currentIndex">
-            <number>0</number>
-           </property>
-           <item>
-            <property name="text">
-             <string>None</string>
-            </property>
-           </item>
-          </widget>
-         </item>
-         <item>
-          <spacer name="horizontalSpacer_4">
-           <property name="orientation">
-            <enum>Qt::Horizontal</enum>
-           </property>
-           <property name="sizeType">
-            <enum>QSizePolicy::Fixed</enum>
-           </property>
-           <property name="sizeHint" stdset="0">
-            <size>
-             <width>40</width>
-             <height>20</height>
-            </size>
-           </property>
-          </spacer>
-         </item>
-         <item>
-          <widget class="QCheckBox" name="cbDTRoff">
-           <property name="text">
-            <string>RTS/DTR OFF</string>
-           </property>
-          </widget>
-         </item>
-         <item>
-          <spacer name="horizontalSpacer_14">
-           <property name="orientation">
-            <enum>Qt::Horizontal</enum>
-           </property>
-           <property name="sizeType">
-            <enum>QSizePolicy::Fixed</enum>
-           </property>
-           <property name="sizeHint" stdset="0">
-            <size>
-             <width>40</width>
-             <height>20</height>
-            </size>
-           </property>
-          </spacer>
-         </item>
-         <item>
-          <widget class="QLabel" name="label_24">
-           <property name="sizePolicy">
-            <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
-             <horstretch>0</horstretch>
-             <verstretch>0</verstretch>
-            </sizepolicy>
-           </property>
-           <property name="minimumSize">
-            <size>
-             <width>60</width>
-             <height>0</height>
-            </size>
-           </property>
-           <property name="maximumSize">
-            <size>
-             <width>60</width>
-             <height>16777215</height>
-            </size>
-           </property>
-           <property name="text">
-            <string>Data bits:</string>
-           </property>
-          </widget>
-         </item>
-         <item>
-          <widget class="QComboBox" name="dataBitsComboBox">
-           <property name="sizePolicy">
-            <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-             <horstretch>0</horstretch>
-             <verstretch>0</verstretch>
-            </sizepolicy>
-           </property>
-           <property name="minimumSize">
-            <size>
-             <width>50</width>
-             <height>0</height>
-            </size>
-           </property>
-           <property name="maximumSize">
-            <size>
-             <width>50</width>
-             <height>16777215</height>
-            </size>
-           </property>
-           <property name="currentIndex">
-            <number>1</number>
-           </property>
-           <item>
-            <property name="text">
-             <string>7</string>
-            </property>
-           </item>
-           <item>
-            <property name="text">
-             <string>8</string>
-            </property>
-           </item>
-          </widget>
-         </item>
-        </layout>
-       </item>
-       <item>
-        <layout class="QHBoxLayout" name="horizontalLayout_9">
-         <item>
-          <widget class="QLabel" name="label_22">
-           <property name="sizePolicy">
-            <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
-             <horstretch>0</horstretch>
-             <verstretch>0</verstretch>
-            </sizepolicy>
-           </property>
-           <property name="minimumSize">
-            <size>
-             <width>110</width>
-             <height>0</height>
-            </size>
-           </property>
-           <property name="maximumSize">
-            <size>
-             <width>100</width>
-             <height>16777215</height>
-            </size>
-           </property>
-           <property name="text">
-            <string>Serial rate:</string>
-           </property>
-          </widget>
-         </item>
-         <item>
-          <widget class="QComboBox" name="serialRateComboBox">
-           <property name="sizePolicy">
-            <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-             <horstretch>0</horstretch>
-             <verstretch>0</verstretch>
-            </sizepolicy>
-           </property>
-           <property name="minimumSize">
-            <size>
-             <width>100</width>
-             <height>0</height>
-            </size>
-           </property>
-           <property name="maximumSize">
-            <size>
-             <width>90</width>
-             <height>16777215</height>
-            </size>
-           </property>
-           <property name="currentIndex">
-            <number>1</number>
-           </property>
-           <item>
-            <property name="text">
-             <string>1200</string>
-            </property>
-           </item>
-           <item>
-            <property name="text">
-             <string>4800</string>
-            </property>
-           </item>
-           <item>
-            <property name="text">
-             <string>9600</string>
-            </property>
-           </item>
-           <item>
-            <property name="text">
-             <string>19200</string>
-            </property>
-           </item>
-           <item>
-            <property name="text">
-             <string>38400</string>
-            </property>
-           </item>
-           <item>
-            <property name="text">
-             <string>57600</string>
-            </property>
-           </item>
-          </widget>
-         </item>
-         <item>
-          <spacer name="horizontalSpacer_13">
-           <property name="orientation">
-            <enum>Qt::Horizontal</enum>
-           </property>
-           <property name="sizeType">
-            <enum>QSizePolicy::Fixed</enum>
-           </property>
-           <property name="sizeHint" stdset="0">
-            <size>
-             <width>40</width>
-             <height>20</height>
-            </size>
-           </property>
-          </spacer>
-         </item>
-         <item>
-          <widget class="QRadioButton" name="rbData">
-           <property name="toolTip">
-            <string>Use special Tx command for "data"</string>
-           </property>
-           <property name="text">
-            <string>Data</string>
-           </property>
-          </widget>
-         </item>
-         <item>
-          <widget class="QRadioButton" name="rbMic">
-           <property name="toolTip">
-            <string>Use normal Tx command</string>
-           </property>
-           <property name="text">
-            <string>Mic</string>
-           </property>
-           <property name="checked">
-            <bool>true</bool>
-           </property>
-          </widget>
-         </item>
-         <item>
-          <spacer name="horizontalSpacer_5">
-           <property name="orientation">
-            <enum>Qt::Horizontal</enum>
-           </property>
-           <property name="sizeHint" stdset="0">
-            <size>
-             <width>40</width>
-             <height>20</height>
-            </size>
-           </property>
-          </spacer>
-         </item>
-         <item>
-          <widget class="QLabel" name="label_25">
-           <property name="sizePolicy">
-            <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
-             <horstretch>0</horstretch>
-             <verstretch>0</verstretch>
-            </sizepolicy>
-           </property>
-           <property name="minimumSize">
-            <size>
-             <width>60</width>
-             <height>0</height>
-            </size>
-           </property>
-           <property name="maximumSize">
-            <size>
-             <width>60</width>
-             <height>16777215</height>
-            </size>
-           </property>
-           <property name="text">
-            <string>Stop bits:</string>
-           </property>
-          </widget>
-         </item>
-         <item>
-          <widget class="QComboBox" name="stopBitsComboBox">
-           <property name="sizePolicy">
-            <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-             <horstretch>0</horstretch>
-             <verstretch>0</verstretch>
-            </sizepolicy>
-           </property>
-           <property name="minimumSize">
-            <size>
-             <width>50</width>
-             <height>0</height>
-            </size>
-           </property>
-           <property name="maximumSize">
-            <size>
-             <width>50</width>
-             <height>16777215</height>
-            </size>
-           </property>
-           <property name="currentIndex">
-            <number>1</number>
-           </property>
-           <item>
-            <property name="text">
-             <string>1</string>
-            </property>
-           </item>
-           <item>
-            <property name="text">
-             <string>2</string>
-            </property>
-           </item>
-          </widget>
-         </item>
-        </layout>
-       </item>
-       <item>
-        <layout class="QHBoxLayout" name="horizontalLayout_10">
-         <item>
-          <widget class="QLabel" name="label_23">
-           <property name="sizePolicy">
-            <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
-             <horstretch>0</horstretch>
-             <verstretch>0</verstretch>
-            </sizepolicy>
-           </property>
-           <property name="minimumSize">
-            <size>
-             <width>110</width>
-             <height>0</height>
-            </size>
-           </property>
-           <property name="maximumSize">
-            <size>
-             <width>100</width>
-             <height>16777215</height>
-            </size>
-           </property>
-           <property name="text">
-            <string>Handshake:</string>
-           </property>
-          </widget>
-         </item>
-         <item>
-          <widget class="QComboBox" name="handshakeComboBox">
-           <property name="sizePolicy">
-            <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-             <horstretch>0</horstretch>
-             <verstretch>0</verstretch>
-            </sizepolicy>
-           </property>
-           <property name="minimumSize">
-            <size>
-             <width>100</width>
-             <height>0</height>
-            </size>
-           </property>
-           <property name="maximumSize">
-            <size>
-             <width>90</width>
-             <height>16777215</height>
-            </size>
-           </property>
-           <property name="currentIndex">
-            <number>2</number>
-           </property>
-           <item>
-            <property name="text">
-             <string>None</string>
-            </property>
-           </item>
-           <item>
-            <property name="text">
-             <string>XonXoff</string>
-            </property>
-           </item>
-           <item>
-            <property name="text">
-             <string>Hardware</string>
-            </property>
-           </item>
-          </widget>
-         </item>
-         <item>
-          <spacer name="horizontalSpacer_16">
-           <property name="orientation">
-            <enum>Qt::Horizontal</enum>
-           </property>
-           <property name="sizeType">
-            <enum>QSizePolicy::Fixed</enum>
-           </property>
-           <property name="sizeHint" stdset="0">
-            <size>
-             <width>40</width>
-             <height>20</height>
-            </size>
-           </property>
-          </spacer>
-         </item>
-         <item>
-          <widget class="QCheckBox" name="cbSplit">
-           <property name="text">
-            <string>Split Tx</string>
-           </property>
-          </widget>
-         </item>
-         <item>
-          <spacer name="horizontalSpacer_6">
-           <property name="orientation">
-            <enum>Qt::Horizontal</enum>
-           </property>
-           <property name="sizeHint" stdset="0">
-            <size>
-             <width>40</width>
-             <height>20</height>
-            </size>
-           </property>
-          </spacer>
-         </item>
-        </layout>
-       </item>
-       <item>
-        <layout class="QHBoxLayout" name="horizontalLayout_11">
-         <item>
-          <widget class="QPushButton" name="testCATButton">
-           <property name="sizePolicy">
-            <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-             <horstretch>0</horstretch>
-             <verstretch>0</verstretch>
-            </sizepolicy>
-           </property>
-           <property name="minimumSize">
-            <size>
-             <width>110</width>
-             <height>0</height>
-            </size>
-           </property>
-           <property name="maximumSize">
-            <size>
-             <width>100</width>
-             <height>16777215</height>
-            </size>
-           </property>
-           <property name="toolTip">
-            <string>Check to see if CAT control is working</string>
-           </property>
-           <property name="text">
-            <string>Test CAT Control</string>
-           </property>
-          </widget>
-         </item>
-         <item>
-          <widget class="QPushButton" name="testPTTButton">
-           <property name="sizePolicy">
-            <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-             <horstretch>0</horstretch>
-             <verstretch>0</verstretch>
-            </sizepolicy>
-           </property>
-           <property name="minimumSize">
-            <size>
-             <width>100</width>
-             <height>0</height>
-            </size>
-           </property>
-           <property name="maximumSize">
-            <size>
-             <width>90</width>
-             <height>16777215</height>
-            </size>
-           </property>
-           <property name="toolTip">
-            <string>Test to see if T/R switching is working</string>
-           </property>
-           <property name="text">
-            <string>Test PTT</string>
-           </property>
-          </widget>
-         </item>
-         <item>
-          <spacer name="horizontalSpacer_17">
-           <property name="orientation">
-            <enum>Qt::Horizontal</enum>
-           </property>
-           <property name="sizeType">
-            <enum>QSizePolicy::Fixed</enum>
-           </property>
-           <property name="sizeHint" stdset="0">
-            <size>
-             <width>40</width>
-             <height>20</height>
-            </size>
-           </property>
-          </spacer>
-         </item>
-         <item>
-          <widget class="QCheckBox" name="cbXIT">
-           <property name="text">
-            <string>XIT</string>
-           </property>
-          </widget>
-         </item>
-         <item>
-          <spacer name="horizontalSpacer_12">
-           <property name="orientation">
-            <enum>Qt::Horizontal</enum>
-           </property>
-           <property name="sizeHint" stdset="0">
-            <size>
-             <width>40</width>
-             <height>20</height>
-            </size>
-           </property>
-          </spacer>
-         </item>
-         <item>
-          <widget class="QLabel" name="label_47">
-           <property name="sizePolicy">
-            <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
-             <horstretch>0</horstretch>
-             <verstretch>0</verstretch>
-            </sizepolicy>
-           </property>
-           <property name="minimumSize">
-            <size>
-             <width>60</width>
-             <height>0</height>
-            </size>
-           </property>
-           <property name="text">
-            <string>Polling interval (s):</string>
-           </property>
-          </widget>
-         </item>
-         <item>
-          <widget class="QSpinBox" name="pollSpinBox">
-           <property name="minimumSize">
-            <size>
-             <width>50</width>
-             <height>0</height>
-            </size>
-           </property>
-           <property name="toolTip">
-            <string>Select interval for reading dial frequency</string>
-           </property>
-           <property name="maximum">
-            <number>60</number>
-           </property>
-          </widget>
-         </item>
-        </layout>
-       </item>
-       <item>
-        <spacer name="verticalSpacer_1">
-         <property name="orientation">
-          <enum>Qt::Vertical</enum>
-         </property>
-         <property name="sizeHint" stdset="0">
-          <size>
-           <width>20</width>
-           <height>13</height>
-          </size>
-         </property>
-        </spacer>
-       </item>
-       <item>
-        <layout class="QHBoxLayout" name="horizontalLayout_13">
-         <item>
-          <spacer name="horizontalSpacer_15">
-           <property name="orientation">
-            <enum>Qt::Horizontal</enum>
-           </property>
-           <property name="sizeType">
-            <enum>QSizePolicy::Fixed</enum>
-           </property>
-           <property name="sizeHint" stdset="0">
-            <size>
-             <width>96</width>
-             <height>20</height>
-            </size>
-           </property>
-          </spacer>
-         </item>
-         <item>
-          <widget class="QLabel" name="label_26">
-           <property name="sizePolicy">
-            <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
-             <horstretch>0</horstretch>
-             <verstretch>0</verstretch>
-            </sizepolicy>
-           </property>
-           <property name="minimumSize">
-            <size>
-             <width>90</width>
-             <height>0</height>
-            </size>
-           </property>
-           <property name="maximumSize">
-            <size>
-             <width>16777215</width>
-             <height>16777215</height>
-            </size>
-           </property>
-           <property name="text">
-            <string>Dev Ch  API       Name</string>
-           </property>
-          </widget>
-         </item>
-        </layout>
-       </item>
-       <item>
-        <layout class="QVBoxLayout" name="verticalLayout_6">
-         <item>
-          <layout class="QHBoxLayout" name="horizontalLayout_3">
-           <item>
-            <widget class="QLabel" name="label_6">
-             <property name="minimumSize">
-              <size>
-               <width>90</width>
-               <height>0</height>
-              </size>
-             </property>
-             <property name="maximumSize">
-              <size>
-               <width>90</width>
-               <height>16777215</height>
-              </size>
-             </property>
-             <property name="text">
-              <string>Audio In:</string>
-             </property>
-            </widget>
-           </item>
-           <item>
-            <widget class="QComboBox" name="comboBoxSndIn">
-             <property name="enabled">
-              <bool>true</bool>
-             </property>
-             <property name="toolTip">
-              <string>Select audio input device and driver API</string>
-             </property>
-            </widget>
-           </item>
-          </layout>
-         </item>
-         <item>
-          <layout class="QHBoxLayout" name="horizontalLayout_4">
-           <item>
-            <widget class="QLabel" name="label_7">
-             <property name="sizePolicy">
-              <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
-               <horstretch>0</horstretch>
-               <verstretch>0</verstretch>
-              </sizepolicy>
-             </property>
-             <property name="minimumSize">
-              <size>
-               <width>90</width>
-               <height>0</height>
-              </size>
-             </property>
-             <property name="maximumSize">
-              <size>
-               <width>90</width>
-               <height>16777215</height>
-              </size>
-             </property>
-             <property name="text">
-              <string>Audio Out:</string>
-             </property>
-            </widget>
-           </item>
-           <item>
-            <widget class="QComboBox" name="comboBoxSndOut">
-             <property name="toolTip">
-              <string>select audio output device and driver API</string>
-             </property>
-            </widget>
-           </item>
-          </layout>
-         </item>
-         <item>
-          <layout class="QHBoxLayout" name="horizontalLayout">
-           <item>
-            <widget class="QLabel" name="label_10">
-             <property name="sizePolicy">
-              <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
-               <horstretch>0</horstretch>
-               <verstretch>0</verstretch>
-              </sizepolicy>
-             </property>
-             <property name="minimumSize">
-              <size>
-               <width>90</width>
-               <height>20</height>
-              </size>
-             </property>
-             <property name="text">
-              <string>Save Directory:</string>
-             </property>
-            </widget>
-           </item>
-           <item>
-            <widget class="QLineEdit" name="saveDirEntry">
-             <property name="toolTip">
-              <string>Directory for saved audio files</string>
-             </property>
-             <property name="text">
-              <string>C:\Users\joe\wsjt\map65\save</string>
-             </property>
-            </widget>
-           </item>
-          </layout>
-         </item>
-        </layout>
-       </item>
-      </layout>
-     </widget>
-     <widget class="QWidget" name="tab_2">
-      <attribute name="title">
-       <string>Tx Macros</string>
-      </attribute>
-      <layout class="QVBoxLayout" name="verticalLayout_4">
-       <item>
-        <spacer name="verticalSpacer_5">
-         <property name="orientation">
-          <enum>Qt::Vertical</enum>
-         </property>
-         <property name="sizeHint" stdset="0">
-          <size>
-           <width>20</width>
-           <height>40</height>
-          </size>
-         </property>
-        </spacer>
-       </item>
-       <item>
-        <layout class="QGridLayout" name="gridLayout">
-         <item row="6" column="1">
-          <widget class="QLabel" name="label_17">
-           <property name="sizePolicy">
-            <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
-             <horstretch>0</horstretch>
-             <verstretch>0</verstretch>
-            </sizepolicy>
-           </property>
-           <property name="minimumSize">
-            <size>
-             <width>20</width>
-             <height>0</height>
-            </size>
-           </property>
-           <property name="maximumSize">
-            <size>
-             <width>20</width>
-             <height>16777215</height>
-            </size>
-           </property>
-           <property name="text">
-            <string>7</string>
-           </property>
-          </widget>
-         </item>
-         <item row="5" column="2">
-          <widget class="QLineEdit" name="macro6">
-           <property name="sizePolicy">
-            <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-             <horstretch>0</horstretch>
-             <verstretch>0</verstretch>
-            </sizepolicy>
-           </property>
-           <property name="minimumSize">
-            <size>
-             <width>200</width>
-             <height>0</height>
-            </size>
-           </property>
-           <property name="maximumSize">
-            <size>
-             <width>200</width>
-             <height>16777215</height>
-            </size>
-           </property>
-          </widget>
-         </item>
-         <item row="0" column="2">
-          <widget class="QLineEdit" name="macro1">
-           <property name="sizePolicy">
-            <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-             <horstretch>0</horstretch>
-             <verstretch>0</verstretch>
-            </sizepolicy>
-           </property>
-           <property name="minimumSize">
-            <size>
-             <width>200</width>
-             <height>0</height>
-            </size>
-           </property>
-           <property name="maximumSize">
-            <size>
-             <width>200</width>
-             <height>16777215</height>
-            </size>
-           </property>
-           <property name="text">
-            <string/>
-           </property>
-          </widget>
-         </item>
-         <item row="2" column="1">
-          <widget class="QLabel" name="label_13">
-           <property name="sizePolicy">
-            <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
-             <horstretch>0</horstretch>
-             <verstretch>0</verstretch>
-            </sizepolicy>
-           </property>
-           <property name="minimumSize">
-            <size>
-             <width>20</width>
-             <height>0</height>
-            </size>
-           </property>
-           <property name="maximumSize">
-            <size>
-             <width>20</width>
-             <height>16777215</height>
-            </size>
-           </property>
-           <property name="text">
-            <string>3</string>
-           </property>
-          </widget>
-         </item>
-         <item row="2" column="2">
-          <widget class="QLineEdit" name="macro3">
-           <property name="sizePolicy">
-            <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-             <horstretch>0</horstretch>
-             <verstretch>0</verstretch>
-            </sizepolicy>
-           </property>
-           <property name="minimumSize">
-            <size>
-             <width>200</width>
-             <height>0</height>
-            </size>
-           </property>
-           <property name="maximumSize">
-            <size>
-             <width>200</width>
-             <height>16777215</height>
-            </size>
-           </property>
-           <property name="text">
-            <string>10W DPL 73 GL</string>
-           </property>
-          </widget>
-         </item>
-         <item row="4" column="1">
-          <widget class="QLabel" name="label_15">
-           <property name="sizePolicy">
-            <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
-             <horstretch>0</horstretch>
-             <verstretch>0</verstretch>
-            </sizepolicy>
-           </property>
-           <property name="minimumSize">
-            <size>
-             <width>20</width>
-             <height>0</height>
-            </size>
-           </property>
-           <property name="maximumSize">
-            <size>
-             <width>20</width>
-             <height>16777215</height>
-            </size>
-           </property>
-           <property name="text">
-            <string>5</string>
-           </property>
-          </widget>
-         </item>
-         <item row="7" column="1">
-          <widget class="QLabel" name="label_18">
-           <property name="sizePolicy">
-            <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
-             <horstretch>0</horstretch>
-             <verstretch>0</verstretch>
-            </sizepolicy>
-           </property>
-           <property name="minimumSize">
-            <size>
-             <width>20</width>
-             <height>0</height>
-            </size>
-           </property>
-           <property name="maximumSize">
-            <size>
-             <width>20</width>
-             <height>16777215</height>
-            </size>
-           </property>
-           <property name="text">
-            <string>8</string>
-           </property>
-          </widget>
-         </item>
-         <item row="8" column="1">
-          <widget class="QLabel" name="label_19">
-           <property name="sizePolicy">
-            <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
-             <horstretch>0</horstretch>
-             <verstretch>0</verstretch>
-            </sizepolicy>
-           </property>
-           <property name="minimumSize">
-            <size>
-             <width>20</width>
-             <height>0</height>
-            </size>
-           </property>
-           <property name="maximumSize">
-            <size>
-             <width>20</width>
-             <height>16777215</height>
-            </size>
-           </property>
-           <property name="text">
-            <string>9</string>
-           </property>
-          </widget>
-         </item>
-         <item row="9" column="1">
-          <widget class="QLabel" name="label_20">
-           <property name="sizePolicy">
-            <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
-             <horstretch>0</horstretch>
-             <verstretch>0</verstretch>
-            </sizepolicy>
-           </property>
-           <property name="minimumSize">
-            <size>
-             <width>20</width>
-             <height>0</height>
-            </size>
-           </property>
-           <property name="maximumSize">
-            <size>
-             <width>20</width>
-             <height>16777215</height>
-            </size>
-           </property>
-           <property name="text">
-            <string>10</string>
-           </property>
-          </widget>
-         </item>
-         <item row="5" column="1">
-          <widget class="QLabel" name="label_16">
-           <property name="sizePolicy">
-            <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
-             <horstretch>0</horstretch>
-             <verstretch>0</verstretch>
-            </sizepolicy>
-           </property>
-           <property name="minimumSize">
-            <size>
-             <width>20</width>
-             <height>0</height>
-            </size>
-           </property>
-           <property name="maximumSize">
-            <size>
-             <width>20</width>
-             <height>16777215</height>
-            </size>
-           </property>
-           <property name="text">
-            <string>6</string>
-           </property>
-          </widget>
-         </item>
-         <item row="3" column="1">
-          <widget class="QLabel" name="label_14">
-           <property name="sizePolicy">
-            <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
-             <horstretch>0</horstretch>
-             <verstretch>0</verstretch>
-            </sizepolicy>
-           </property>
-           <property name="minimumSize">
-            <size>
-             <width>20</width>
-             <height>0</height>
-            </size>
-           </property>
-           <property name="maximumSize">
-            <size>
-             <width>20</width>
-             <height>16777215</height>
-            </size>
-           </property>
-           <property name="text">
-            <string>4</string>
-           </property>
-          </widget>
-         </item>
-         <item row="9" column="2">
-          <widget class="QLineEdit" name="macro10">
-           <property name="sizePolicy">
-            <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-             <horstretch>0</horstretch>
-             <verstretch>0</verstretch>
-            </sizepolicy>
-           </property>
-           <property name="minimumSize">
-            <size>
-             <width>200</width>
-             <height>0</height>
-            </size>
-           </property>
-           <property name="maximumSize">
-            <size>
-             <width>200</width>
-             <height>16777215</height>
-            </size>
-           </property>
-          </widget>
-         </item>
-         <item row="4" column="2">
-          <widget class="QLineEdit" name="macro5">
-           <property name="sizePolicy">
-            <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-             <horstretch>0</horstretch>
-             <verstretch>0</verstretch>
-            </sizepolicy>
-           </property>
-           <property name="minimumSize">
-            <size>
-             <width>200</width>
-             <height>0</height>
-            </size>
-           </property>
-           <property name="maximumSize">
-            <size>
-             <width>200</width>
-             <height>16777215</height>
-            </size>
-           </property>
-           <property name="text">
-            <string/>
-           </property>
-          </widget>
-         </item>
-         <item row="3" column="2">
-          <widget class="QLineEdit" name="macro4">
-           <property name="sizePolicy">
-            <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-             <horstretch>0</horstretch>
-             <verstretch>0</verstretch>
-            </sizepolicy>
-           </property>
-           <property name="minimumSize">
-            <size>
-             <width>200</width>
-             <height>0</height>
-            </size>
-           </property>
-           <property name="maximumSize">
-            <size>
-             <width>200</width>
-             <height>16777215</height>
-            </size>
-           </property>
-           <property name="text">
-            <string/>
-           </property>
-          </widget>
-         </item>
-         <item row="1" column="2">
-          <widget class="QLineEdit" name="macro2">
-           <property name="sizePolicy">
-            <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-             <horstretch>0</horstretch>
-             <verstretch>0</verstretch>
-            </sizepolicy>
-           </property>
-           <property name="minimumSize">
-            <size>
-             <width>200</width>
-             <height>0</height>
-            </size>
-           </property>
-           <property name="maximumSize">
-            <size>
-             <width>200</width>
-             <height>16777215</height>
-            </size>
-           </property>
-           <property name="text">
-            <string>5W DPL 73 GL</string>
-           </property>
-          </widget>
-         </item>
-         <item row="8" column="2">
-          <widget class="QLineEdit" name="macro9">
-           <property name="sizePolicy">
-            <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-             <horstretch>0</horstretch>
-             <verstretch>0</verstretch>
-            </sizepolicy>
-           </property>
-           <property name="minimumSize">
-            <size>
-             <width>200</width>
-             <height>0</height>
-            </size>
-           </property>
-           <property name="maximumSize">
-            <size>
-             <width>200</width>
-             <height>16777215</height>
-            </size>
-           </property>
-          </widget>
-         </item>
-         <item row="5" column="3">
-          <spacer name="horizontalSpacer_8">
-           <property name="orientation">
-            <enum>Qt::Horizontal</enum>
-           </property>
-           <property name="sizeHint" stdset="0">
-            <size>
-             <width>40</width>
-             <height>20</height>
-            </size>
-           </property>
-          </spacer>
-         </item>
-         <item row="0" column="1">
-          <widget class="QLabel" name="label_11">
-           <property name="sizePolicy">
-            <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
-             <horstretch>0</horstretch>
-             <verstretch>0</verstretch>
-            </sizepolicy>
-           </property>
-           <property name="minimumSize">
-            <size>
-             <width>20</width>
-             <height>0</height>
-            </size>
-           </property>
-           <property name="maximumSize">
-            <size>
-             <width>20</width>
-             <height>16777215</height>
-            </size>
-           </property>
-           <property name="text">
-            <string>1</string>
-           </property>
-          </widget>
-         </item>
-         <item row="6" column="2">
-          <widget class="QLineEdit" name="macro7">
-           <property name="sizePolicy">
-            <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-             <horstretch>0</horstretch>
-             <verstretch>0</verstretch>
-            </sizepolicy>
-           </property>
-           <property name="minimumSize">
-            <size>
-             <width>200</width>
-             <height>0</height>
-            </size>
-           </property>
-           <property name="maximumSize">
-            <size>
-             <width>200</width>
-             <height>16777215</height>
-            </size>
-           </property>
-          </widget>
-         </item>
-         <item row="1" column="1">
-          <widget class="QLabel" name="label_12">
-           <property name="sizePolicy">
-            <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
-             <horstretch>0</horstretch>
-             <verstretch>0</verstretch>
-            </sizepolicy>
-           </property>
-           <property name="minimumSize">
-            <size>
-             <width>20</width>
-             <height>0</height>
-            </size>
-           </property>
-           <property name="maximumSize">
-            <size>
-             <width>20</width>
-             <height>16777215</height>
-            </size>
-           </property>
-           <property name="text">
-            <string>2</string>
-           </property>
-          </widget>
-         </item>
-         <item row="7" column="2">
-          <widget class="QLineEdit" name="macro8">
-           <property name="sizePolicy">
-            <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-             <horstretch>0</horstretch>
-             <verstretch>0</verstretch>
-            </sizepolicy>
-           </property>
-           <property name="minimumSize">
-            <size>
-             <width>200</width>
-             <height>0</height>
-            </size>
-           </property>
-           <property name="maximumSize">
-            <size>
-             <width>200</width>
-             <height>16777215</height>
-            </size>
-           </property>
-          </widget>
-         </item>
-         <item row="5" column="0">
-          <spacer name="horizontalSpacer">
-           <property name="orientation">
-            <enum>Qt::Horizontal</enum>
-           </property>
-           <property name="sizeHint" stdset="0">
-            <size>
-             <width>40</width>
-             <height>20</height>
-            </size>
-           </property>
-          </spacer>
-         </item>
-        </layout>
-       </item>
-       <item>
-        <spacer name="verticalSpacer_3">
-         <property name="orientation">
-          <enum>Qt::Vertical</enum>
-         </property>
-         <property name="sizeHint" stdset="0">
-          <size>
-           <width>20</width>
-           <height>40</height>
-          </size>
-         </property>
-        </spacer>
-       </item>
-      </layout>
-     </widget>
-     <widget class="QWidget" name="tab_3">
-      <attribute name="title">
-       <string>Default Frequencies</string>
-      </attribute>
-      <layout class="QVBoxLayout" name="verticalLayout_5">
-       <item>
-        <spacer name="verticalSpacer_6">
-         <property name="orientation">
-          <enum>Qt::Vertical</enum>
-         </property>
-         <property name="sizeHint" stdset="0">
-          <size>
-           <width>20</width>
-           <height>40</height>
-          </size>
-         </property>
-        </spacer>
-       </item>
-       <item>
-        <layout class="QGridLayout" name="gridLayout_2">
-         <item row="5" column="4">
-          <widget class="QLabel" name="label_39">
-           <property name="text">
-            <string>6 m</string>
-           </property>
-          </widget>
-         </item>
-         <item row="5" column="5">
-          <widget class="QLineEdit" name="f13">
-           <property name="sizePolicy">
-            <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-             <horstretch>0</horstretch>
-             <verstretch>0</verstretch>
-            </sizepolicy>
-           </property>
-           <property name="minimumSize">
-            <size>
-             <width>90</width>
-             <height>27</height>
-            </size>
-           </property>
-           <property name="maximumSize">
-            <size>
-             <width>90</width>
-             <height>16777215</height>
-            </size>
-           </property>
-           <property name="text">
-            <string>50.293</string>
-           </property>
-           <property name="alignment">
-            <set>Qt::AlignCenter</set>
-           </property>
-          </widget>
-         </item>
-         <item row="0" column="1">
-          <widget class="QLabel" name="label_43">
-           <property name="text">
-            <string>Band</string>
-           </property>
-          </widget>
-         </item>
-         <item row="0" column="2">
-          <widget class="QLabel" name="label_44">
-           <property name="text">
-            <string>Freq (MHz)</string>
-           </property>
-          </widget>
-         </item>
-         <item row="3" column="5">
-          <widget class="QLineEdit" name="f11">
-           <property name="sizePolicy">
-            <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-             <horstretch>0</horstretch>
-             <verstretch>0</verstretch>
-            </sizepolicy>
-           </property>
-           <property name="minimumSize">
-            <size>
-             <width>90</width>
-             <height>27</height>
-            </size>
-           </property>
-           <property name="maximumSize">
-            <size>
-             <width>90</width>
-             <height>16777215</height>
-            </size>
-           </property>
-           <property name="text">
-            <string>24.9246</string>
-           </property>
-           <property name="alignment">
-            <set>Qt::AlignCenter</set>
-           </property>
-          </widget>
-         </item>
-         <item row="4" column="1">
-          <widget class="QLabel" name="label_30">
-           <property name="text">
-            <string>80 m</string>
-           </property>
-          </widget>
-         </item>
-         <item row="2" column="4">
-          <widget class="QLabel" name="label_36">
-           <property name="text">
-            <string>15 m</string>
-           </property>
-          </widget>
-         </item>
-         <item row="2" column="5">
-          <widget class="QLineEdit" name="f10">
-           <property name="sizePolicy">
-            <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-             <horstretch>0</horstretch>
-             <verstretch>0</verstretch>
-            </sizepolicy>
-           </property>
-           <property name="minimumSize">
-            <size>
-             <width>90</width>
-             <height>27</height>
-            </size>
-           </property>
-           <property name="maximumSize">
-            <size>
-             <width>90</width>
-             <height>16777215</height>
-            </size>
-           </property>
-           <property name="text">
-            <string>21.078</string>
-           </property>
-           <property name="alignment">
-            <set>Qt::AlignCenter</set>
-           </property>
-          </widget>
-         </item>
-         <item row="4" column="4">
-          <widget class="QLabel" name="label_38">
-           <property name="text">
-            <string>10 m</string>
-           </property>
-          </widget>
-         </item>
-         <item row="1" column="1">
-          <widget class="QLabel" name="label_27">
-           <property name="text">
-            <string>2200 m</string>
-           </property>
-          </widget>
-         </item>
-         <item row="3" column="4">
-          <widget class="QLabel" name="label_37">
-           <property name="text">
-            <string>12 m</string>
-           </property>
-          </widget>
-         </item>
-         <item row="4" column="5">
-          <widget class="QLineEdit" name="f12">
-           <property name="sizePolicy">
-            <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-             <horstretch>0</horstretch>
-             <verstretch>0</verstretch>
-            </sizepolicy>
-           </property>
-           <property name="minimumSize">
-            <size>
-             <width>90</width>
-             <height>27</height>
-            </size>
-           </property>
-           <property name="maximumSize">
-            <size>
-             <width>90</width>
-             <height>16777215</height>
-            </size>
-           </property>
-           <property name="text">
-            <string>28.078</string>
-           </property>
-           <property name="alignment">
-            <set>Qt::AlignCenter</set>
-           </property>
-          </widget>
-         </item>
-         <item row="6" column="5">
-          <widget class="QLineEdit" name="f14">
-           <property name="sizePolicy">
-            <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-             <horstretch>0</horstretch>
-             <verstretch>0</verstretch>
-            </sizepolicy>
-           </property>
-           <property name="minimumSize">
-            <size>
-             <width>90</width>
-             <height>27</height>
-            </size>
-           </property>
-           <property name="maximumSize">
-            <size>
-             <width>90</width>
-             <height>16777215</height>
-            </size>
-           </property>
-           <property name="text">
-            <string>70.091</string>
-           </property>
-           <property name="alignment">
-            <set>Qt::AlignCenter</set>
-           </property>
-          </widget>
-         </item>
-         <item row="5" column="1">
-          <widget class="QLabel" name="label_31">
-           <property name="text">
-            <string>60 m</string>
-           </property>
-          </widget>
-         </item>
-         <item row="6" column="1">
-          <widget class="QLabel" name="label_32">
-           <property name="text">
-            <string>40 m</string>
-           </property>
-          </widget>
-         </item>
-         <item row="6" column="4">
-          <widget class="QLabel" name="label_40">
-           <property name="text">
-            <string>4 m</string>
-           </property>
-          </widget>
-         </item>
-         <item row="1" column="4">
-          <widget class="QLabel" name="label_35">
-           <property name="text">
-            <string>17 m</string>
-           </property>
-          </widget>
-         </item>
-         <item row="0" column="4">
-          <widget class="QLabel" name="label_45">
-           <property name="text">
-            <string>Band</string>
-           </property>
-          </widget>
-         </item>
-         <item row="0" column="5">
-          <widget class="QLabel" name="label_46">
-           <property name="text">
-            <string>Freq (MHz)</string>
-           </property>
-          </widget>
-         </item>
-         <item row="7" column="1">
-          <widget class="QLabel" name="label_33">
-           <property name="text">
-            <string>30 m</string>
-           </property>
-          </widget>
-         </item>
-         <item row="8" column="5">
-          <widget class="QLineEdit" name="f16">
-           <property name="sizePolicy">
-            <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-             <horstretch>0</horstretch>
-             <verstretch>0</verstretch>
-            </sizepolicy>
-           </property>
-           <property name="minimumSize">
-            <size>
-             <width>90</width>
-             <height>27</height>
-            </size>
-           </property>
-           <property name="maximumSize">
-            <size>
-             <width>90</width>
-             <height>16777215</height>
-            </size>
-           </property>
-           <property name="text">
-            <string>432.178</string>
-           </property>
-           <property name="alignment">
-            <set>Qt::AlignCenter</set>
-           </property>
-          </widget>
-         </item>
-         <item row="3" column="1">
-          <widget class="QLabel" name="label_29">
-           <property name="text">
-            <string>160 m</string>
-           </property>
-          </widget>
-         </item>
-         <item row="2" column="1">
-          <widget class="QLabel" name="label_28">
-           <property name="text">
-            <string>630 m</string>
-           </property>
-          </widget>
-         </item>
-         <item row="8" column="1">
-          <widget class="QLabel" name="label_34">
-           <property name="text">
-            <string>20 m</string>
-           </property>
-          </widget>
-         </item>
-         <item row="8" column="4">
-          <widget class="QLabel" name="label_42">
-           <property name="text">
-            <string>Other</string>
-           </property>
-          </widget>
-         </item>
-         <item row="1" column="5">
-          <widget class="QLineEdit" name="f9">
-           <property name="sizePolicy">
-            <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-             <horstretch>0</horstretch>
-             <verstretch>0</verstretch>
-            </sizepolicy>
-           </property>
-           <property name="minimumSize">
-            <size>
-             <width>90</width>
-             <height>27</height>
-            </size>
-           </property>
-           <property name="maximumSize">
-            <size>
-             <width>90</width>
-             <height>16777215</height>
-            </size>
-           </property>
-           <property name="text">
-            <string>18.1046</string>
-           </property>
-           <property name="alignment">
-            <set>Qt::AlignCenter</set>
-           </property>
-          </widget>
-         </item>
-         <item row="2" column="2">
-          <widget class="QLineEdit" name="f2">
-           <property name="sizePolicy">
-            <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-             <horstretch>0</horstretch>
-             <verstretch>0</verstretch>
-            </sizepolicy>
-           </property>
-           <property name="minimumSize">
-            <size>
-             <width>90</width>
-             <height>27</height>
-            </size>
-           </property>
-           <property name="maximumSize">
-            <size>
-             <width>90</width>
-             <height>16777215</height>
-            </size>
-           </property>
-           <property name="text">
-            <string>0.4742</string>
-           </property>
-           <property name="alignment">
-            <set>Qt::AlignCenter</set>
-           </property>
-          </widget>
-         </item>
-         <item row="7" column="4">
-          <widget class="QLabel" name="label_41">
-           <property name="text">
-            <string>2 m</string>
-           </property>
-          </widget>
-         </item>
-         <item row="7" column="5">
-          <widget class="QLineEdit" name="f15">
-           <property name="sizePolicy">
-            <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-             <horstretch>0</horstretch>
-             <verstretch>0</verstretch>
-            </sizepolicy>
-           </property>
-           <property name="minimumSize">
-            <size>
-             <width>90</width>
-             <height>27</height>
-            </size>
-           </property>
-           <property name="maximumSize">
-            <size>
-             <width>90</width>
-             <height>16777215</height>
-            </size>
-           </property>
-           <property name="text">
-            <string>144.489</string>
-           </property>
-           <property name="alignment">
-            <set>Qt::AlignCenter</set>
-           </property>
-          </widget>
-         </item>
-         <item row="1" column="2">
-          <widget class="QLineEdit" name="f1">
-           <property name="sizePolicy">
-            <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-             <horstretch>0</horstretch>
-             <verstretch>0</verstretch>
-            </sizepolicy>
-           </property>
-           <property name="minimumSize">
-            <size>
-             <width>90</width>
-             <height>27</height>
-            </size>
-           </property>
-           <property name="maximumSize">
-            <size>
-             <width>90</width>
-             <height>16777215</height>
-            </size>
-           </property>
-           <property name="text">
-            <string>0.136</string>
-           </property>
-           <property name="alignment">
-            <set>Qt::AlignCenter</set>
-           </property>
-          </widget>
-         </item>
-         <item row="3" column="2">
-          <widget class="QLineEdit" name="f3">
-           <property name="sizePolicy">
-            <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-             <horstretch>0</horstretch>
-             <verstretch>0</verstretch>
-            </sizepolicy>
-           </property>
-           <property name="minimumSize">
-            <size>
-             <width>90</width>
-             <height>27</height>
-            </size>
-           </property>
-           <property name="maximumSize">
-            <size>
-             <width>90</width>
-             <height>16777215</height>
-            </size>
-           </property>
-           <property name="text">
-            <string>1.838</string>
-           </property>
-           <property name="alignment">
-            <set>Qt::AlignCenter</set>
-           </property>
-          </widget>
-         </item>
-         <item row="5" column="2">
-          <widget class="QLineEdit" name="f5">
-           <property name="sizePolicy">
-            <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-             <horstretch>0</horstretch>
-             <verstretch>0</verstretch>
-            </sizepolicy>
-           </property>
-           <property name="minimumSize">
-            <size>
-             <width>90</width>
-             <height>27</height>
-            </size>
-           </property>
-           <property name="maximumSize">
-            <size>
-             <width>90</width>
-             <height>16777215</height>
-            </size>
-           </property>
-           <property name="text">
-            <string>5.2872</string>
-           </property>
-           <property name="alignment">
-            <set>Qt::AlignCenter</set>
-           </property>
-          </widget>
-         </item>
-         <item row="4" column="2">
-          <widget class="QLineEdit" name="f4">
-           <property name="sizePolicy">
-            <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-             <horstretch>0</horstretch>
-             <verstretch>0</verstretch>
-            </sizepolicy>
-           </property>
-           <property name="minimumSize">
-            <size>
-             <width>90</width>
-             <height>27</height>
-            </size>
-           </property>
-           <property name="maximumSize">
-            <size>
-             <width>90</width>
-             <height>16777215</height>
-            </size>
-           </property>
-           <property name="text">
-            <string>3.578</string>
-           </property>
-           <property name="alignment">
-            <set>Qt::AlignCenter</set>
-           </property>
-          </widget>
-         </item>
-         <item row="4" column="3">
-          <spacer name="horizontalSpacer_9">
-           <property name="orientation">
-            <enum>Qt::Horizontal</enum>
-           </property>
-           <property name="sizeHint" stdset="0">
-            <size>
-             <width>40</width>
-             <height>20</height>
-            </size>
-           </property>
-          </spacer>
-         </item>
-         <item row="7" column="2">
-          <widget class="QLineEdit" name="f7">
-           <property name="sizePolicy">
-            <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-             <horstretch>0</horstretch>
-             <verstretch>0</verstretch>
-            </sizepolicy>
-           </property>
-           <property name="minimumSize">
-            <size>
-             <width>90</width>
-             <height>27</height>
-            </size>
-           </property>
-           <property name="maximumSize">
-            <size>
-             <width>90</width>
-             <height>16777215</height>
-            </size>
-           </property>
-           <property name="text">
-            <string>10.130</string>
-           </property>
-           <property name="alignment">
-            <set>Qt::AlignCenter</set>
-           </property>
-          </widget>
-         </item>
-         <item row="6" column="2">
-          <widget class="QLineEdit" name="f6">
-           <property name="sizePolicy">
-            <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-             <horstretch>0</horstretch>
-             <verstretch>0</verstretch>
-            </sizepolicy>
-           </property>
-           <property name="minimumSize">
-            <size>
-             <width>90</width>
-             <height>27</height>
-            </size>
-           </property>
-           <property name="maximumSize">
-            <size>
-             <width>90</width>
-             <height>16777215</height>
-            </size>
-           </property>
-           <property name="text">
-            <string>7.078</string>
-           </property>
-           <property name="alignment">
-            <set>Qt::AlignCenter</set>
-           </property>
-          </widget>
-         </item>
-         <item row="8" column="2">
-          <widget class="QLineEdit" name="f8">
-           <property name="sizePolicy">
-            <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-             <horstretch>0</horstretch>
-             <verstretch>0</verstretch>
-            </sizepolicy>
-           </property>
-           <property name="minimumSize">
-            <size>
-             <width>90</width>
-             <height>27</height>
-            </size>
-           </property>
-           <property name="maximumSize">
-            <size>
-             <width>90</width>
-             <height>16777215</height>
-            </size>
-           </property>
-           <property name="text">
-            <string>14.078</string>
-           </property>
-           <property name="alignment">
-            <set>Qt::AlignCenter</set>
-           </property>
-          </widget>
-         </item>
-         <item row="4" column="0">
-          <spacer name="horizontalSpacer_10">
-           <property name="orientation">
-            <enum>Qt::Horizontal</enum>
-           </property>
-           <property name="sizeHint" stdset="0">
-            <size>
-             <width>40</width>
-             <height>20</height>
-            </size>
-           </property>
-          </spacer>
-         </item>
-         <item row="4" column="6">
-          <spacer name="horizontalSpacer_11">
-           <property name="orientation">
-            <enum>Qt::Horizontal</enum>
-           </property>
-           <property name="sizeHint" stdset="0">
-            <size>
-             <width>40</width>
-             <height>20</height>
-            </size>
-           </property>
-          </spacer>
-         </item>
-        </layout>
-       </item>
-       <item>
-        <spacer name="verticalSpacer_4">
-         <property name="orientation">
-          <enum>Qt::Vertical</enum>
-         </property>
-         <property name="sizeHint" stdset="0">
-          <size>
-           <width>20</width>
-           <height>40</height>
-          </size>
-         </property>
-        </spacer>
-       </item>
-      </layout>
-     </widget>
-    </widget>
-   </item>
-   <item>
-    <widget class="QDialogButtonBox" name="buttonBox">
-     <property name="maximumSize">
-      <size>
-       <width>469</width>
-       <height>16777215</height>
-      </size>
-     </property>
-     <property name="orientation">
-      <enum>Qt::Horizontal</enum>
-     </property>
-     <property name="standardButtons">
-      <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
-     </property>
-    </widget>
-   </item>
-  </layout>
- </widget>
- <tabstops>
-  <tabstop>myCallEntry</tabstop>
-  <tabstop>myGridEntry</tabstop>
-  <tabstop>pttMethodComboBox</tabstop>
-  <tabstop>pttComboBox</tabstop>
-  <tabstop>cbPSKReporter</tabstop>
-  <tabstop>cbID73</tabstop>
-  <tabstop>idIntSpinBox</tabstop>
-  <tabstop>pskReporterAntenna</tabstop>
-  <tabstop>cbEnableCAT</tabstop>
-  <tabstop>rigComboBox</tabstop>
-  <tabstop>catPortComboBox</tabstop>
-  <tabstop>dataBitsComboBox</tabstop>
-  <tabstop>serialRateComboBox</tabstop>
-  <tabstop>stopBitsComboBox</tabstop>
-  <tabstop>handshakeComboBox</tabstop>
-  <tabstop>testCATButton</tabstop>
-  <tabstop>testPTTButton</tabstop>
-  <tabstop>pollSpinBox</tabstop>
-  <tabstop>comboBoxSndIn</tabstop>
-  <tabstop>comboBoxSndOut</tabstop>
-  <tabstop>saveDirEntry</tabstop>
-  <tabstop>macro1</tabstop>
-  <tabstop>macro2</tabstop>
-  <tabstop>macro3</tabstop>
-  <tabstop>macro4</tabstop>
-  <tabstop>macro5</tabstop>
-  <tabstop>macro6</tabstop>
-  <tabstop>macro7</tabstop>
-  <tabstop>macro8</tabstop>
-  <tabstop>macro9</tabstop>
-  <tabstop>macro10</tabstop>
-  <tabstop>f1</tabstop>
-  <tabstop>f2</tabstop>
-  <tabstop>f3</tabstop>
-  <tabstop>f4</tabstop>
-  <tabstop>f5</tabstop>
-  <tabstop>f6</tabstop>
-  <tabstop>f7</tabstop>
-  <tabstop>f8</tabstop>
-  <tabstop>f9</tabstop>
-  <tabstop>f10</tabstop>
-  <tabstop>f11</tabstop>
-  <tabstop>f12</tabstop>
-  <tabstop>f13</tabstop>
-  <tabstop>f14</tabstop>
-  <tabstop>f15</tabstop>
-  <tabstop>f16</tabstop>
-  <tabstop>buttonBox</tabstop>
-  <tabstop>ioTabWidget</tabstop>
- </tabstops>
- <resources/>
- <connections>
-  <connection>
-   <sender>buttonBox</sender>
-   <signal>accepted()</signal>
-   <receiver>DialogSndCard</receiver>
-   <slot>accept()</slot>
-   <hints>
-    <hint type="sourcelabel">
-     <x>248</x>
-     <y>254</y>
-    </hint>
-    <hint type="destinationlabel">
-     <x>157</x>
-     <y>274</y>
-    </hint>
-   </hints>
-  </connection>
-  <connection>
-   <sender>buttonBox</sender>
-   <signal>rejected()</signal>
-   <receiver>DialogSndCard</receiver>
-   <slot>reject()</slot>
-   <hints>
-    <hint type="sourcelabel">
-     <x>316</x>
-     <y>260</y>
-    </hint>
-    <hint type="destinationlabel">
-     <x>286</x>
-     <y>274</y>
-    </hint>
-   </hints>
-  </connection>
- </connections>
-</ui>
diff --git a/displaytext.cpp b/displaytext.cpp
index 0b8181e..094099e 100644
--- a/displaytext.cpp
+++ b/displaytext.cpp
@@ -1,10 +1,40 @@
 #include "displaytext.h"
-#include <QDebug>
+
 #include <QMouseEvent>
+#include <QDateTime>
+#include <QTextCharFormat>
+#include <QFont>
+#include <QTextCursor>
+
+#include "qt_helpers.hpp"
+
+#include "moc_displaytext.cpp"
 
 DisplayText::DisplayText(QWidget *parent) :
-    QTextBrowser(parent)
+    QTextEdit(parent)
 {
+    setReadOnly (true);
+    viewport ()->setCursor (Qt::ArrowCursor);
+    setWordWrapMode (QTextOption::NoWrap);
+    setStyleSheet ("");
+}
+
+void DisplayText::setContentFont(QFont const& font)
+{
+  setFont (font);
+  m_charFormat.setFont (font);
+  selectAll ();
+  auto cursor = textCursor ();
+  cursor.mergeCharFormat (m_charFormat);
+  cursor.clearSelection ();
+  cursor.movePosition (QTextCursor::End);
+
+  // position so viewport scrolled to left
+  cursor.movePosition (QTextCursor::Up);
+  cursor.movePosition (QTextCursor::StartOfLine);
+
+  setTextCursor (cursor);
+  ensureCursorVisible ();
 }
 
 void DisplayText::mouseDoubleClickEvent(QMouseEvent *e)
@@ -12,5 +42,139 @@ void DisplayText::mouseDoubleClickEvent(QMouseEvent *e)
   bool ctrl = (e->modifiers() & Qt::ControlModifier);
   bool shift = (e->modifiers() & Qt::ShiftModifier);
   emit(selectCallsign(shift,ctrl));
-  QTextBrowser::mouseDoubleClickEvent(e);
+  QTextEdit::mouseDoubleClickEvent(e);
+}
+
+void DisplayText::insertLineSpacer(QString const& line)
+{
+  _insertText (line, "#d3d3d3");
+}
+
+void DisplayText::_insertText(const QString text, const QString bg)
+{
+    QString s = "<table border=0 cellspacing=0 width=100%><tr><td bgcolor=\"" +
+      bg + "\">" + text.trimmed ().replace (' ', " ") + "</td></tr></table>";
+    auto cursor = textCursor ();
+    cursor.movePosition (QTextCursor::End);
+    auto pos = cursor.position ();
+    cursor.insertHtml (s);
+    cursor.setPosition (pos, QTextCursor::MoveAnchor);
+    cursor.movePosition (QTextCursor::End, QTextCursor::KeepAnchor);
+    cursor.mergeCharFormat (m_charFormat);
+    cursor.clearSelection ();
+
+    // position so viewport scrolled to left
+    cursor.movePosition (QTextCursor::Up);
+    cursor.movePosition (QTextCursor::StartOfLine);
+
+    setTextCursor (cursor);
+    ensureCursorVisible ();
+}
+
+
+void DisplayText::_appendDXCCWorkedB4(DecodedText& t1, QString& bg,
+                                      LogBook logBook, QColor color_CQ,
+                                      QColor color_DXCC,
+                                      QColor color_NewCall)
+{
+    QString call = t1.CQersCall ();
+
+    QString countryName;
+    bool callWorkedBefore;
+    bool countryWorkedBefore;
+    logBook.match(/*in*/call,/*out*/countryName,callWorkedBefore,countryWorkedBefore);
+
+    int charsAvail = 48;
+
+    // the decoder (seems) to always generate 40 chars. For a normal CQ call, the last five are spaces
+    // TODO this magic 36 characters is also referenced in MainWindow::doubleClickOnCall()
+    int s3 = t1.indexOf(" ",35);
+    if (s3 < 35)
+        s3 = 35; // we always want at least the characters to position 35
+    s3 += 1; // convert the index into a character count
+    t1 = t1.left(s3);  // reduce trailing white space
+    charsAvail -= s3;
+    if (charsAvail > 4)
+    {
+        if (!countryWorkedBefore) // therefore not worked call either
+        {
+            t1 += "!";
+            bg=color_DXCC.name();
+        }
+        else
+            if (!callWorkedBefore) // but have worked the country
+            {
+                t1 += "~";
+                bg=color_NewCall.name();
+            }
+            else
+            {
+                t1 += " ";  // have worked this call before
+                bg=color_CQ.name();
+            }
+        charsAvail -= 1;
+
+        // do some obvious abbreviations
+        countryName.replace ("Islands", "Is.");
+        countryName.replace ("Island", "Is.");
+        countryName.replace ("North ", "N. ");
+        countryName.replace ("Northern ", "N. ");
+        countryName.replace ("South ", "S. ");
+        countryName.replace ("East ", "E. ");
+        countryName.replace ("Eastern ", "E. ");
+        countryName.replace ("West ", "W. ");
+        countryName.replace ("Western ", "W. ");
+        countryName.replace ("Central ", "C. ");
+        countryName.replace (" and ", " & ");
+        countryName.replace ("Republic", "Rep.");
+        countryName.replace ("United States", "U.S.A.");
+        countryName.replace ("Fed. Rep. of ", "");
+        countryName.replace ("French ", "Fr.");
+        countryName.replace ("Asiatic", "AS");
+        countryName.replace ("European", "EU");
+        countryName.replace ("African", "AF");
+        t1 += countryName;
+    }
+}
+
+void DisplayText::displayDecodedText(DecodedText decodedText, QString myCall,
+                                     bool displayDXCCEntity, LogBook logBook,
+                                     QColor color_CQ, QColor color_MyCall,
+                                     QColor color_DXCC, QColor color_NewCall)
+{
+    QString bg="white";
+    bool CQcall = false;
+    if (decodedText.string ().contains (" CQ ") > 0 || decodedText.string ().contains (" CQ DX "))
+    {
+        CQcall = true;
+        bg=color_CQ.name();
+    }
+    if (myCall != "" and (
+                          decodedText.indexOf (" " + myCall + " ") >= 0
+                          or decodedText.indexOf (" " + myCall + "/") >= 0
+                          or decodedText.indexOf ("/" + myCall + " ") >= 0
+                          ))
+      bg=color_MyCall.name();
+
+    // if enabled add the DXCC entity and B4 status to the end of the preformated text line t1
+    if (displayDXCCEntity && CQcall)
+        _appendDXCCWorkedB4(/*mod*/decodedText,bg,logBook,color_CQ,
+                            color_DXCC,color_NewCall);
+
+    _insertText(decodedText.string(),bg);
+}
+
+
+void DisplayText::displayTransmittedText(QString text, QString modeTx, qint32 txFreq,
+                                         QColor color_TxMsg)
+{
+    QString bg=color_TxMsg.name();
+    QString t1=" @ ";
+    if(modeTx=="JT65") t1=" # ";
+    QString t2;
+    t2.sprintf("%4d",txFreq);
+    QString t = QDateTime::currentDateTimeUtc().toString("hhmm") + \
+        "  Tx      " + t2 + t1 + text;   // The position of the 'Tx' is searched for in DecodedText and in MainWindow.  Not sure if thats required anymore? VK3ACF
+
+    _insertText(t,bg);
 }
diff --git a/displaytext.h b/displaytext.h
index c07f00e..7bca6a0 100644
--- a/displaytext.h
+++ b/displaytext.h
@@ -1,22 +1,41 @@
+// -*- Mode: C++ -*-
 #ifndef DISPLAYTEXT_H
 #define DISPLAYTEXT_H
 
-#include <QTextBrowser>
+#include <QTextEdit>
+#include "logbook/logbook.h"
+#include "decodedtext.h"
 
-class DisplayText : public QTextBrowser
+
+class DisplayText : public QTextEdit
 {
     Q_OBJECT
 public:
     explicit DisplayText(QWidget *parent = 0);
 
+    void setContentFont (QFont const&);
+    void insertLineSpacer(QString const&);
+    void displayDecodedText(DecodedText decodedText, QString myCall, bool displayDXCCEntity,
+                            LogBook logBook, QColor color_CQ, QColor color_MyCall,
+                            QColor color_DXCC, QColor color_NewCall);
+    void displayTransmittedText(QString text, QString modeTx, qint32 txFreq,
+                                QColor color_TxMsg);
+
 signals:
-  void selectCallsign(bool shift, bool ctrl);
+    void selectCallsign(bool shift, bool ctrl);
 
 public slots:
 
+
 protected:
-  void mouseDoubleClickEvent(QMouseEvent *e);
+    void mouseDoubleClickEvent(QMouseEvent *e);
+
+private:
+    void _insertText(const QString text, const QString bg);
+    void _appendDXCCWorkedB4(/*mod*/DecodedText& t1, QString &bg, LogBook logBook,
+                 QColor color_CQ, QColor color_DXCC, QColor color_NewCall);
 
+  QTextCharFormat m_charFormat;
 };
 
 #endif // DISPLAYTEXT_H
diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt
new file mode 100644
index 0000000..ce3fb74
--- /dev/null
+++ b/doc/CMakeLists.txt
@@ -0,0 +1,163 @@
+set (common_SRCS
+  common/communication.adoc
+  common/license.adoc
+  common/links.adoc
+  )
+
+set (UG_SRCS
+  user_guide/acknowledgements.adoc
+  user_guide/install-from-source.adoc
+  user_guide/rig-config-drake.adoc
+  user_guide/settings-radio.adoc
+  user_guide/compiling.adoc
+  user_guide/install-linux.adoc
+  user_guide/rig-config-elecraft.adoc
+  user_guide/settings-reporting.adoc
+  user_guide/config-details.adoc
+  user_guide/install-mac.adoc
+  user_guide/rig-config-flexrad.adoc
+  user_guide/settings-txmacros.adoc
+  user_guide/controls-functions-center.adoc
+  user_guide/install-windows.adoc
+  user_guide/rig-config-icom.adoc
+  user_guide/system-requirements.adoc
+  user_guide/controls-functions-left.adoc
+  user_guide/introduction.adoc
+  user_guide/rig-config-kenwood.adoc
+  user_guide/transceiver-setup.adoc
+  user_guide/controls-functions-main-window.adoc
+  user_guide/jt65-jt9-differences.adoc
+  user_guide/rig-config-main.adoc
+  user_guide/tutorial-example1.adoc
+  user_guide/controls-functions-menus.adoc
+  user_guide/jt65-protocol.adoc
+  user_guide/rig-config-softrock.adoc
+  user_guide/tutorial-example2.adoc
+  user_guide/controls-functions-messages.adoc
+  user_guide/jt9-protocol.adoc
+  user_guide/rig-config-template.adoc
+  user_guide/tutorial-main-window.adoc
+  user_guide/controls-functions-status-bar.adoc
+  user_guide/make-qso.adoc
+  user_guide/rig-config-tentec.adoc
+  user_guide/tutorial-wide-graph-settings.adoc
+  user_guide/controls-functions-wide-graph.adoc
+  user_guide/platform-dependencies.adoc
+  user_guide/rig-config-yaesu.adoc
+  user_guide/tx-rx.adoc
+  user_guide/coop-prgrms.adoc
+  user_guide/rig-config-adat.adoc
+  user_guide/settings-audio.adoc
+  user_guide/utilities.adoc
+  user_guide/faq.adoc
+  user_guide/rig-config-alinco.adoc
+  user_guide/settings-frequencies.adoc
+  user_guide/wsjtx-main.adoc
+  user_guide/font-sizes.adoc
+  user_guide/rig-config-aor.adoc
+  user_guide/settings-general.adoc
+  user_guide/cooperating-programs.adoc
+  user_guide/logging.adoc
+  user_guide/settings-colors.adoc
+  )
+
+set (UG_IMGS
+  user_guide/images/130610_2343-wav-80.png
+  user_guide/images/freemsg.png
+  user_guide/images/misc-main-ui.png
+  user_guide/images/colors.png
+  user_guide/images/status-bar-a.png
+  user_guide/images/MacAppMenu.png
+  user_guide/images/help-menu.png
+  user_guide/images/mode-menu.png
+  user_guide/images/r4148-txmac-ui.png
+  user_guide/images/traditional-msg-box.png
+  user_guide/images/RadioTab.png
+  user_guide/images/keyboard-shortcuts.png
+  user_guide/images/new-msg-box.png
+  user_guide/images/save-menu.png
+  user_guide/images/tx-macros.png
+  user_guide/images/band-settings.png
+  user_guide/images/log-qso.png
+  user_guide/images/r3666-config-screen-80.png
+  user_guide/images/settings-audio.png
+  user_guide/images/view-menu.png
+  user_guide/images/decode-menu.png
+  user_guide/images/main-ui-1.5.png
+  user_guide/images/r3666-main-ui-80.png
+  user_guide/images/settings-ui.png
+  user_guide/images/wide-graph-controls.png
+  user_guide/images/decodes.png
+  user_guide/images/main-ui-controls.png
+  user_guide/images/reporting.png
+  user_guide/images/setup-menu.png
+  user_guide/images/file-menu.png
+  user_guide/images/misc-controls-center.png
+  user_guide/images/r4148-freq-ui.png
+  user_guide/images/special-mouse-commands.png
+  user_guide/images/psk-reporter.png
+  user_guide/images/jtalert.png
+)
+
+find_package (PythonInterp 2.4 REQUIRED)
+if (PYTHON_VERSION_STRING VERSION_GREATER 2.9.9)
+  message (FATAL_ERROR "The asciidoc package requires a Python version less than 3
+
+Use CMAKE_PREFIX_PATH to point to an earlier version or install one,
+you can also skip building the documentation by switching the option
+WSJT_GENERATE_DOCS to OFF.")
+endif (PYTHON_VERSION_STRING VERSION_GREATER 2.9.9)
+
+find_program (ASCIIDOC_EXECUTABLE NAMES asciidoc asciidoc.py)
+if (NOT ASCIIDOC_EXECUTABLE)
+  message (FATAL_ERROR "Asciidoc is required to build the documentation
+
+Building the documenation may optionally be tured off by setting the CMake
+option WSJT_GENERATE_DOCS to OFF.")
+endif (NOT ASCIIDOC_EXECUTABLE)
+
+include (CMakeParseArguments)
+
+# generate an HTML document from asciidoc text files(s)
+#
+# HTML - variable for output file ${CMAKE_CURRENT_BINARY_DIR}/`$basename ${SOURCE}`.html
+# SOURCE - top level asciidoc file
+# ASCIIDOC_OPTIONS - asciidoc command options
+# DEPENDS - dependent files
+function (html_document)
+  cmake_parse_arguments (args "" "SOURCE;HTML" "ASCIIDOC_OPTIONS;DEPENDS" ${ARGN})
+  get_filename_component (_output_name_we ${args_SOURCE} NAME_WE)
+  get_filename_component (_path ${args_SOURCE} PATH)
+  set (_doc_file ${CMAKE_CURRENT_BINARY_DIR}/${_output_name_we}.html)
+  add_custom_command (
+    OUTPUT ${_doc_file}
+    WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/${path}
+    COMMAND ${PYTHON_EXECUTABLE} ARGS ${ASCIIDOC_EXECUTABLE} ${args_ASCIIDOC_OPTIONS} --out-file=${CMAKE_CURRENT_BINARY_DIR}/${_output_name_we}.html ${args_SOURCE}
+    DEPENDS ${args_DEPENDS}
+    COMMENT "Generating ${_doc_file}"
+    )
+  set (${args_HTML} ${_doc_file} PARENT_SCOPE)
+endfunction (html_document)
+
+configure_file (wsjtx.conf.in wsjtx.conf.out)
+# copy the file to the final location only if the generated output
+# changes reduces needless rebuilds
+execute_process (
+  WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+  COMMAND ${CMAKE_COMMAND} -E copy_if_different wsjtx.conf.out wsjtx.conf
+  )
+
+html_document(
+  HTML user_guide
+  SOURCE user_guide/wsjtx-main.adoc
+  ASCIIDOC_OPTIONS -a data-uri -a toc2 -a max-width=1024px --conf-file=${CMAKE_CURRENT_BINARY_DIR}/wsjtx.conf --backend=xhtml11 --theme wsjt
+  DEPENDS ${common_SRCS} ${UG_SRCS} ${UG_IMGS} wsjtx.conf.in theme/wsjt/wsjt.css
+  )
+add_custom_target (docs ALL DEPENDS ${user_guide})
+
+install (FILES
+  ${user_guide}
+  DESTINATION ${WSJT_SHARE_DESTINATION}/${WSJT_DOC_DESTINATION}
+  RENAME ${PROJECT_MANUAL}
+  #COMPONENT runtime
+  )
diff --git a/doc/README b/doc/README
new file mode 100644
index 0000000..9737bc7
--- /dev/null
+++ b/doc/README
@@ -0,0 +1,51 @@
+This folder  contains the sources  of WSJT-X documentation.   To build
+these you will need the asciidoc and Python v2 tools installed.
+
+If you do not wish to build  the documentation, it is possible to skip
+this  directory  in the  WSJT-X  build  by  setting the  CMake  option
+WSJT_GENERATE_DOCS to OFF in your build tree.
+
+
+On Linux
+========
+
+You will probably have these installed already if you are building the
+WSJT-X  manpages,  if you  are  not  you  will  just need  to  install
+asciidoc:
+
+ sudo apt-get install asciidoc
+
+or
+
+ sudo yum install asciidoc
+
+or whatever your distribution and package management requires.
+
+
+On Mac OS X
+===========
+
+I recommend MacPorts:
+
+ sudo port install asciidoc
+
+
+On Windows
+==========
+
+The asciidoc  tool is a  Python script so you  will need to  install a
+version of  Python v2. If  you already have  Python v3 as  the default
+Python interpreter on your system  then download and install Python v2
+(probably v2.7.x) but  adjust the installer options so as  not to make
+it  the  default  system  Python   interpreter,  this  is  normally  a
+configuration option in the MSI installer.
+
+The current  version of asciidoc (8.6.9)  is broken on Windows  so you
+will need to get the latest development version:
+
+ download https://github.com/asciidoc/asciidoc/archive/master.zip
+
+and unzip  it somewhere like  C:\Tools then you  will need to  add the
+path to asciidoc and possibly Python  v2 to your CMake tool chain file
+for building WSJT-X. The directory  containing asciidoc.py needs to be
+included in the CMAKE_PREFIX_PATH variable.
diff --git a/doc/common/communication.adoc b/doc/common/communication.adoc
new file mode 100644
index 0000000..ba9c32e
--- /dev/null
+++ b/doc/common/communication.adoc
@@ -0,0 +1,17 @@
+The following are established communication channels for the WSJT Group.
+For updates and other information on the continuing development of _WSJT_,
+_MAP65_, _WSPR_, _WSPR-X_, and _WSJT-X_ you are invited to subscribe to the
+{dev_mail_list}. 
+
+.General Information
+* Main Site: {homepage}
+* Development Site: {projsummary}
+
+.Development Related
+* Project Manager, email: {joe_taylor}
+* Development Email: {devmail1}
+* Development Mailing List (join): {dev_mail_list}
+* Repository Updates, (join): {dev_mail_svn}
+
+.Community Related
+* Discussion Board: {wsjt_yahoo_group}
\ No newline at end of file
diff --git a/doc/common/license.adoc b/doc/common/license.adoc
new file mode 100755
index 0000000..b540dfb
--- /dev/null
+++ b/doc/common/license.adoc
@@ -0,0 +1,15 @@
+include::./links.adoc[]
+_{prog}_ is free software: you can redistribute it and/or modify
+under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+_{prog}_ 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 documentation. If not, see {gnu_gpl}.
+
+Copyright (C) 2001-2015 Joseph H Taylor, Jr, {joe_taylor}.
diff --git a/doc/common/links.adoc b/doc/common/links.adoc
new file mode 100644
index 0000000..d028771
--- /dev/null
+++ b/doc/common/links.adoc
@@ -0,0 +1,111 @@
+////
+Link file to hold all links
+File Location: ./doc/common/links.adoc
+Usage example: include::../common/links.adoc[]
+Syntax: [link-id] [link] [displayed test]
+
+Example:
+:pskreporter: http://pskreporter.info/pskmap.html[PSK Reporter]
+
+[link-id] = :pskreporter:
+[link] http://pskreporter.info/pskmap.html
+[displayed test] PSK Reporter
+
+Perform searches from the doc root directory: C:\JTSDK-DOC\doc
+Search: grep -rl --exclude-dir="*\.svn" {pskreporter} .
+		grep -rl --exclude-dir="*\.svn" PSK Reporter .
+		grep -rl --exclude-dir="*\.svn" {devsvn} .
+        grep -rl --exclude-dir="*\.svn" {kvasd} .
+        grep -rl --exclude-dir="*\.svn" {ntpsetup} .
+
+Include links.adoc: grep -rl --exclude-dir="*\.svn" pskreporter .
+Exclude links.adoc: grep -rl --exclude-dir="*\.svn" {pskreporter} .
+
+Note(s):
+a). Don't forget a space then "." at the end.
+b). To include links.adoc file itself, remove the brackets {} from
+the pattern search:
+c). Look at each of the files listed to ensure the [displayed test]
+still makes sense in the caption. If not, just add another link.
+d). Edit lines as needed. Keeping them in alphabetic order help see dupes.
+
+////
+
+// General URL's
+//:launchpadac6sl: https://launchpad.net/~jnogatch/+archive/wsjtx[WSJT-X Linux Packages]
+:asciidoc_cheatsheet: http://powerman.name/doc/asciidoc[AsciiDoc Cheatsheet]
+:asciidoc_help: http://www.methods.co.nz/asciidoc/userguide.html[AsciiDoc User Guide]
+:asciidoc_questions: http://www.methods.co.nz/asciidoc/faq.html[AsciiDoc FAQ]
+:asciidoc_syntax: http://xpt.sourceforge.net/techdocs/nix/tool/asciidoc-syn/ascs01-AsciiDocMarkupSyntaxQuickSummary/single/[AsciiDoc Syntax]
+:asciidoctor_style: http://asciidoctor.org/docs/asciidoc-writers-guide/#delimited-blocks[AsciiDoctor Styles Guide]
+:asciidoctor_syntax: http://asciidoctor.org/docs/asciidoc-writers-guide/#delimited-blocks[AsciiDoctor Syntax Guide]
+:cc_by_sa: http://creativecommons.org/licenses/by-sa/3.0/[Commons Attribution-ShareAlike 3.0 Unported License]
+:debian32: http://physics.princeton.edu/pulsar/K1JT/wsjtx_{VERSION}_i386.deb[wsjtx_{VERSION}_i386.deb]
+:debian64: http://physics.princeton.edu/pulsar/K1JT/wsjtx_{VERSION}_amd64.deb[wsjtx_{VERSION}_amd64.deb]
+:debian: http://www.debian.org/[Debian]
+:dev_guide: http://www.physics.princeton.edu/pulsar/K1JT/wsjtx-doc/wsjt-dev-guide.html[Dev-Guide]
+:devsvn1: http://sourceforge.net/p/wsjt/wsjt/HEAD/tree/[Devel-SVN]
+:devsvn: http://sourceforge.net/p/wsjt/wsjt/HEAD/tree/[SourceForge]
+:dimension4: http://www.thinkman.com/dimension4/[Dimension4]
+:download: http://physics.princeton.edu/pulsar/K1JT/wsjtx.html[Download Page]
+:dxatlas: http://www.dxatlas.com/[Afreet Software, Inc.]
+:dxlcommander: http://www.dxlabsuite.com/commander/[Commander]
+:dxlsuite: http://www.dxlabsuite.com/[DX Lab Suite]
+:fedora32: http://physics.princeton.edu/pulsar/K1JT/wsjtx-{VERSION}-i686.rpm[wsjtx-{VERSION}-i686.rpm]
+:fedora64: http://physics.princeton.edu/pulsar/K1JT/wsjtx-{VERSION}-x86_64.rpm[wsjtx-{VERSION}-x86_64.rpm]
+:fmt_arrl: http://www.arrl.org/frequency-measuring-test[ARRL FMT Info]
+:fmt_group: https://groups.yahoo.com/neo/groups/FMT-nuts/info[FMT Group]
+:fmt_k5cm: http://www.k5cm.com/[FMT Event Info]
+:gnu_gpl: http://www.gnu.org/licenses/gpl-3.0.txt[GNU General Public License]
+:homepage: http://physics.princeton.edu/pulsar/K1JT/[WSJT Home Page]
+:hrd: http://www.hrdsoftwarellc.com/[Ham Radio Deluxe]
+:jt65protocol: http://physics.princeton.edu/pulsar/K1JT/JT65.pdf[QEX]
+:jtalert: http://hamapps.com[JT-ALERT-X]
+:kvasd-installer: http://physics.princeton.edu/pulsar/K1JT/kv-installer.txt[here]
+:launchpadki7mt: https://launchpad.net/~ki7mt[KI7MT PPA's]
+:msys_url: http://sourceforge.net/projects/mingwbuilds/files/external-binary-packages/[MSYS Download]
+:ntpsetup: http://www.satsignal.eu/ntp/setup.html[Network Time Protocol Setup]
+:osx_instructions: http://physics.princeton.edu/pulsar/K1JT/OSX_Readme[here]
+:ppa: http://en.wikipedia.org/wiki/Personal_Package_Archive[PPA]
+:projsummary: http://sourceforge.net/projects/wsjt/[Project Summary]
+:pskreporter: http://pskreporter.info/pskmap.html[PSK Reporter]
+:sourceforge: https://sourceforge.net/user/registration[SourceForge]
+:sourceforge-jtsdk: https://sourceforge.net/projects/jtsdk[SourceForge JTSDK]
+:ubuntu_sdk: https://launchpad.net/~ubuntu-sdk-team/+archive/ppa[Ubuntu SDK Notice]
+:wsjt_yahoo_group: https://groups.yahoo.com/neo/groups/wsjtgroup/info[WSJT Group]
+:wsjtx: http://physics.princeton.edu/pulsar/K1JT/wsjtx.html[WSJT-X]
+:wspr0_guide: http://www.physics.princeton.edu/pulsar/K1JT/WSPR0_Instructions.TXT[WSPR0 Guide]
+:wspr: http://physics.princeton.edu/pulsar/K1JT/wspr.html[WSPR Home Page]
+:wsprnet: http://wsprnet.org/drupal/[WSPRnet]
+:wsprnet_activity: http://wsprnet.org/drupal/wsprnet/activity[WSPRnet Activity page]
+
+// Download Links
+:cty_dat: http://www.country-files.com/cty/[here]
+:hamlib3: https://dl.dropboxusercontent.com/u/4192709/Hamlib-integration-wsjtx.zip[Download]
+:jtsdk_doc: http://physics.princeton.edu/pulsar/K1JT/JTSDK-DOC.exe[Download]
+:jtsdk_installer: http://sourceforge.net/projects/jtsdk/files/win32/2.0.0/JTSDK-2.0.0-B2-Win32.exe/download[Download]
+:jtsdk_omnirig: http://sourceforge.net/projects/jtsdk/files/win32/2.0.0/base/contrib/OmniRig.zip/download[Download]
+:jtsdk_py: http://physics.princeton.edu/pulsar/K1JT/JTSDK-PY.exe[Download]
+:jtsdk_qt: http://physics.princeton.edu/pulsar/K1JT/JTSDK-QT.exe[Download]
+:jtsdk_vcredist: http://sourceforge.net/projects/jtsdk/files/win32/2.0.0/base/contrib/vcredist_x86.exe/download[Download]
+:kvasd: http://physics.princeton.edu/pulsar/K1JT/kvasd[kvasd]
+:nh6z: http://www.nh6z.net/Amatuer_Radio_Station_NH6Z/Other_Peoples_Software.html[here]
+:omnirig: http://www.dxatlas.com/OmniRig/Files/OmniRig.zip[Download]
+:osx: http://physics.princeton.edu/pulsar/K1JT/wsjtx-{VERSION}-Darwin.dmg[wsjtx-{VERSION}-Darwin.dmg]
+:svn: http://subversion.apache.org/packages.html#windows[Subversion]
+:win32: http://physics.princeton.edu/pulsar/K1JT/wsjtx-{VERSION}-win32.exe[wsjtx-{VERSION}-win32.exe]
+:wsjt_svn: http://sourceforge.net/p/wsjt/wsjt/HEAD/tree/[here]
+:wspr_code: http://physics.princeton.edu/pulsar/K1JT/WSPRcode.exe[WSPRcode.exe]
+:wspr_svn: http://sourceforge.net/p/wsjt/wsjt/HEAD/tree/branches/wspr/[here]
+:kvasd_installer: http://sourceforge.net/projects/wsjt/files/kvasd-installer/kvasd-installer-1.12.14/kvasd-installer-1.12.14.tar.gz/download[kvasd-installer]
+
+// MAIL-TO links
+:alex_efros: mailto:powerman at powerman.name[Alex Efros]
+:bill_somerville: mailto:g4wjs -at- c l a s s d e s i g n -dot- com [G4WJS]
+:dev_mail_list: http://sourceforge.net/mailarchive/forum.php?forum_name=wsjt-devel[WSJT Developers Email List]
+:dev_mail_svn: https://sourceforge.net/auth/subscriptions/[WSJT SVN Archives]
+:devmail: mailto:wsjt-devel at lists.sourceforge.net[wsjt-devel]
+:devmail1: mailto:wsjt-devel at lists.sourceforge.net[Post Message]
+:greg_beam: mailto:ki7mt at yahoo.com[KI7MT]
+:joe_taylor: mailto:joe at princeton.edu[K1JT]
+:stuart_rackman: mailto:srackham at gmail.com[Stuart Rackham]
diff --git a/doc/theme/wsjt/wsjt.css b/doc/theme/wsjt/wsjt.css
new file mode 100644
index 0000000..ab2ddb4
--- /dev/null
+++ b/doc/theme/wsjt/wsjt.css
@@ -0,0 +1,546 @@
+/* Below  is the content  of the  asciidoc.css file from  the asciidoc
+   distribution, the  WSJT theme additions  are at the bottom  of this
+   file */
+
+/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
+
+/* Default font. */
+body {
+  font-family: Georgia,serif;
+}
+
+/* Title font. */
+h1, h2, h3, h4, h5, h6,
+div.title, caption.title,
+thead, p.table.header,
+#toctitle,
+#author, #revnumber, #revdate, #revremark,
+#footer {
+  font-family: Arial,Helvetica,sans-serif;
+}
+
+body {
+  margin: 1em 5% 1em 5%;
+}
+
+a {
+  color: blue;
+  text-decoration: underline;
+}
+a:visited {
+  color: fuchsia;
+}
+
+em {
+  font-style: italic;
+  color: navy;
+}
+
+strong {
+  font-weight: bold;
+  color: #083194;
+}
+
+h1, h2, h3, h4, h5, h6 {
+  color: #527bbd;
+  margin-top: 1.2em;
+  margin-bottom: 0.5em;
+  line-height: 1.3;
+}
+
+h1, h2, h3 {
+  border-bottom: 2px solid silver;
+}
+h2 {
+  padding-top: 0.5em;
+}
+h3 {
+  float: left;
+}
+h3 + * {
+  clear: left;
+}
+h5 {
+  font-size: 1.0em;
+}
+
+div.sectionbody {
+  margin-left: 0;
+}
+
+hr {
+  border: 1px solid silver;
+}
+
+p {
+  margin-top: 0.5em;
+  margin-bottom: 0.5em;
+}
+
+ul, ol, li > p {
+  margin-top: 0;
+}
+ul > li     { color: #aaa; }
+ul > li > * { color: black; }
+
+.monospaced, code, pre {
+  font-family: "Courier New", Courier, monospace;
+  font-size: inherit;
+  color: navy;
+  padding: 0;
+  margin: 0;
+}
+pre {
+  white-space: pre-wrap;
+}
+
+#author {
+  color: #527bbd;
+  font-weight: bold;
+  font-size: 1.1em;
+}
+#email {
+}
+#revnumber, #revdate, #revremark {
+}
+
+#footer {
+  font-size: small;
+  border-top: 2px solid silver;
+  padding-top: 0.5em;
+  margin-top: 4.0em;
+}
+#footer-text {
+  float: left;
+  padding-bottom: 0.5em;
+}
+#footer-badges {
+  float: right;
+  padding-bottom: 0.5em;
+}
+
+#preamble {
+  margin-top: 1.5em;
+  margin-bottom: 1.5em;
+}
+div.imageblock, div.exampleblock, div.verseblock,
+div.quoteblock, div.literalblock, div.listingblock, div.sidebarblock,
+div.admonitionblock {
+  margin-top: 1.0em;
+  margin-bottom: 1.5em;
+}
+div.admonitionblock {
+  margin-top: 2.0em;
+  margin-bottom: 2.0em;
+  margin-right: 10%;
+  color: #606060;
+}
+
+div.content { /* Block element content. */
+  padding: 0;
+}
+
+/* Block element titles. */
+div.title, caption.title {
+  color: #527bbd;
+  font-weight: bold;
+  text-align: left;
+  margin-top: 1.0em;
+  margin-bottom: 0.5em;
+}
+div.title + * {
+  margin-top: 0;
+}
+
+td div.title:first-child {
+  margin-top: 0.0em;
+}
+div.content div.title:first-child {
+  margin-top: 0.0em;
+}
+div.content + div.title {
+  margin-top: 0.0em;
+}
+
+div.sidebarblock > div.content {
+  background: #ffffee;
+  border: 1px solid #dddddd;
+  border-left: 4px solid #f0f0f0;
+  padding: 0.5em;
+}
+
+div.listingblock > div.content {
+  border: 1px solid #dddddd;
+  border-left: 5px solid #f0f0f0;
+  background: #f8f8f8;
+  padding: 0.5em;
+}
+
+div.quoteblock, div.verseblock {
+  padding-left: 1.0em;
+  margin-left: 1.0em;
+  margin-right: 10%;
+  border-left: 5px solid #f0f0f0;
+  color: #888;
+}
+
+div.quoteblock > div.attribution {
+  padding-top: 0.5em;
+  text-align: right;
+}
+
+div.verseblock > pre.content {
+  font-family: inherit;
+  font-size: inherit;
+}
+div.verseblock > div.attribution {
+  padding-top: 0.75em;
+  text-align: left;
+}
+/* DEPRECATED: Pre version 8.2.7 verse style literal block. */
+div.verseblock + div.attribution {
+  text-align: left;
+}
+
+div.admonitionblock .icon {
+  vertical-align: top;
+  font-size: 1.1em;
+  font-weight: bold;
+  text-decoration: underline;
+  color: #527bbd;
+  padding-right: 0.5em;
+}
+div.admonitionblock td.content {
+  padding-left: 0.5em;
+  border-left: 3px solid #dddddd;
+}
+
+div.exampleblock > div.content {
+  border-left: 3px solid #dddddd;
+  padding-left: 0.5em;
+}
+
+div.imageblock div.content { padding-left: 0; }
+span.image img { border-style: none; vertical-align: text-bottom; }
+a.image:visited { color: white; }
+
+dl {
+  margin-top: 0.8em;
+  margin-bottom: 0.8em;
+}
+dt {
+  margin-top: 0.5em;
+  margin-bottom: 0;
+  font-style: normal;
+  color: navy;
+}
+dd > *:first-child {
+  margin-top: 0.1em;
+}
+
+ul, ol {
+    list-style-position: outside;
+}
+ol.arabic {
+  list-style-type: decimal;
+}
+ol.loweralpha {
+  list-style-type: lower-alpha;
+}
+ol.upperalpha {
+  list-style-type: upper-alpha;
+}
+ol.lowerroman {
+  list-style-type: lower-roman;
+}
+ol.upperroman {
+  list-style-type: upper-roman;
+}
+
+div.compact ul, div.compact ol,
+div.compact p, div.compact p,
+div.compact div, div.compact div {
+  margin-top: 0.1em;
+  margin-bottom: 0.1em;
+}
+
+tfoot {
+  font-weight: bold;
+}
+td > div.verse {
+  white-space: pre;
+}
+
+div.hdlist {
+  margin-top: 0.8em;
+  margin-bottom: 0.8em;
+}
+div.hdlist tr {
+  padding-bottom: 15px;
+}
+dt.hdlist1.strong, td.hdlist1.strong {
+  font-weight: bold;
+}
+td.hdlist1 {
+  vertical-align: top;
+  font-style: normal;
+  padding-right: 0.8em;
+  color: navy;
+}
+td.hdlist2 {
+  vertical-align: top;
+}
+div.hdlist.compact tr {
+  margin: 0;
+  padding-bottom: 0;
+}
+
+.comment {
+  background: yellow;
+}
+
+.footnote, .footnoteref {
+  font-size: 0.8em;
+}
+
+span.footnote, span.footnoteref {
+  vertical-align: super;
+}
+
+#footnotes {
+  margin: 20px 0 20px 0;
+  padding: 7px 0 0 0;
+}
+
+#footnotes div.footnote {
+  margin: 0 0 5px 0;
+}
+
+#footnotes hr {
+  border: none;
+  border-top: 1px solid silver;
+  height: 1px;
+  text-align: left;
+  margin-left: 0;
+  width: 20%;
+  min-width: 100px;
+}
+
+div.colist td {
+  padding-right: 0.5em;
+  padding-bottom: 0.3em;
+  vertical-align: top;
+}
+div.colist td img {
+  margin-top: 0.3em;
+}
+
+ at media print {
+  #footer-badges { display: none; }
+}
+
+#toc {
+  margin-bottom: 2.5em;
+}
+
+#toctitle {
+  color: #527bbd;
+  font-size: 1.1em;
+  font-weight: bold;
+  margin-top: 1.0em;
+  margin-bottom: 0.1em;
+}
+
+div.toclevel0, div.toclevel1, div.toclevel2, div.toclevel3, div.toclevel4 {
+  margin-top: 0;
+  margin-bottom: 0;
+}
+div.toclevel2 {
+  margin-left: 2em;
+  font-size: 0.9em;
+}
+div.toclevel3 {
+  margin-left: 4em;
+  font-size: 0.9em;
+}
+div.toclevel4 {
+  margin-left: 6em;
+  font-size: 0.9em;
+}
+
+span.aqua { color: aqua; }
+span.black { color: black; }
+span.blue { color: blue; }
+span.fuchsia { color: fuchsia; }
+span.gray { color: gray; }
+span.green { color: green; }
+span.lime { color: lime; }
+span.maroon { color: maroon; }
+span.navy { color: navy; }
+span.olive { color: olive; }
+span.purple { color: purple; }
+span.red { color: red; }
+span.silver { color: silver; }
+span.teal { color: teal; }
+span.white { color: white; }
+span.yellow { color: yellow; }
+
+span.aqua-background { background: aqua; }
+span.black-background { background: black; }
+span.blue-background { background: blue; }
+span.fuchsia-background { background: fuchsia; }
+span.gray-background { background: gray; }
+span.green-background { background: green; }
+span.lime-background { background: lime; }
+span.maroon-background { background: maroon; }
+span.navy-background { background: navy; }
+span.olive-background { background: olive; }
+span.purple-background { background: purple; }
+span.red-background { background: red; }
+span.silver-background { background: silver; }
+span.teal-background { background: teal; }
+span.white-background { background: white; }
+span.yellow-background { background: yellow; }
+
+span.big { font-size: 2em; }
+span.small { font-size: 0.6em; }
+
+span.underline { text-decoration: underline; }
+span.overline { text-decoration: overline; }
+span.line-through { text-decoration: line-through; }
+
+div.unbreakable { page-break-inside: avoid; }
+
+
+/*
+ * xhtml11 specific
+ *
+ * */
+
+div.tableblock {
+  margin-top: 1.0em;
+  margin-bottom: 1.5em;
+}
+div.tableblock > table {
+  border: 3px solid #527bbd;
+}
+thead, p.table.header {
+  font-weight: bold;
+  color: #527bbd;
+}
+p.table {
+  margin-top: 0;
+}
+/* Because the table frame attribute is overriden by CSS in most browsers. */
+div.tableblock > table[frame="void"] {
+  border-style: none;
+}
+div.tableblock > table[frame="hsides"] {
+  border-left-style: none;
+  border-right-style: none;
+}
+div.tableblock > table[frame="vsides"] {
+  border-top-style: none;
+  border-bottom-style: none;
+}
+
+
+/*
+ * html5 specific
+ *
+ * */
+
+table.tableblock {
+  margin-top: 1.0em;
+  margin-bottom: 1.5em;
+}
+thead, p.tableblock.header {
+  font-weight: bold;
+  color: #527bbd;
+}
+p.tableblock {
+  margin-top: 0;
+}
+table.tableblock {
+  border-width: 3px;
+  border-spacing: 0px;
+  border-style: solid;
+  border-color: #527bbd;
+  border-collapse: collapse;
+}
+th.tableblock, td.tableblock {
+  border-width: 1px;
+  padding: 4px;
+  border-style: solid;
+  border-color: #527bbd;
+}
+
+table.tableblock.frame-topbot {
+  border-left-style: hidden;
+  border-right-style: hidden;
+}
+table.tableblock.frame-sides {
+  border-top-style: hidden;
+  border-bottom-style: hidden;
+}
+table.tableblock.frame-none {
+  border-style: hidden;
+}
+
+th.tableblock.halign-left, td.tableblock.halign-left {
+  text-align: left;
+}
+th.tableblock.halign-center, td.tableblock.halign-center {
+  text-align: center;
+}
+th.tableblock.halign-right, td.tableblock.halign-right {
+  text-align: right;
+}
+
+th.tableblock.valign-top, td.tableblock.valign-top {
+  vertical-align: top;
+}
+th.tableblock.valign-middle, td.tableblock.valign-middle {
+  vertical-align: middle;
+}
+th.tableblock.valign-bottom, td.tableblock.valign-bottom {
+  vertical-align: bottom;
+}
+
+
+/*
+ * manpage specific
+ *
+ * */
+
+body.manpage h1 {
+  padding-top: 0.5em;
+  padding-bottom: 0.5em;
+  border-top: 2px solid silver;
+  border-bottom: 2px solid silver;
+}
+body.manpage h2 {
+  border-style: none;
+}
+body.manpage div.sectionbody {
+  margin-left: 3em;
+}
+
+ at media print {
+  body.manpage div#toc { display: none; }
+}
+
+
+/* WSJT styling  overriding the above which is the  content of the
+   standard asciidoc.css style sheet */
+body {
+  font-family: Arial, Hevetica, sans-serif;
+}
+
+h1, h2, h3, h4, h5, h6 {
+  font-family: Georgia, "Times New Roman", Times, serif;
+}
+
+a:visited {
+  color: purple;
+}
diff --git a/doc/user_guide/acknowledgements.adoc b/doc/user_guide/acknowledgements.adoc
new file mode 100644
index 0000000..b37b1c5
--- /dev/null
+++ b/doc/user_guide/acknowledgements.adoc
@@ -0,0 +1,24 @@
+// Status=review
+
+Since 2005 the _WSJT_ project (including programs _WSJT_, _MAP65_,
+_WSPR_, _WSJT-X_, and _WSPR-X_) has been ``open source'', with all
+code licensed under the GNU Public License (GPL).  Many users of these
+programs, too numerous to mention here individually, have contributed
+suggestions and advice that have greatly aided the development of
+_WSJT_ and its sister programs.
+
+For _WSJT-X_ in particular, we acknowledge contributions from *AC6SL,
+AE4JY, DJ0OT, G4KLA, G4WJS, K3WYC, KA6MAL, KA9Q, KB1ZMX, KI7MT, KK1D,
+PY2SDR, VK3ACF, VK4BDJ, W4TI, W4TV, and W9MDB*.  Each of these
+amateurs has helped to bring the program’s design, code, and
+documentation to its present state.
+
+Most of the color palettes for the _WSJT-X_ waterfall were copied from
+the excellent, well documented, open-source program _fldigi_, by *W1HKJ*
+and friends.
+
+We use development tools and libraries from many sources.  We
+particularly wish to acknowledge importance of the GNU Compiler
+Collection from the Free Software Foundation, the "clang" compiler
+from LLVM at the University of Illinois, the Qt Project from Digia
+PLC, and the FFTW package by Matteo Frigo and Steven G. Johnson.
diff --git a/doc/user_guide/compiling.adoc b/doc/user_guide/compiling.adoc
new file mode 100644
index 0000000..13a8550
--- /dev/null
+++ b/doc/user_guide/compiling.adoc
@@ -0,0 +1,20 @@
+// Status=review
+// Note to developers. The URL http://developer.berlios.de/projects/wsjt/. is
+// to a very old src version of WSJT 5.7 or so. WSJTX is not listed at all.
+// Also, all the Qt4 stuff is now obsolete, and needs to be updated.
+
+// Web Links
+// Source File is: dev-guide/source/wsjtx-dev/wsjtx-dev.adoc
+// At some point, compiling_wsjtx_linux.html needs a name change to: wsjtx-dev.html
+// These files can only be built on Linux, due to source-highlight being removed
+// From the windows build batch file.
+:dev-guide: http://www.physics.princeton.edu/pulsar/K1JT/wsjtx-doc/wsjt-dev-guide.html[WSJT Developers Guide]
+
+// mail-to links
+
+A Developer's Guide for WSJT and its sister programs is itself under
+development.  The present draft contains full instructions for
+compiling _WSJT-X_ in Linux, and an outline of steps required in
+Windows.  
+
+{dev-guide}
diff --git a/doc/user_guide/config-details.adoc b/doc/user_guide/config-details.adoc
new file mode 100644
index 0000000..8b4234c
--- /dev/null
+++ b/doc/user_guide/config-details.adoc
@@ -0,0 +1,4 @@
+// Status=review
+[[CONFIG_DETAILS]]
+
+Are we here?
diff --git a/doc/user_guide/controls-functions-center.adoc b/doc/user_guide/controls-functions-center.adoc
new file mode 100644
index 0000000..a65784b
--- /dev/null
+++ b/doc/user_guide/controls-functions-center.adoc
@@ -0,0 +1,32 @@
+// Status=review
+
+At the center of the main window are a number of controls used when
+making QSOs:
+
+//.Misc Controls Center
+image::images/misc-controls-center.png[align="center",alt="Misc Controls Center"]
+
+* Check *Tx even* to transmit in even-numbered UTC minutes.  Uncheck
+this box to transmit in the odd minutes.  This selection is made
+automatically when you double-click on a decoded text line, as
+described in the <<TUTORIAL,Basic Operating Tutorial>>.
+
+* The Tx and Rx audio frequencies are usually set automatically by
+double-clicking on decoded text or a signal in the waterfall.  They 
+can also be adjusted with spinner controls. 
+
+* You can force Tx frequency to the current Rx frequency by clicking
+the *Tx<Rx* button, and vice-versa for *Rx<Tx*.  (Copy is from right
+to left.)  Check the box *Lock Tx=Rx* to make the frequencies always
+track one another.  The on-the-air frequency of your lowest JT9 or
+JT65 tone is the sum of dial frequency and audio Tx frequency.
+
+* The *Report* control lets you change a signal report that has been
+inserted automatically. Most reports will fall in the range –26 to +10
+dB.  Remember that JT65 reports saturate at an upper limit of -1
+dB.
+
+IMPORTANT: When signals are close to or above 0 dB, you and your QSO
+partner should probably reduce power.  The WSJT modes are supposed to
+be weak signal modes!
+
diff --git a/doc/user_guide/controls-functions-left.adoc b/doc/user_guide/controls-functions-left.adoc
new file mode 100644
index 0000000..e5b130b
--- /dev/null
+++ b/doc/user_guide/controls-functions-left.adoc
@@ -0,0 +1,41 @@
+// Status=review
+
+Controls related to frequency selection, received audio level, the
+station being called, and date and time are found at lower left of the
+main window:
+
+//.Misc Controls Left
+image::images/misc-main-ui.png[align="center",alt="Mist Menu Items"]
+
+* A drop-down list of frequencies and bands at upper left lets you
+select the operating band and sets dial frequency to a value taken
+from the *Frequencies* tab on the *Settings* window.  If CAT control
+is active the radio's dial frequency will be set accordingly; if not,
+you must tune the radio manually.
+
+* Alternatively, you can enter a frequency (in MHz) or band name in
+recognized ADIF format, for example 630m, 20m, or 70cm.  The band-name
+format works only if a working frequency has been set up on that band,
+in which case the first working frequency on that band is
+selected. 
+
+* If you are using CAT control, a small colored square appears in
+green if the CAT control is activated and functional.  The green
+square contains the character S if the rig is detected to be in
+*Split* mode.  The square becomes red if you have requested CAT
+control but communication with the radio has been lost.
+
+IMPORTANT: Many Icom rigs cannot be queried for split status, current
+VFO or split transmit frequency.  Consequently you should not change
+the current VFO, split status or frequency using controls on the radio
+when using _WSJT-X_.
+
+* If *DX Grid* contains a valid Maidenhead locator, the corresponding
+great-circle azimuth and distance from your location are displayed.
+
+* The program can maintain a database of callsigns and locators for
+future reference.  Click *Add* to insert the present call and locator
+in the database; click *Lookup* to retrieve the locator for a
+previously stored call.  This feature is mainly useful for situations
+in which the number of active stations is modest and reasonably
+stable, such as EME (Earth-Moon-Earth) communication.
diff --git a/doc/user_guide/controls-functions-main-window.adoc b/doc/user_guide/controls-functions-main-window.adoc
new file mode 100644
index 0000000..2c27bcc
--- /dev/null
+++ b/doc/user_guide/controls-functions-main-window.adoc
@@ -0,0 +1,51 @@
+// Status=review
+The following buttons appear just under the decoded text windows on
+the main screen:
+
+//.Main UI Controls
+image::images/main-ui-controls.png[align="left",width=650,alt="Main UI Controls"]
+
+* *Log QSO* raises a dialog window pre-filled with known information
+about a QSO you have nearly completed.  You can edit or add to this
+information before clicking *OK* to log the QSO.  If you check *Prompt
+me to log QSO* on the *Setup* menu, the program will raise the
+confirmation screen automatically when you send a 73 or free-text
+message.
+
+//.Log QSO Window
+image::images/log-qso.png[align="center",alt="Log QSO"]
+
+* *Stop* will terminate normal data acquisition in case you want to
+freeze the waterfall or open and explore a previously recorded audio
+file.
+
+* *Monitor* restarts normal receive operation.  This button is
+highlighted in green when the _WSJT-X_ is receiving.  If you are
+using CAT control, toggling *Monitor* OFF relinquishes control of the
+rig; if *Monitor returns to last used frequency" is selected
+on the *Settings | General* tab, toggling *Monitor* back ON will
+return to the original frequency.
+
+* *Erase* clears the right-hand decoded text window. 
+Double-clicking *Erase* clears both text windows.
+
+* *Decode* tells the program to repeat the decoding procedure at the
+Rx frequency (green marker on waterfall), using the most recently
+completed sequence of received data.  
+
+* *Enable Tx* toggles the program into automatic T/R sequencing mode
+and highlights the button in red.  A transmission will start at
+the beginning of the selected (odd or even) sequence, or immediately
+if appropriate.  A transmission will not be started any later than 24
+s into a UTC minute.
+
+* *Halt Tx* terminates a transmission in progress and disables
+automatic T/R sequencing.
+
+* *Tune* may be used to switch into Tx mode and generate an
+unmodulated carrier at the specified Tx frequency (red marker
+on waterfall).  This process may be useful for adjusting an antenna
+tuner.  The button is highlighted in red while *Tune* is
+active.  Toggle the button a second time to terminate the *Tune*
+process.
+
diff --git a/doc/user_guide/controls-functions-menus.adoc b/doc/user_guide/controls-functions-menus.adoc
new file mode 100644
index 0000000..6ccd11e
--- /dev/null
+++ b/doc/user_guide/controls-functions-menus.adoc
@@ -0,0 +1,46 @@
+// Status=review
+
+Program menus offer many options for configuration and operation.
+Most of the items are self-explanatory; a few additional details are
+provided below.  Keyboard shortcuts for some frequently used menu
+items are listed at the right.
+
+==== WSJT-X menu
+image::images/MacAppMenu.png[align="left",alt="Mac App Menu"]
+
+This menu appears on the Macintosh only. *Settings* appears here,
+labeled as *Preferences*, rather than on the *File* menu.  *About
+WSJT-X* appears here rather than on the *Help* menu.
+
+[[FILE_MENU]]
+==== File menu
+image::images/file-menu.png[align="left",alt="File Menu"]
+
+[[VIEW_MENU]]
+==== View Menu
+image::images/view-menu.png[align="left",alt="View Menu"]
+
+[[MODE_MENU]]
+==== Mode Menu
+image::images/mode-menu.png[align="left",alt="Mode Menu"]
+
+[[DECODE_MENU]]
+==== Decode Menu
+image::images/decode-menu.png[align="left",alt="Decode Menu"]
+
+[[SAVE_MENU]]
+[[SAVE-WAV]]
+==== Save Menu
+image::images/save-menu.png[align="left",alt="Save Menu"]
+
+Choose *Save all* to save received data as audio +.wav+ files.
+*Save decoded* will save only those files containing at least one 
+decoded message.  
+
+[[HELP_MENU]]
+==== Help Menu
+image::images/help-menu.png[align="left",alt="Help Menu"]
+
+image::images/keyboard-shortcuts.png[align="left",alt="Help Menu"]
+
+image::images/special-mouse-commands.png[align="left",alt="Help Menu"]
diff --git a/doc/user_guide/controls-functions-messages.adoc b/doc/user_guide/controls-functions-messages.adoc
new file mode 100644
index 0000000..1a316e6
--- /dev/null
+++ b/doc/user_guide/controls-functions-messages.adoc
@@ -0,0 +1,55 @@
+// Status=review
+
+Two arrangements of controls are provided for generating and selecting
+Tx messages.  Controls familiar to users of program _WSJT_
+appear on *Tab 1*, providing six fields for message entry.
+Pre-formatted messages for the standard minimal QSO are generated when
+you click *Generate Std Msgs* or double-click on an appropriate line
+in one of the decoded text windows.
+
+//.Traditional Message Menu
+image::images/traditional-msg-box.png[align="center",alt="Traditional Message Menu"]
+
+* Select the next message to be transmitted (at the start of your next
+Tx sequence) by clicking on the circle under *Next*.
+
+* To change to a specified Tx message immediately during a
+transmission, click on a rectangular button under the *Now* label.
+Changing a Tx message in mid-stream will slightly reduce the chance of
+a correct decode, but it is usually OK if done in the first 10-15 s of
+a transmission.
+
+* All six Tx message fields are editable.  You can modify an
+automatically generated message or enter a desired message, keeping in
+mind the strict limits on message content.  See <<PROTOCOLS,Protocol
+Specifications>> for details.
+
+* Click on the pull-down arrow for message #5 to select one of the
+pre-stored messages entered on the *Settings | Tx Macros* tab.
+Pressing *Enter* on a modified message #5 automatically adds that
+message to the stored macros.
+
+The second arrangement of controls for generating and selecting
+Tx messages appears on *Tab 2* of the Message Control Panel:
+
+//.New Message Menu
+image::images/new-msg-box.png[align="center",alt="New Message Menu"]
+
+With this setup you normally follow a top-to-bottom sequence of
+transmissions from the left column if you are calling CQ, or the right
+column if answering a CQ.  
+
+* Clicking a button puts the appropriate message in the *Gen Msg* box.
+If you are already transmitting, the Tx message is changed
+immediately.
+
+* You can enter and transmit anything (up to 13 characters, including
+spaces) in the *Free Msg* box.
+
+* Click on the pull-down arrow in the *Free Msg* box to select a
+pre-stored macro.  Pressing *Enter* on a modified message here
+automatically adds that message to the table of stored macros.
+
+IMPORTANT: During a transmission the actual message being sent always
+appears in the first box of the status bar (bottom left of the main
+screen).
diff --git a/doc/user_guide/controls-functions-status-bar.adoc b/doc/user_guide/controls-functions-status-bar.adoc
new file mode 100644
index 0000000..71f00be
--- /dev/null
+++ b/doc/user_guide/controls-functions-status-bar.adoc
@@ -0,0 +1,17 @@
+// Status=review
+
+A *Status Bar* at the bottom edge of the main window provides
+information about operating conditions.  
+
+//.Status Bar
+image::images/status-bar-a.png[align="left",alt="New Message Menu"]
+
+Labels on the *Status Bar* display such information as the program's
+current operating state, operating mode, the content of your most
+recent transmitted message, and whether *Double-click on call sets Tx
+enable* has been selected on the *Settings | General* tab. The first
+label (operating state) can be Receiving, Tx (for Transmitting), Tune,
+or the name of file opened from the *File* menu; this label is
+highlighted in green for Receiving, yellow for Tx, and red for Tune.
+When transmitting, the Tx message is displayed exactly as it will be
+decoded by receiving stations.
diff --git a/doc/user_guide/controls-functions-wide-graph.adoc b/doc/user_guide/controls-functions-wide-graph.adoc
new file mode 100644
index 0000000..5de0e4d
--- /dev/null
+++ b/doc/user_guide/controls-functions-wide-graph.adoc
@@ -0,0 +1,49 @@
+// Status=review
+
+The following controls appear at the bottom of the Wide Graph window.
+With the exception of *JT65 nnnn JT9*, they affect only the graphical
+displays — they have no effect on the decoding process.
+
+image::images/wide-graph-controls.png[align="center",alt="Wide Graph Controls"]
+
+- *Bins/Pixel* controls the displayed frequency resolution.  Set this
+value to 1 for the highest possible resolution, or to higher numbers
+to compress the spectral display. Normal operation with a convenient
+window size works well at 2 to 8 bins per pixel.
+
+- *JT65 nnnn JT9* sets the dividing point (blue marker) for wide-band
+decoding of JT65 and JT9 signals in *JT9+JT65* mode.  The decoder
+looks for JT65 signals everywhere, but JT9 signals only above this
+frequency.
+
+- *Start nnn Hz* sets the low-frequency starting point of the
+waterfall frequency scale.
+
+- *N Avg* is the number of successive FFTs to be averaged before
+updating the spectral display.  Values around 5 are suitable for
+normal JT9 and JT65 operation.  Adjust *N Avg* to make the waterfall
+move faster or slower, as desired.
+
+- *Zero* and *Gain* control the reference level and scaling for
+waterfall colors.  Values around 0 for both parameters are usually
+about right, depending on the input signal level, the chosen palette,
+and your own preferences.
+
+- A dropdown list below the *Palette* label lets you select from a
+wide range of waterfall color palettes.  
+
+- Click *Adjust* to activate a window that allows you to create a
+user-defined palette.
+
+- Check *Flatten* if you want _WSJT-X_ to compensate for a sloping or
+uneven response across the received passband.  For this feature to
+work properly, remember to restrict the range of displayed frequencies
+so that only the active part of the spectrum is shown.
+
+- Select *Current* or *Cumulative* for the spectrum displayed in the
+bottom one-third of the Wide Graph window.  *Current* is the average
+spectrum over the most recent *N Avg* FFT calculations.  *Cumulative*
+is the average spectrum since the start of the present UTC minute.
+(*Linear Avg* is not useful for JT9 or JT65; it is intended for use
+with the yet-to-be implemented JT4 mode.)
+
diff --git a/doc/user_guide/coop-prgrms.adoc b/doc/user_guide/coop-prgrms.adoc
new file mode 100644
index 0000000..b76a989
--- /dev/null
+++ b/doc/user_guide/coop-prgrms.adoc
@@ -0,0 +1,5 @@
+There is one program and one service that compliment _WSJT-X_ greatly. They are as follows:
+
+- {pskreporter}
+
+- {jtalert}
\ No newline at end of file
diff --git a/doc/user_guide/cooperating-programs.adoc b/doc/user_guide/cooperating-programs.adoc
new file mode 100644
index 0000000..91796df
--- /dev/null
+++ b/doc/user_guide/cooperating-programs.adoc
@@ -0,0 +1,23 @@
+_WSJT-X_ is programmed to cooperate closely with several other useful
+programs.  
+
+* {dxlsuite} and {hrd} were described in the section on <<RADIO,rig control>>.
+
+* {pskreporter}, by Philip Gladstone, is a web server that gathers
+reception reports sent by various other programs, including _WSJT-X_.
+The information is made available in near real time on a world map,
+and also as statistical summaries of various kinds.  A number of
+options are available to the user; for example, you can request a map
+showing world-wide JT65 activity on all amateur bands over over the
+past hour.  Such a map might look like this, where different colors
+represent different bands:
+
+image::images/psk-reporter.png[align="left",alt="PSK Reporter"]
+
+* {jtalert}, by VK3AMA, is available only for Windows.  It provides
+many operating aids including automatic logging to several third-party
+logging programs, audio and visual alerts following a number of
+optional alert conditions (decoding of a new DXCC, new state, etc.),
+and convenient direct access to web services such as callsign lookup.
+
+image::images/jtalert.png[align="left",alt="JTAlert-X image"]
diff --git a/doc/user_guide/faq.adoc b/doc/user_guide/faq.adoc
new file mode 100644
index 0000000..8de25ef
--- /dev/null
+++ b/doc/user_guide/faq.adoc
@@ -0,0 +1,83 @@
+////
+Questions:
+ Should be short one liners ending with ?::
+ If your question is too long for one line, consider multiple questions or rephrase
+
+Answers:
+ Can be bullet or paragraphs. Bullets make for easier reading.
+
+Bullet Usage:
+ *  = a circle bullet single intent
+ ** = circle bullet double indent
+ .  = should be avoided as the questions are numbered
+ .. = bullet a, b, c, and so on, double indent
+
+Alternatives: Use a * Bullet, followed by .. for example, then have
+a multi-section answer using the * as the section header
+ 
+ * Section Header 1
+ .. Possible Answer a
+ .. Possible Answer b
+ * Section Header 2
+ .. Possible Answer a
+ .. Possible Answer b
+ 
+Link Usage:
+ Use the common/links.adoc for href links to maintain consistency. Try to avoid
+ apostrophes ` or ' as it breaks AsciiDoc syntax without special escaping 
+ and they do not translate into other languages well.
+
+////
+[qanda]
+My displayed spectrum is flatter when I do not check the *Flatten* box. What's wrong?::
+
+_WSJT-X_ does not expect a steep filter edge within the displayed
+passband. Use a wider IF filter or reduce the displayed passband by
+decreasing *Bins/Pixel*, increasing *Start*, or reducing the width of
+the *Wide Graph*.  You might also choose to re-center the filter
+passband, if such control is available.
+
+My rig has only a single SSB filter, about 2700 Hz bandwidth.  Can I use split mode?::
+
+Set _Split Operation_ to *Rig* (or if necessary, *Fake It*) on the
+*Settings | Radio* tab.  To operate primarily in the JT9 frequency
+range, check the *{plus}2 kHz* box. VFO-A will be moved up by that
+amount, e.g., to 14.078 MHz on 20 meters.  The JT9 sub-band now falls
+between about 500 Hz and 2000Hz on the waterfall display.  As
+described above, VFO-B will be adjusted so as to keep your Tx audio
+always between 1500 and 2000 Hz.  To operate JT65, simply uncheck the
+*{plus}2 kHz* option.  If your rig has an IF shift control or
+equivalent (``passband tuning''), you can operate as if you had 4 kHz
+Rx bandwidth and use the IF shift control to focus on any 2.7 kHz
+portion of the JT65 and JT9 sub-bands.
+
+How should I configure _WSJT-X_ to run multiple instances?::
+
+Start _WSJT-X_ from a command-prompt window, passing each instance a
+unique identifier as in the following two-instance example.  This
+procedure will isolate the *Settings* file and the writable file
+location for each instance of _WSJT-X_.
+
+ wsjtx --rig-name=TS2000
+ wsjtx --rig-name=FT847
+
+When setting up rig control through _OmniRig_, something goes wrong when I click *Test CAT*.  What can I do about it?::
+
+_OmniRig_ apparently has a bug that appears when you click *Test CAT*.
+Forget using *Test CAT* and just click *OK*.  _OmniRig_ then behaves
+normally.
+
+I am using _WSJT-X_ with _Ham Radio Deluxe_.  All seems well until I start HRD Logbook or DM780 running in parallel; then CAT control becomes unreliable.::
+
+You may see delays up to 20 seconds or so in frequency changes or
+other radio commands, due to a bug in HRD.  HRD folks are aware of the
+problem, and are working to resolve it.
+
+I am running _WSJT-X_ under Ubuntu 14.04.  The program starts, but menu bar is missing from the top of the main window and the hot-keys don't work.::
+
+Ubuntu's new ``Unity'' desktop puts the menu for the currently active
+window at the top of the primary display screen.  You can restore menu
+bars to their traditional locations by typing the following in a
+command-prompt window:
+
+ sudo apt-get remove appmenu-qt5 
diff --git a/doc/user_guide/font-sizes.adoc b/doc/user_guide/font-sizes.adoc
new file mode 100644
index 0000000..af8fd64
--- /dev/null
+++ b/doc/user_guide/font-sizes.adoc
@@ -0,0 +1,15 @@
+// Status=review
+
+- You can control the program's font sizes by using a text editor
+(e.g., Windows Notepad or similar) to create a one-line file named
++fonts.txt+ in the _WSJT-X_ installation directory. Enter a single
+line of text with four numbers separated by spaces.  The first two
+numbers control the font size (in points) and weight (on a 0 – 100
+scale) of most labels on the user interface. The last two numbers
+control size and weight of text in the *Band Activity* and *Rx
+Frequency* windows.
+
+- By default the four numbers are ``8 50 10 50''. If you need larger
+fonts in the user interface and bold text in the decode windows, try
+something like ``10 50 12 100'' (without the quotes).
+
diff --git a/doc/user_guide/images/130610_2343-wav-80.png b/doc/user_guide/images/130610_2343-wav-80.png
new file mode 100644
index 0000000..3360529
Binary files /dev/null and b/doc/user_guide/images/130610_2343-wav-80.png differ
diff --git a/doc/user_guide/images/MacAppMenu.png b/doc/user_guide/images/MacAppMenu.png
new file mode 100644
index 0000000..bd3f2c2
Binary files /dev/null and b/doc/user_guide/images/MacAppMenu.png differ
diff --git a/doc/user_guide/images/RadioTab.png b/doc/user_guide/images/RadioTab.png
new file mode 100644
index 0000000..2db6dfd
Binary files /dev/null and b/doc/user_guide/images/RadioTab.png differ
diff --git a/doc/user_guide/images/band-settings.png b/doc/user_guide/images/band-settings.png
new file mode 100644
index 0000000..9b8dd08
Binary files /dev/null and b/doc/user_guide/images/band-settings.png differ
diff --git a/doc/user_guide/images/colors.png b/doc/user_guide/images/colors.png
new file mode 100644
index 0000000..20a3efe
Binary files /dev/null and b/doc/user_guide/images/colors.png differ
diff --git a/doc/user_guide/images/decode-menu.png b/doc/user_guide/images/decode-menu.png
new file mode 100644
index 0000000..1b23834
Binary files /dev/null and b/doc/user_guide/images/decode-menu.png differ
diff --git a/doc/user_guide/images/decodes.png b/doc/user_guide/images/decodes.png
new file mode 100644
index 0000000..af9c732
Binary files /dev/null and b/doc/user_guide/images/decodes.png differ
diff --git a/doc/user_guide/images/file-menu.png b/doc/user_guide/images/file-menu.png
new file mode 100644
index 0000000..758d977
Binary files /dev/null and b/doc/user_guide/images/file-menu.png differ
diff --git a/doc/user_guide/images/freemsg.png b/doc/user_guide/images/freemsg.png
new file mode 100644
index 0000000..c0fc06d
Binary files /dev/null and b/doc/user_guide/images/freemsg.png differ
diff --git a/doc/user_guide/images/help-menu.png b/doc/user_guide/images/help-menu.png
new file mode 100644
index 0000000..8b1d33a
Binary files /dev/null and b/doc/user_guide/images/help-menu.png differ
diff --git a/doc/user_guide/images/jtalert.png b/doc/user_guide/images/jtalert.png
new file mode 100644
index 0000000..ed85caf
Binary files /dev/null and b/doc/user_guide/images/jtalert.png differ
diff --git a/doc/user_guide/images/keyboard-shortcuts.png b/doc/user_guide/images/keyboard-shortcuts.png
new file mode 100644
index 0000000..7811009
Binary files /dev/null and b/doc/user_guide/images/keyboard-shortcuts.png differ
diff --git a/doc/user_guide/images/log-qso.png b/doc/user_guide/images/log-qso.png
new file mode 100644
index 0000000..5f46f63
Binary files /dev/null and b/doc/user_guide/images/log-qso.png differ
diff --git a/doc/user_guide/images/main-ui-1.5.png b/doc/user_guide/images/main-ui-1.5.png
new file mode 100644
index 0000000..9c07f2d
Binary files /dev/null and b/doc/user_guide/images/main-ui-1.5.png differ
diff --git a/doc/user_guide/images/main-ui-controls.png b/doc/user_guide/images/main-ui-controls.png
new file mode 100644
index 0000000..a5fa580
Binary files /dev/null and b/doc/user_guide/images/main-ui-controls.png differ
diff --git a/doc/user_guide/images/misc-controls-center.png b/doc/user_guide/images/misc-controls-center.png
new file mode 100644
index 0000000..6d952f1
Binary files /dev/null and b/doc/user_guide/images/misc-controls-center.png differ
diff --git a/doc/user_guide/images/misc-main-ui.png b/doc/user_guide/images/misc-main-ui.png
new file mode 100644
index 0000000..9516ab8
Binary files /dev/null and b/doc/user_guide/images/misc-main-ui.png differ
diff --git a/doc/user_guide/images/mode-menu.png b/doc/user_guide/images/mode-menu.png
new file mode 100644
index 0000000..c65353f
Binary files /dev/null and b/doc/user_guide/images/mode-menu.png differ
diff --git a/doc/user_guide/images/new-msg-box.png b/doc/user_guide/images/new-msg-box.png
new file mode 100644
index 0000000..ec74e25
Binary files /dev/null and b/doc/user_guide/images/new-msg-box.png differ
diff --git a/doc/user_guide/images/psk-reporter.png b/doc/user_guide/images/psk-reporter.png
new file mode 100644
index 0000000..037d40a
Binary files /dev/null and b/doc/user_guide/images/psk-reporter.png differ
diff --git a/doc/user_guide/images/r3666-config-screen-80.png b/doc/user_guide/images/r3666-config-screen-80.png
new file mode 100644
index 0000000..315aad7
Binary files /dev/null and b/doc/user_guide/images/r3666-config-screen-80.png differ
diff --git a/doc/user_guide/images/r3666-main-ui-80.png b/doc/user_guide/images/r3666-main-ui-80.png
new file mode 100644
index 0000000..b693b73
Binary files /dev/null and b/doc/user_guide/images/r3666-main-ui-80.png differ
diff --git a/doc/user_guide/images/r4148-freq-ui.png b/doc/user_guide/images/r4148-freq-ui.png
new file mode 100644
index 0000000..d5679e5
Binary files /dev/null and b/doc/user_guide/images/r4148-freq-ui.png differ
diff --git a/doc/user_guide/images/r4148-txmac-ui.png b/doc/user_guide/images/r4148-txmac-ui.png
new file mode 100644
index 0000000..865b314
Binary files /dev/null and b/doc/user_guide/images/r4148-txmac-ui.png differ
diff --git a/doc/user_guide/images/reporting.png b/doc/user_guide/images/reporting.png
new file mode 100644
index 0000000..ba4b9b8
Binary files /dev/null and b/doc/user_guide/images/reporting.png differ
diff --git a/doc/user_guide/images/save-menu.png b/doc/user_guide/images/save-menu.png
new file mode 100644
index 0000000..c9b48ff
Binary files /dev/null and b/doc/user_guide/images/save-menu.png differ
diff --git a/doc/user_guide/images/settings-audio.png b/doc/user_guide/images/settings-audio.png
new file mode 100644
index 0000000..faff49e
Binary files /dev/null and b/doc/user_guide/images/settings-audio.png differ
diff --git a/doc/user_guide/images/settings-ui.png b/doc/user_guide/images/settings-ui.png
new file mode 100644
index 0000000..e6cf2d3
Binary files /dev/null and b/doc/user_guide/images/settings-ui.png differ
diff --git a/doc/user_guide/images/setup-menu.png b/doc/user_guide/images/setup-menu.png
new file mode 100644
index 0000000..fdf2423
Binary files /dev/null and b/doc/user_guide/images/setup-menu.png differ
diff --git a/doc/user_guide/images/special-mouse-commands.png b/doc/user_guide/images/special-mouse-commands.png
new file mode 100644
index 0000000..ca7ef8a
Binary files /dev/null and b/doc/user_guide/images/special-mouse-commands.png differ
diff --git a/doc/user_guide/images/status-bar-a.png b/doc/user_guide/images/status-bar-a.png
new file mode 100644
index 0000000..f7b84cf
Binary files /dev/null and b/doc/user_guide/images/status-bar-a.png differ
diff --git a/doc/user_guide/images/traditional-msg-box.png b/doc/user_guide/images/traditional-msg-box.png
new file mode 100644
index 0000000..15b1771
Binary files /dev/null and b/doc/user_guide/images/traditional-msg-box.png differ
diff --git a/doc/user_guide/images/tx-macros.png b/doc/user_guide/images/tx-macros.png
new file mode 100644
index 0000000..4f6db23
Binary files /dev/null and b/doc/user_guide/images/tx-macros.png differ
diff --git a/doc/user_guide/images/view-menu.png b/doc/user_guide/images/view-menu.png
new file mode 100644
index 0000000..23230f0
Binary files /dev/null and b/doc/user_guide/images/view-menu.png differ
diff --git a/doc/user_guide/images/wide-graph-controls.png b/doc/user_guide/images/wide-graph-controls.png
new file mode 100644
index 0000000..bad2a7c
Binary files /dev/null and b/doc/user_guide/images/wide-graph-controls.png differ
diff --git a/doc/user_guide/install-from-source.adoc b/doc/user_guide/install-from-source.adoc
new file mode 100644
index 0000000..466528f
--- /dev/null
+++ b/doc/user_guide/install-from-source.adoc
@@ -0,0 +1,29 @@
+// Status=review
+
+Source code for _WSJT-X_ is available from a public repository at
+{devsvn}. To compile the program you will need to install at least the
+following packages:
+
+- Subversion 1.8 or later
+- Qt 5.2 or later
+- g++ 4.8 or later
+- gfortran 4.8 or later
+- fftw3
+- MinGW (for Windows only)
+
+Source code for _WSJT-X_ v{VERSION} can be downloaded with the command:
+
+=====
+svn co svn://svn.code.sf.net/p/wsjt/wsjt/tags/wsjtx-{VERSION}
+=====
+
+and for the current development branch,
+
+=====
+svn co svn://svn.code.sf.net/p/wsjt/wsjt/branches/wsjtx
+=====
+
+If you are interested in contributing to the development and
+documentation of _WSJT_ and its sister programs, please join the
+developer's email list {devmail} and let us know of your areas of
+interest.
diff --git a/doc/user_guide/install-linux.adoc b/doc/user_guide/install-linux.adoc
new file mode 100644
index 0000000..d631f4b
--- /dev/null
+++ b/doc/user_guide/install-linux.adoc
@@ -0,0 +1,79 @@
+// Status=review
+
+Debian, Ubuntu, and other Debian-based systems:
+
+* 32-bit: {debian32}
+- To install: +sudo dpkg -i wsjtx_{VERSION}_i386.deb+
+- Uninstall:  +sudo dpkg -P wsjtx+
+* 64-bit: {debian64}
+- To install: +sudo dpkg -i wsjtx_{VERSION}_amd64.deb+
+- Uninstall:  +sudo dpkg -P wsjtx+
+
+You may also need to execute the following commands in a terminal:
+
+ sudo apt-get install libqt5multimedia5-plugins libqt5serialport5 
+ sudo apt-get install libfftw3-single3
+
+For Ubuntu 15.04 and similar systems, the above and also
+
+ sudo apt-get install libqt5opengl5 
+
+Fedora, Red Hat, and other rpm-based systems:
+
+* 32-bit: {fedora32}
+- To install: +sudo rpm -i wsjtx-{VERSION}-i686.rpm+
+- Uninstall: +sudo rpm -e wsjtx+
+* 64-bit: {fedora64}
+- To install: +sudo rpm -i wsjtx-{VERSION}-x86_64.rpm+
+- Uninstall: +sudo rpm -e wsjtx+
+
+You may also need to execute the following commands in a terminal:
+
+ sudo yum install fftw-libs-single qt5-qtmultimedia qt5-qtserialport 
+
+.KVASD Installation
+
+All Linux users must install a companion program called +kvasd+, an
+implementation of the the Koetter-Vardy algebraic soft-decision
+decoder for the Reed Solomon (63,12) code.  Users of Ubuntu and other
+Debian-based sysyems can install +kvasd+ by executing the following
+commands in a terminal:
+
+ sudo add-apt-repository ppa:ki7mt/kvasd-installer
+ sudo apt-get update
+ sudo apt-get install kvasd-installer
+ kvasd-installer
+
+The final screen of the installer should include the line
+
+ KVASD version 1.12 -- Decode test *** PASSED ***
+
+which should also be displayed if the command
+
+ kvasd -v
+
+is executed after installation is complete.
+
+You can install +kvasd+ on most Linux systems (including ARM-based
+systems) by downloading, unpacking, and executing the simple tools
+packaged in the +kvasd-installer+ script.  Your system will need the 
+following standard tools already installed: 
+
+ autoconf awk bash dialog libgfortran svn
+
+Download the {kvasd_installer} tarfile to a conveniant directory, then
+execute the following commands in a terminal there:
+
+ tar xzf kvasd-installer-1.12.14.tar.gz
+ cd kvasd-installer-1.12.14
+ ./autogen.sh
+ sudo make install
+ kvasd-installer
+
+As described above, the final screen of the installer should include
+the line
+
+ KVASD version 1.12 -- Decode test *** PASSED ***
+
+
+
diff --git a/doc/user_guide/install-mac.adoc b/doc/user_guide/install-mac.adoc
new file mode 100644
index 0000000..7c8a0dd
--- /dev/null
+++ b/doc/user_guide/install-mac.adoc
@@ -0,0 +1,23 @@
+// These instructions are up-to-date for WSJT-X v1.4
+
+*OS X 10.7* and later: Download the file {osx} to your desktop,
+double-click on it and consult its +ReadMe+ file for important
+installation notes.  
+
+If you have already installed a previous version, you can retain it by
+changing its name in the *Applications* folder (say, from _WSJT-X_ to
+_WSJT-X_previous_).  You can then proceed to the installation phase.
+
+Take note also of the following:
+
+* Double-click on *KVASD-Installer* to insert the KVASD decoder into
+_WSJT-X_.
+
+* Use the Mac's *Audio MIDI Setup* utility to configure your sound
+card for 48000 Hz, two-channel, 16-bit format.
+
+* Use *System Preferences* to select an external time source to keep
+your system clock synchronized to UTC.
+
+* To uninstall simply drag the _WSJT-X_ application from *Applications* 
+to the *Trash Can*. 
diff --git a/doc/user_guide/install-windows.adoc b/doc/user_guide/install-windows.adoc
new file mode 100644
index 0000000..8980315
--- /dev/null
+++ b/doc/user_guide/install-windows.adoc
@@ -0,0 +1,28 @@
+// Status=review
+
+Download and execute the package file {win32}, following these
+instructions:
+
+- Install _WSJT-X_ into its own directory rather than in the conventional
+location +C:\Program Files\WSJTX+.  Suggested installation directories are
++C:\WSJTX+ or +C:\WSJT\WSJTX+.
+
+- All program files relating to _WSJT-X_ will be stored in the chosen
+installation directory and its subdirectories. 
+
+- Logs and other writeable files will normally be found in the 
+directory +C:\Users\<username>\AppData\Local\WSJT-X+.
+
+- The built-in Windows facility for time synchronization is usually
+not adequate. We recommend the program _Meinberg NTP_: see {ntpsetup}
+for downloading and installation instructions.
+
+- _WSJT-X_ expects your sound card to do its raw sampling at 48000 Hz.
+To ensure that this will be so when running under recent versions of
+Windows, open the system's *Sound* control panel and select in turn the
+*Recording* and *Playback* tabs. Click on *Properties*, then
+*Advanced*, and select *16 bit, 48000 Hz (DVD Quality)*.
+
+- You can uninstall _WSJT-X_ by clicking its *Uninstall* link in the
+Windows *Start* menu, or by using *Uninstall a Program* on the
+Windows Control Panel.
diff --git a/doc/user_guide/introduction.adoc b/doc/user_guide/introduction.adoc
new file mode 100644
index 0000000..bfd6c38
--- /dev/null
+++ b/doc/user_guide/introduction.adoc
@@ -0,0 +1,43 @@
+// Status=review
+
+_WSJT-X_ is a computer program designed to facilitate basic amateur
+radio communication using very weak signals. The first four letters in
+the program name stand for “Weak Signal communication by K1JT,” while
+the suffix “-X” indicates that _WSJT-X_ started as an extended (and
+experimental) branch of the program _WSJT_.
+
+_WSJT-X_ currently offers two protocols or “modes,” JT65 and JT9.
+Both are designed for making reliable, confirmed QSOs under extreme
+weak-signal conditions. They use nearly identical message structure
+and source encoding.  JT65 was designed for EME (“moonbounce”) on the
+VHF/UHF bands and has also proven very effective for worldwide QRP
+communication on the HF bands.  JT9 is optimized for the LF, MF, and
+lower HF bands.  It is about 2 dB more sensitive than JT65
+while using less than 10% of the bandwidth. Both modes use one-minute
+timed sequences of alternating transmission and reception, so a
+minimal QSO takes four to six minutes — two or three transmissions by
+each station, one sending in odd UTC minutes and the other even. On
+the HF bands, world-wide QSOs are possible with power levels of a few
+watts and compromise antennas.
+
+_WSJT-X_ can display a passband as large as 5 kHz and provides
+dual-mode reception of both JT65 and JT9 signals. If your receiver can
+be configured with at least 4 kHz bandwidth in USB mode, you can set
+the dial frequency to one of the standard JT65 frequencies — for
+example, 14.076 MHz for the 20-meter band — and display the full JT65
+and JT9 sub-bands simultaneously on the waterfall. You can then make
+QSOs in both modes using nothing more than mouse clicks.
+
+Plans for future program development call for _WSJT-X_ and _WSJT_ to
+merge together. _WSJT-X_ will gradually acquire additional modes
+such as JT4 that are now supported in _WSJT_. The entire
+WSJT-related effort is an open-source project, released under the 
+{gnu_gpl} (GPL). If you have programming or
+documentation skills or would like to contribute to the project in
+other ways, please make your interests known to the development team.
+The project’s source-code repository can be found at {devsvn}, and
+most communication among the developers takes place on the email
+reflector {devmail}.  User-level questions and answers, and general
+communication among users is found on the {wsjt_yahoo_group} email
+reflector.
+
diff --git a/doc/user_guide/jt65-jt9-differences.adoc b/doc/user_guide/jt65-jt9-differences.adoc
new file mode 100644
index 0000000..f237e49
--- /dev/null
+++ b/doc/user_guide/jt65-jt9-differences.adoc
@@ -0,0 +1,41 @@
+// Status=review
+
+The most striking difference between JT65 and JT9 is the much smaller
+occupied bandwidth of JT9: 15.6 Hz, compared with 177.6 Hz for JT65A.
+Transmissions in the two modes are essentially the same length, and
+both modes use exactly 72 bits to carry message information. At the
+user level the two modes support nearly identical message structures.
+
+JT65 signal reports are constrained to the range –1 to –30 dB. This
+range is more than adequate for EME purposes, but not really enough
+for optimum use at HF and below. S/N values displayed by the JT65
+decoder are clamped at an upper limit –1 dB, and in present JT65
+decoders the S/N scale is nonlinear above –10 dB.
+
+By comparison, JT9 allows for signal reports in the range –50 to +49
+dB. It manages this by taking over a small portion of ``message
+space'' that would otherwise be used for grid locators within 1 degree
+of the south pole. The S/N scale of the present JT9 decoder is
+reasonably linear (although it’s not intended to be a precision
+measurement tool).  
+
+With clean signals and a clean noise background, JT65 achieves nearly
+100% decoding down to S/N = –22 dB and about 50% success at –24
+dB. JT9 is about 2 dB better, achieving 50% decoding at –26 dB. Both
+modes produce extremely low false-decode rates.
+
+Early experience suggests that under most HF propagation conditions
+the two modes have comparable reliability. The tone spacing of JT9 is
+about two-thirds that of JT65, so in some disturbed ionospheric
+conditions in the higher portion of the HF spectrum, JT65 may perform
+better.
+
+JT9 is an order of magnitude better in spectral efficiency. On a busy
+HF band, the conventional 2-kHz-wide JT65 sub-band is often filled
+with overlapping signals. Ten times as many JT9 signals can fit into
+the same frequency range, without collisions.
+
+JT65 signals often decode correctly even when they overlap. Such
+behavior is much less likely with JT9 signals, which fill their occupied
+bandwidth more densely. JT65 may also be more forgiving of small 
+frequency drifts.
diff --git a/doc/user_guide/jt65-protocol.adoc b/doc/user_guide/jt65-protocol.adoc
new file mode 100644
index 0000000..2b7a151
--- /dev/null
+++ b/doc/user_guide/jt65-protocol.adoc
@@ -0,0 +1,51 @@
+// Status=review
+
+JT65 was designed for making minimal QSOs via EME (``moon-bounce'') on
+the VHF and UHF bands. A detailed description of the protocol and its
+implementation in program _WSJT_ was published in {jt65protocol} for
+September-October, 2005. Briefly stated, JT65 uses 60 s T/R sequences
+and carefully structured messages. Standard messages are compressed so
+that two callsigns and a grid locator can be transmitted in just 71
+information bits.  A 72^nd^ bit serves as a flag to indicate that a
+message consists of arbitrary text (up to 13 characters) instead of
+callsigns and a grid locator.  Special formats allow other information
+such as add-on callsign prefixes (e.g., ZA/K1ABC) or numerical signal
+reports (in dB) to be substituted for the grid locator. The basic aim
+is to compress the most common messages used for minimally valid QSOs
+into a minimum fixed number of bits. After compression, a Reed Solomon
+(63,12) error-control code converts 72-bit user messages into
+sequences of 63 six-bit channel symbols.
+
+JT65 requires tight synchronization of time and frequency between
+transmitting and receiving stations. Each transmission is divided into
+126 contiguous time intervals or symbols of length 4096/11025 = 0.372
+s. Within each interval the waveform is a constant-amplitude sinusoid
+at one of 65 pre-defined frequencies. Frequency steps between
+intervals are accomplished in a phase-continuous manner. Half of the
+channel symbols are devoted to a pseudo-random synchronizing vector
+interleaved with the encoded information symbols. The sync vector
+allows calibration of time and frequency offsets between transmitter
+and receiver. A transmission nominally begins at t = 1 s after the
+start of a UTC minute and finishes at t = 47.8 seconds. The
+synchronizing tone is at 11025 × 472/4096 = 1270.46 Hz, and is normally
+sent in each interval having a “1” in the following pseudo-random
+sequence:
+
+ 100110001111110101000101100100011100111101101111000110101011001
+ 101010100100000011000000011010010110101010011001001000011111111
+
+Encoded user information is transmitted during the 63 intervals not
+used for the sync tone. Each channel symbol generates a tone at
+frequency 11025 × 472/4096 + 11025/4096 × (N+2) × m, where N is the
+value of the six-bit symbol, 0 ≤ N ≤ 63, and m is 1, 2, or 4 for JT65
+sub-modes A, B, or C.  Sub-mode JT65A is always used at HF.
+
+For EME (but, conventionally, not on the HF bands) the signal report
+OOO is sometimes used instead of numerical signal reports. It is
+conveyed by reversing sync and data positions in the transmitted
+sequence.  Shorthand messages for RO, RRR, and 73 dispense with the
+sync vector entirely and use time intervals of 16384/11025 = 1.486 s
+for pairs of alternating tones. The lower frequency is always 1270.46
+Hz, the same as that of the sync tone, and the frequency separation is
+110250/4096 = 26.92 Hz multiplied by n × m, with n = 2, 3, 4 for the
+messages RO, RRR, and 73.
diff --git a/doc/user_guide/jt9-protocol.adoc b/doc/user_guide/jt9-protocol.adoc
new file mode 100644
index 0000000..f8a3cc0
--- /dev/null
+++ b/doc/user_guide/jt9-protocol.adoc
@@ -0,0 +1,20 @@
+// Status=review
+//Needs work!
+
+JT9 is designed for making minimally valid QSOs at LF, MF, and HF. It
+uses 72-bit structured messages nearly identical (at the user level)
+to those in JT65. Error control coding (ECC) uses a strong
+convolutional code with constraint length K=32, rate r=1/2, and a zero
+tail, leading to an encoded message length of (72+31) × 2 = 206
+information-carrying bits. Modulation is nine-tone frequency-shift
+keying, 9-FSK.  Eight tones are used for data, one for
+synchronization. Eight data tones means that three data bits are
+conveyed by each transmitted information symbol. Sixteen symbol
+intervals are devoted to synchronization, so a transmission requires a
+total of 206 / 3 + 16 = 85 (rounded up) channel symbols. The sync
+symbols are those numbered 1, 2, 5, 10, 16, 23, 33, 35, 51, 52, 55,
+60, 66, 73, 83, and 85 in the transmitted sequence.  Each symbol lasts
+for 6912 sample intervals at 12000 samples per second, or about 0.576
+seconds. Tone spacing of the 9-FSK modulation is 12000/6912 = 1.736
+Hz, the inverse of the symbol duration. The total occupied bandwidth
+is 9 × 1.736 = 15.6 Hz.
diff --git a/doc/user_guide/logging.adoc b/doc/user_guide/logging.adoc
new file mode 100644
index 0000000..961477d
--- /dev/null
+++ b/doc/user_guide/logging.adoc
@@ -0,0 +1,40 @@
+A basic logging facility in _WSJT-X_ saves QSO information to flies
+named +wsjtx.log+ (in comma-separated text format) and +wsjtx_log.adi+
+(in standard ADIF format).  These files can be imported directly into
+other programs, for example spreadsheets and popular logging prgrams.
+More elaborate logging capabilities are supported in cooperation with
+{jtalert}, {hrd}, or the {dxlsuite}.
+
+The program option *Show DXCC entity and worked before status*
+(selectable on the *Settings | General* tab) is intended mostly for
+use on non-Windows platforms, where {jtalert} is not available.  When
+this option is checked _WSJT-X_ appends some additional information to
+all CQ messages displayed in the _Band Activity_ window.  The name of
+the DXCC entity is shown, abbreviated if necessary.  Your ``worked
+before'' status for this callsign (according to log file
++wsjtx_log.adi+) is flagged with a single character and a change of
+background color, as follows:
+
+[horizontal]
+!::  (default color bright purple) -- New DXCC entity
+~::  (light pink) -- You have already worked this DXCC entity but not 
+this station
+ ::  (green) -- You have previously worked the calling station
+
+In this respect the program does not distinguish between modes, but it
+does differentiate between bands.
+
+_WSJT-X_ includes a built-in +cty.dat+ file containing DXCC prefix 
+information.  Updated files can be downloaded from {cty_dat} when 
+required.  If an updated +cty.dat+ is present in the logs folder 
+and readable, it will be used in preference to the built-in one.
+
+The log file +wsjtx_log.adi+ is updated whenever you log a QSO from
+_WSJT-X_.  (Keep in mind that if you erase this file you will lose all
+``worked before'' information.)  You can append or overwrite the
++wsjtx_log.adi+ file by exporting your QSO history as an ADIF file
+from another logging program.  Turning *Show DXCC entity and worked
+before status* off and then on again will cause _WSJT-X_ to re-read
+the log file.  Very large log files may cause _WSJT-X_ to slow down
+when searching for calls.
+
diff --git a/doc/user_guide/make-qso.adoc b/doc/user_guide/make-qso.adoc
new file mode 100644
index 0000000..861a94f
--- /dev/null
+++ b/doc/user_guide/make-qso.adoc
@@ -0,0 +1,166 @@
+// Status=review
+=== Standard Exchange
+By longstanding tradition, a minimally valid QSO requires the exchange
+of callsigns, a signal report or some other information, and
+acknowledgments.  _WSJT-X_ is designed to facilitate making such
+minimal QSOs using short, structured messages. The process works best
+if you use these formats and follow standard operating practices. The
+recommended basic QSO goes something like this:
+
+[width="90%",cols="3,7,12",options="header"]
+|=======================================
+|UTC|Transmitted Message|Comment
+|0001|CQ K1ABC FN42|K1ABC calls CQ
+|0002|K1ABC G0XYZ IO91|G0XYZ answers
+|0003|G0XYZ K1ABC –19|K1ABC sends report
+|0004|K1ABC G0XYZ R–22|G0XYZ sends acknowledgment and report
+|0005|G0XYZ K1ABC RRR|K1ABC sends acknowledgment
+|0006|K1ABC G0XYZ 73|G0XYZ sends 73
+|=======================================
+
+*Standard messages* consist of two callsigns (or CQ, QRZ, or DE and
+one callsign) followed by the transmitting station’s grid locator, a
+signal report, R plus a signal report, or the final acknowledgements
+RRR or 73.  These messages are compressed and encoded in a highly
+efficient and reliable way.  In uncompressed form (as displayed
+on-screen) they may contain as many as 22 characters.
+
+*Signal reports* are specified as signal-to-noise ratio (S/N) in dB,
+using a standard reference noise bandwidth of 2500 Hz.  Thus, in
+example message at UTC 0003 above, K1ABC is telling G0XYZ that his
+signal is 19 dB below the noise power in bandwidth 2500 Hz.  In the
+message at 0004, G0XYZ acknowledges receipt of that report and
+responds with a –22 dB signal report.  JT65 reports are constrained to
+lie in the range –30 to –1 dB, and values are significantly compressed
+above about -10 dB.  JT9 supports the extended range –50 to +49 dB and
+assigns more reliable numbers to relatively strong signals.
+
+IMPORTANT: Signals become visible on the waterfall around S/N = –26 dB and
+audible (to someone with very good hearing) around –15 dB. Thresholds
+for decodability are around –24 dB for JT65, –26 dB for JT9.
+
+=== Free Text Messages
+
+Users often add some friendly chit-chat at the end of a QSO.
+Free-format messages such as ``TNX ROBERT 73'' or ``5W VERT 73 GL''
+are supported, up to a maximum of 13 characters, including spaces.  In
+general you should avoid the character / in free-text nessages, as the
+program may then try to interpret your construction as part of a
+compound callsign.  It should be obvious that the JT9 and JT65
+protocols are not designed or well suited for extensive conversations
+or rag-chewing.
+
+[[COMP-CALL]] 
+=== Compound Callsigns
+
+Compound callsigns such as xx/K1ABC or K1ABC/x are handled in
+one of two possible ways:
+
+.Messages containing Type 1 compound callsigns
+
+A list of about 350 of the most common prefixes and suffixes can be
+displayed from the *Help* menu.  A single compound callsign involving
+one item from this list can be used in place of the standard third
+word of a message (normally a locator, signal report, RRR, or 73).
+The following examples are all acceptable messages containing *Type 1*
+compound callsigns:
+
+ CQ ZA/K1ABC
+ CQ K1ABC/4
+ ZA/K1ABC G0XYZ
+ G0XYZ K1ABC/4
+
+The following messages are _not_ valid, because a third word is not
+permitted in any message containing a *Type 1* compound callsign:
+
+ ZA/K1ABC G0XYZ -22        #These messages will be sent
+ G0XYZ K1ABC/4 73          #without the third "word"
+
+A QSO between two stations using *Type 1* compound-callsign messages
+might look like this:
+
+ CQ ZA/K1ABC
+                     ZA/K1ABC G0XYZ
+ G0XYZ K1ABC –19
+                     K1ABC G0XYZ R–22
+ G0XYZ K1ABC RRR
+                     K1ABC G0XYZ 73
+
+Notice that the full compound callsign is sent and received in the
+first two transmissions.  After that, the operators omit the add-on
+prefix or suffix and use the standard structured messages.
+
+.Type 2 Compound-Callsign Messages
+
+Prefixes and suffixes _not_ found in the displayable short list are
+handled by using *Type 2* compound callsigns.  In this case the
+compound callsign must be the second word in a two- or three-word
+message, and the first word must be CQ, DE, or QRZ.  Prefixes can be 1
+to 4 characters, suffixes 1 to 3 characters.  A third word conveying a
+locator, report, RRR, or 73 is permitted.  The following are valid 
+messages containing *Type 2* compound callsigns:
+
+ CQ W4/G0XYZ FM07
+ QRZ K1ABC/VE6 DO33
+ DE W4/G0XYZ FM18
+ DE W4/G0XYZ -22
+ DE W4/G0XYZ R-22
+ DE W4/G0XYZ RRR
+ DE W4/G0XYZ 73
+
+In each case, the message is treated as *Type 2* because the add-on
+prefix or suffix is _not_ one of those in the fixed list.  Note
+that a second callsign is never permissible in these messages.
+
+IMPORTANT: Remember that during a transmission your transmitted message is
+always displayed in the first label on the *Status Bar*, highlighted
+in yellow.  It is displayed there exactly as another station will
+receive it.  Be sure to check that you are actually transmitting the
+message you wish to send!
+
+QSOs involving *Type 2* compound callsigns might look like either
+of the following sequences
+
+ CQ K1ABC/VE1 FN75
+                     K1ABC G0XYZ IO91
+ G0XYZ K1ABC –19
+                     K1ABC G0XYZ R–22
+ G0XYZ K1ABC RRR
+                     K1ABC/VE1 73
+
+
+ CQ K1ABC FN42
+                     DE G0XYZ/W4 FM18
+ G0XYZ K1ABC –19
+                     K1ABC G0XYZ R–22
+ G0XYZ K1ABC RRR
+                     DE G0XYZ/W4 73
+
+Operators with a compound callsign use its full form when calling CQ
+and possibly also in a 73 transmission, as may be required by
+licensing authorities.  Other transmissions during a QSO may use the
+standard structured messages without callsign prefix or suffix. 
+
+IMPORTANT: If you are using a compound callsign, you may want to
+experiment with the option *Message generation for type 2 compound
+callsign holders* on the *Settings | General* tab, so that messages
+will be generated that best suit your needs.
+
+=== Pre-QSO Checklist
+
+Before attempting your first QSO with JT9 or JT65, be sure to go
+through the <<TUTORIAL,Basic Operating Tutorial>> above, as well as the following
+checklist:
+
+- Your callsign and grid locator set to correct values
+
+- PTT and CAT control (if used) properly configured and tested
+
+- Computer clock properly synchronized to UTC within ±1 s
+
+- Radio set to *USB* (upper sideband) mode
+
+- Radio filters centered and set to widest available passband (up to 5 kHz).
+
+IMPORTANT: Remember that JT9 and J65 generally do not require high
+power. Under most HF propagation conditions, QRP is the norm.
diff --git a/doc/user_guide/platform-dependencies.adoc b/doc/user_guide/platform-dependencies.adoc
new file mode 100644
index 0000000..2d79ac8
--- /dev/null
+++ b/doc/user_guide/platform-dependencies.adoc
@@ -0,0 +1,48 @@
+// Status=review
+
+A few _WSJT-X_ features behave differently in Windows, Linux, or OS X,
+or may not be relevant to all operating platforms.
+
+.File locations
+* *Windows*
+Settings::
+ +%LOCALAPPDATA%\WSJT-X\WSJT-X.ini+
+Log files::
+ +%LOCALAPPDATA%\WSJT-X\+
+Default save::
+ +%LOCALAPPDATA%\WSJT-X\save\+
+
+* *Windows, when using "--rig-name=xxx"*
+Settings::
+ +%LOCALAPPDATA%\WSJT-X - xxx+
+Log files::
+  +%LOCALAPPDATA%\WSJT-X - xxx\WSJT-X - xxx.ini+
+
+* *Linux*
+Settings::
+ +~/.config/WSJT-X.ini+
+Log files:: 
+ +~/.local/share/WSJT-X/+
+Default save::
+ +~/.local/share/WSJT-X/save/+
+
+* *Linux, when using "--rig-name=xxx"*
+Log files::
+ +~/.local/share/WSJT-X - xxx/+
+Default save::
+ +~/.config/WSJT-x - xxx.ini+
+
+* *Macintosh*
+Settings::
+ +~/Library/Preferences/WSJT-X.ini+
+Log files::
+ +~/Library/Application Support/WSJT-X/+
+Default save:: 
+ +~/Library/Application Support/WSJT-X/save/+
+
+* *Macintosh, when using "--rig-name=xxx"*
+Log files::
+ +~/Library/Application Support/WSJT-X - xxx/+
+Default save::
+ +~/Library/Preferences/WSJT-X - xxx.ini+
+
diff --git a/doc/user_guide/rig-config-adat.adoc b/doc/user_guide/rig-config-adat.adoc
new file mode 100644
index 0000000..a556a60
--- /dev/null
+++ b/doc/user_guide/rig-config-adat.adoc
@@ -0,0 +1,104 @@
+// Status=needsupdate
+// This is a comment line, anything with // is ignored at process time.
+// because the page is not a main page include, we need to add
+// ref-links again, as they are not global.
+:icons:
+:badges:
+:rig_template: link:rig-config-template.html[Template]
+:devmail: mailto:wsjt-devel at lists.berlios.de[wsjt-devel]
+
+= ADAT Configuration Guide
+Available Configurations
+
+If you have configuration data for a rig that is not listed, or comments about a
+particular rig configuration, please use the {rig_template} and send it to
+{devmail}. 
+
+[align="center",valign="middle",halign="center"]
+// 5 Models per line please
+|========
+|<<X1,ADAT1>>|<<X2,ADAT2>>|ADAT3|ADAT4|ADAT5
+|========
+
+[[X1]]
+== ADAT-1
+.Configuration Covers:
+
+* MyCall:
+* MyGrid:
+* PTT Method:
+* Pskreporter:
+* CW Id After 73:
+* CW Interval:
+* CAT NOTES:
+* DTR:
+* RTS:
+* CAT Port:
+* CAT Port Settings:
+* Split:
+* Polling:
+* Audio-In:
+* Audio-In Mono:
+* Audio-Out:
+* Audio-Out:
+
+=== OS Specific Notes
+.Notes Relating To Operating System
+
+* Windows: XP, Vista, Win7, Win8, etc.
+* Linux: Slackaware, Fedora, FreeBSD, Ubuntu, Debian, etc
+* Mac OSx: 
+
+=== Interface Notes
+.Notes Relating To Rig Interface
+
+* Navigator
+* SignaLink
+* ShackLan
+* Kam
+* DX-Doubler
+* Array Solutions
+* Home-Brew
+
+[[X2]]
+== ADAT-2
+.Configuration Covers:
+
+* MyCall:
+* MyGrid:
+* PTT Method:
+* Pskreporter:
+* CW Id After 73:
+* CW Interval:
+* CAT NOTES:
+- Note-1/2/3
+* DTR:
+* RTS:
+* CAT Port:
+* CAT Port Settings:
+* Split:
+* Polling:
+* Audio
+-In:
+* Audio-In Mono:
+* Audio-Out:
+* Audio-Out:
+
+=== OS Specific Notes
+.Notes Relating To Operating System
+
+* Windows: XP, Vista, Win7, Win8, etc.
+* Linux: Slackaware, Fedora, FreeBSD, Ubuntu, Debian, etc
+* Mac OSx: 
+
+=== Interface Notes
+.Notes Relating To Rig Interface
+
+* Navigator
+* SignaLink
+* ShackLan
+* Kam
+* DX-Doubler
+* Array Solutions
+* Home-Brew
+
diff --git a/doc/user_guide/rig-config-alinco.adoc b/doc/user_guide/rig-config-alinco.adoc
new file mode 100644
index 0000000..bf42e3d
--- /dev/null
+++ b/doc/user_guide/rig-config-alinco.adoc
@@ -0,0 +1,104 @@
+// Status=needsupdate
+// This is a comment line, anything with // is ignored at process time.
+// because the page is not a main page include, we need to add
+// ref-links again, as they are not global.
+:icons:
+:badges:
+:rig_template: link:rig-config-template.html[Template]
+:devmail: mailto:wsjt-devel at lists.berlios.de[wsjt-devel]
+
+= Alinco Configuration Guide
+Available Configurations
+
+If you have configuration data for a rig that is not listed, or comments about a
+particular rig configuration, please use the {rig_template} and send it to
+{devmail}.
+
+[align="center",valign="middle",halign="center"]
+// 5 Models per line please
+|========
+|<<X1,Alinco1>>|<<X2,Alinco2>>|Alinco3|Alinco4|Alinco5
+|========
+
+[[X1]]
+== Alinco-1
+.Configuration Covers:
+
+* MyCall:
+* MyGrid:
+* PTT Method:
+* Pskreporter:
+* CW Id After 73:
+* CW Interval:
+* CAT NOTES:
+* DTR:
+* RTS:
+* CAT Port:
+* CAT Port Settings:
+* Split:
+* Polling:
+* Audio-In:
+* Audio-In Mono:
+* Audio-Out:
+* Audio-Out:
+
+=== OS Specific Notes
+.Notes Relating To Operating System
+
+* Windows: XP, Vista, Win7, Win8, etc.
+* Linux: Slackaware, Fedora, FreeBSD, Ubuntu, Debian, etc
+* Mac OSx: 
+
+=== Interface Notes
+.Notes Relating To Rig Interface
+
+* Navigator
+* SignaLink
+* ShackLan
+* Kam
+* DX-Doubler
+* Array Solutions
+* Home-Brew
+
+[[X2]]
+== Alinco-2
+.Configuration Covers:
+
+* MyCall:
+* MyGrid:
+* PTT Method:
+* Pskreporter:
+* CW Id After 73:
+* CW Interval:
+* CAT NOTES:
+- Note-1/2/3
+* DTR:
+* RTS:
+* CAT Port:
+* CAT Port Settings:
+* Split:
+* Polling:
+* Audio
+-In:
+* Audio-In Mono:
+* Audio-Out:
+* Audio-Out:
+
+=== OS Specific Notes
+.Notes Relating To Operating System
+
+* Windows: XP, Vista, Win7, Win8, etc.
+* Linux: Slackaware, Fedora, FreeBSD, Ubuntu, Debian, etc
+* Mac OSx: 
+
+=== Interface Notes
+.Notes Relating To Rig Interface
+
+* Navigator
+* SignaLink
+* ShackLan
+* Kam
+* DX-Doubler
+* Array Solutions
+* Home-Brew
+
diff --git a/doc/user_guide/rig-config-aor.adoc b/doc/user_guide/rig-config-aor.adoc
new file mode 100644
index 0000000..11cb943
--- /dev/null
+++ b/doc/user_guide/rig-config-aor.adoc
@@ -0,0 +1,103 @@
+// Status=needsupdate
+// This is a comment line, anything with // is ignored at process time.
+// because the page is not a main page include, we need to add
+// ref-links again, as they are not global.
+:icons:
+:badges:
+:rig_template: link:rig-config-template.html[Template]
+:devmail: mailto:wsjt-devel at lists.berlios.de[wsjt-devel]
+
+= AOR Configuration Guide
+Available Configurations
+
+If you have configuration data for a rig that is not listed, or comments about a
+particular rig configuration, please use the {rig_template} and send it to
+{devmail}. 
+
+[align="center",valign="middle",halign="center"]
+// 5 Models per line please
+|========
+|<<X1,AOR1>>|<<X2,AOR2>>|AOR3|AOR4|AOR5
+|========
+
+[[X1]]
+== AOR-1
+.Configuration Covers:
+
+* MyCall:
+* MyGrid:
+* PTT Method:
+* Pskreporter:
+* CW Id After 73:
+* CW Interval:
+* CAT NOTES:
+* DTR:
+* RTS:
+* CAT Port:
+* CAT Port Settings:
+* Split:
+* Polling:
+* Audio-In:
+* Audio-In Mono:
+* Audio-Out:
+* Audio-Out:
+
+=== OS Specific Notes
+.Notes Relating To Operating System
+
+* Windows: XP, Vista, Win7, Win8, etc.
+* Linux: Slackaware, Fedora, FreeBSD, Ubuntu, Debian, etc
+* Mac OSx: 
+
+=== Interface Notes
+.Notes Relating To Rig Interface
+
+* Navigator
+* SignaLink
+* ShackLan
+* Kam
+* DX-Doubler
+* Array Solutions
+* Home-Brew
+
+[[X2]]
+== AOR-2
+.Configuration Covers:
+
+* MyCall:
+* MyGrid:
+* PTT Method:
+* Pskreporter:
+* CW Id After 73:
+* CW Interval:
+* CAT NOTES:
+- Note-1/2/3
+* DTR:
+* RTS:
+* CAT Port:
+* CAT Port Settings:
+* Split:
+* Polling:
+* Audio
+-In:
+* Audio-In Mono:
+* Audio-Out:
+* Audio-Out:
+
+=== OS Specific Notes
+.Notes Relating To Operating System
+
+* Windows: XP, Vista, Win7, Win8, etc.
+* Linux: Slackaware, Fedora, FreeBSD, Ubuntu, Debian, etc
+* Mac OSx: 
+
+=== Interface Notes
+.Notes Relating To Rig Interface
+
+* Navigator
+* SignaLink
+* ShackLan
+* Kam
+* DX-Doubler
+* Array Solutions
+* Home-Brew
diff --git a/doc/user_guide/rig-config-drake.adoc b/doc/user_guide/rig-config-drake.adoc
new file mode 100644
index 0000000..5310ff5
--- /dev/null
+++ b/doc/user_guide/rig-config-drake.adoc
@@ -0,0 +1,104 @@
+// Status=needsupdate
+// This is a comment line, anything with // is ignored at process time.
+// because the page is not a main page include, we need to add
+// ref-links again, as they are not global.
+:icons:
+:badges:
+:rig_template: link:rig-config-template.html[Template]
+:devmail: mailto:wsjt-devel at lists.berlios.de[wsjt-devel]
+
+= Drake Configuration Guide
+Available Configurations
+
+If you have configuration data for a rig that is not listed, or comments about a
+particular rig configuration, please use the {rig_template} and send it to
+{devmail}.
+
+[align="center",valign="middle",halign="center"]
+// 5 Models per line please
+|========
+|<<X1,Drake1>>|<<X2,Drake2>>|Drake3|Drake4|Drake5
+|========
+
+[[X1]]
+== Drake-1
+.Configuration Covers:
+
+* MyCall:
+* MyGrid:
+* PTT Method:
+* Pskreporter:
+* CW Id After 73:
+* CW Interval:
+* CAT NOTES:
+* DTR:
+* RTS:
+* CAT Port:
+* CAT Port Settings:
+* Split:
+* Polling:
+* Audio-In:
+* Audio-In Mono:
+* Audio-Out:
+* Audio-Out:
+
+=== OS Specific Notes
+.Notes Relating To Operating System
+
+* Windows: XP, Vista, Win7, Win8, etc.
+* Linux: Slackaware, Fedora, FreeBSD, Ubuntu, Debian, etc
+* Mac OSx: 
+
+=== Interface Notes
+.Notes Relating To Rig Interface
+
+* Navigator
+* SignaLink
+* ShackLan
+* Kam
+* DX-Doubler
+* Array Solutions
+* Home-Brew
+
+[[X2]]
+== Drake-2
+.Configuration Covers:
+
+* MyCall:
+* MyGrid:
+* PTT Method:
+* Pskreporter:
+* CW Id After 73:
+* CW Interval:
+* CAT NOTES:
+- Note-1/2/3
+* DTR:
+* RTS:
+* CAT Port:
+* CAT Port Settings:
+* Split:
+* Polling:
+* Audio
+-In:
+* Audio-In Mono:
+* Audio-Out:
+* Audio-Out:
+
+=== OS Specific Notes
+.Notes Relating To Operating System
+
+* Windows: XP, Vista, Win7, Win8, etc.
+* Linux: Slackaware, Fedora, FreeBSD, Ubuntu, Debian, etc
+* Mac OSx: 
+
+=== Interface Notes
+.Notes Relating To Rig Interface
+
+* Navigator
+* SignaLink
+* ShackLan
+* Kam
+* DX-Doubler
+* Array Solutions
+* Home-Brew
+
diff --git a/doc/user_guide/rig-config-elecraft.adoc b/doc/user_guide/rig-config-elecraft.adoc
new file mode 100644
index 0000000..34a05f2
--- /dev/null
+++ b/doc/user_guide/rig-config-elecraft.adoc
@@ -0,0 +1,104 @@
+// Status=needsupdate
+// This is a comment line, anything with // is ignored at process time.
+// because the page is not a main page include, we need to add
+// ref-links again, as they are not global.
+:icons:
+:badges:
+:rig_template: link:rig-config-template.html[Template]
+:devmail: mailto:wsjt-devel at lists.berlios.de[wsjt-devel]
+
+= ElectroCraft Configuration Guide
+Available Configurations
+
+If you have configuration data for a rig that is not listed, or comments about a
+particular rig configuration, please use the {rig_template} and send it to
+{devmail}.
+
+[align="center",valign="middle",halign="center"]
+// 5 Models per line please
+|========
+|<<X1,ElectroCraft1>>|<<X2,ElectroCraft2>>|ElectroCraft3|ElectroCraft4|ElectroCraft5
+|========
+
+[[X1]]
+== ElectroCraft-1
+.Configuration Covers:
+
+* MyCall:
+* MyGrid:
+* PTT Method:
+* Pskreporter:
+* CW Id After 73:
+* CW Interval:
+* CAT NOTES:
+* DTR:
+* RTS:
+* CAT Port:
+* CAT Port Settings:
+* Split:
+* Polling:
+* Audio-In:
+* Audio-In Mono:
+* Audio-Out:
+* Audio-Out:
+
+=== OS Specific Notes
+.Notes Relating To Operating System
+
+* Windows: XP, Vista, Win7, Win8, etc.
+* Linux: Slackaware, Fedora, FreeBSD, Ubuntu, Debian, etc
+* Mac OSx: 
+
+=== Interface Notes
+.Notes Relating To Rig Interface
+
+* Navigator
+* SignaLink
+* ShackLan
+* Kam
+* DX-Doubler
+* Array Solutions
+* Home-Brew
+
+[[X2]]
+== ElectroCraft-2
+.Configuration Covers:
+
+* MyCall:
+* MyGrid:
+* PTT Method:
+* Pskreporter:
+* CW Id After 73:
+* CW Interval:
+* CAT NOTES:
+- Note-1/2/3
+* DTR:
+* RTS:
+* CAT Port:
+* CAT Port Settings:
+* Split:
+* Polling:
+* Audio
+-In:
+* Audio-In Mono:
+* Audio-Out:
+* Audio-Out:
+
+=== OS Specific Notes
+.Notes Relating To Operating System
+
+* Windows: XP, Vista, Win7, Win8, etc.
+* Linux: Slackaware, Fedora, FreeBSD, Ubuntu, Debian, etc
+* Mac OSx: 
+
+=== Interface Notes
+.Notes Relating To Rig Interface
+
+* Navigator
+* SignaLink
+* ShackLan
+* Kam
+* DX-Doubler
+* Array Solutions
+* Home-Brew
+
diff --git a/doc/user_guide/rig-config-flexrad.adoc b/doc/user_guide/rig-config-flexrad.adoc
new file mode 100644
index 0000000..dd17de5
--- /dev/null
+++ b/doc/user_guide/rig-config-flexrad.adoc
@@ -0,0 +1,104 @@
+// Status=needsupdate
+// This is a comment line, anything with // is ignored at process time.
+// because the page is not a main page include, we need to add
+// ref-links again, as they are not global.
+:icons:
+:badges:
+:rig_template: link:rig-config-template.html[Template]
+:devmail: mailto:wsjt-devel at lists.berlios.de[wsjt-devel]
+
+= Flex Radio Configuration Guide
+Available Configurations
+
+If you have configuration data for a rig that is not listed, or comments about a
+particular rig configuration, please use the {rig_template} and send it to
+{devmail}.
+
+[align="center",valign="middle",halign="center"]
+// 5 Models per line please
+|========
+|<<X1,Flex1>>|<<X2,Flex2>>|Flex3|Flex4|Flex5
+|========
+
+[[X1]]
+== Flex-1
+.Configuration Covers:
+
+* MyCall:
+* MyGrid:
+* PTT Method:
+* Pskreporter:
+* CW Id After 73:
+* CW Interval:
+* CAT NOTES:
+* DTR:
+* RTS:
+* CAT Port:
+* CAT Port Settings:
+* Split:
+* Polling:
+* Audio-In:
+* Audio-In Mono:
+* Audio-Out:
+* Audio-Out:
+
+=== OS Specific Notes
+.Notes Relating To Operating System
+
+* Windows: XP, Vista, Win7, Win8, etc.
+* Linux: Slackaware, Fedora, FreeBSD, Ubuntu, Debian, etc
+* Mac OSx: 
+
+=== Interface Notes
+.Notes Relating To Rig Interface
+
+* Navigator
+* SignaLink
+* ShackLan
+* Kam
+* DX-Doubler
+* Array Solutions
+* Home-Brew
+
+[[X2]]
+== Flex-2
+.Configuration Covers:
+
+* MyCall:
+* MyGrid:
+* PTT Method:
+* Pskreporter:
+* CW Id After 73:
+* CW Interval:
+* CAT NOTES:
+- Note-1/2/3
+* DTR:
+* RTS:
+* CAT Port:
+* CAT Port Settings:
+* Split:
+* Polling:
+* Audio
+-In:
+* Audio-In Mono:
+* Audio-Out:
+* Audio-Out:
+
+=== OS Specific Notes
+.Notes Relating To Operating System
+
+* Windows: XP, Vista, Win7, Win8, etc.
+* Linux: Slackaware, Fedora, FreeBSD, Ubuntu, Debian, etc
+* Mac OSx: 
+
+=== Interface Notes
+.Notes Relating To Rig Interface
+
+* Navigator
+* SignaLink
+* ShackLan
+* Kam
+* DX-Doubler
+* Array Solutions
+* Home-Brew
+
diff --git a/doc/user_guide/rig-config-icom.adoc b/doc/user_guide/rig-config-icom.adoc
new file mode 100644
index 0000000..2e626ad
--- /dev/null
+++ b/doc/user_guide/rig-config-icom.adoc
@@ -0,0 +1,104 @@
+// Status=needsupdate
+// This is a comment line, anything with // is ignored at process time.
+// because the page is not a main page include, we need to add
+// ref-links again, as they are not global.
+:icons:
+:badges:
+:rig_template: link:rig-config-template.html[Template]
+:devmail: mailto:wsjt-devel at lists.berlios.de[wsjt-devel]
+
+= Icom Configuration Guide
+Available Configurations
+
+If you have configuration data for a rig that is not listed, or comments about a
+particular rig configuration, please use the {rig_template} and send it to
+{devmail}.
+
+[align="center",valign="middle",halign="center"]
+// 5 Models per line please
+|========
+|<<X1,Icom1>>|<<X2,Icom2>>|Icom3|Icom4|Icom5
+|========
+
+[[X1]]
+== Icom-1
+.Configuration Covers:
+
+* MyCall:
+* MyGrid:
+* PTT Method:
+* Pskreporter:
+* CW Id After 73:
+* CW Interval:
+* CAT NOTES:
+* DTR:
+* RTS:
+* CAT Port:
+* CAT Port Settings:
+* Split:
+* Polling:
+* Audio-In:
+* Audio-In Mono:
+* Audio-Out:
+* Audio-Out:
+
+=== OS Specific Notes
+.Notes Relating To Operating System
+
+* Windows: XP, Vista, Win7, Win8, etc.
+* Linux: Slackaware, Fedora, FreeBSD, Ubuntu, Debian, etc
+* Mac OSx: 
+
+=== Interface Notes
+.Notes Relating To Rig Interface
+
+* Navigator
+* SignaLink
+* ShackLan
+* Kam
+* DX-Doubler
+* Array Solutions
+* Home-Brew
+
+[[X2]]
+== Icom-2
+.Configuration Covers:
+
+* MyCall:
+* MyGrid:
+* PTT Method:
+* Pskreporter:
+* CW Id After 73:
+* CW Interval:
+* CAT NOTES:
+- Note-1/2/3
+* DTR:
+* RTS:
+* CAT Port:
+* CAT Port Settings:
+* Split:
+* Polling:
+* Audio
+-In:
+* Audio-In Mono:
+* Audio-Out:
+* Audio-Out:
+
+=== OS Specific Notes
+.Notes Relating To Operating System
+
+* Windows: XP, Vista, Win7, Win8, etc.
+* Linux: Slackaware, Fedora, FreeBSD, Ubuntu, Debian, etc
+* Mac OSx: 
+
+=== Interface Notes
+.Notes Relating To Rig Interface
+
+* Navigator
+* SignaLink
+* ShackLan
+* Kam
+* DX-Doubler
+* Array Solutions
+* Home-Brew
+
diff --git a/doc/user_guide/rig-config-kenwood.adoc b/doc/user_guide/rig-config-kenwood.adoc
new file mode 100644
index 0000000..708d269
--- /dev/null
+++ b/doc/user_guide/rig-config-kenwood.adoc
@@ -0,0 +1,104 @@
+// Status=needsupdate
+// This is a comment line, anything with // is ignored at process time.
+// because the page is not a main page include, we need to add
+// ref-links again, as they are not global.
+:icons:
+:badges:
+:rig_template: link:rig-config-template.html[Template]
+:devmail: mailto:wsjt-devel at lists.berlios.de[wsjt-devel]
+
+= Kenwood Configuration Guide
+Available Configurations
+
+If you have configuration data for a rig that is not listed, or comments about a
+particular rig configuration, please use the {rig_template} and send it to
+{devmail}.
+
+[align="center",valign="middle",halign="center"]
+// 5 Models per line please
+|========
+|<<X1,Kenwood1>>|<<X2,Kenwood2>>|Kenwood3|Kenwood4|Kenwood5
+|========
+
+[[X1]]
+== Kenwood-1
+.Configuration Covers:
+
+* MyCall:
+* MyGrid:
+* PTT Method:
+* Pskreporter:
+* CW Id After 73:
+* CW Interval:
+* CAT NOTES:
+* DTR:
+* RTS:
+* CAT Port:
+* CAT Port Settings:
+* Split:
+* Polling:
+* Audio-In:
+* Audio-In Mono:
+* Audio-Out:
+* Audio-Out:
+
+=== OS Specific Notes
+.Notes Relating To Operating System
+
+* Windows: XP, Vista, Win7, Win8, etc.
+* Linux: Slackaware, Fedora, FreeBSD, Ubuntu, Debian, etc
+* Mac OSx: 
+
+=== Interface Notes
+.Notes Relating To Rig Interface
+
+* Navigator
+* SignaLink
+* ShackLan
+* Kam
+* DX-Doubler
+* Array Solutions
+* Home-Brew
+
+[[X2]]
+== Kenwood-2
+.Configuration Covers:
+
+* MyCall:
+* MyGrid:
+* PTT Method:
+* Pskreporter:
+* CW Id After 73:
+* CW Interval:
+* CAT NOTES:
+- Note-1/2/3
+* DTR:
+* RTS:
+* CAT Port:
+* CAT Port Settings:
+* Split:
+* Polling:
+* Audio
+-In:
+* Audio-In Mono:
+* Audio-Out:
+* Audio-Out:
+
+=== OS Specific Notes
+.Notes Relating To Operating System
+
+* Windows: XP, Vista, Win7, Win8, etc.
+* Linux: Slackaware, Fedora, FreeBSD, Ubuntu, Debian, etc
+* Mac OSx: 
+
+=== Interface Notes
+.Notes Relating To Rig Interface
+
+* Navigator
+* SignaLink
+* ShackLan
+* Kam
+* DX-Doubler
+* Array Solutions
+* Home-Brew
+
diff --git a/doc/user_guide/rig-config-main.adoc b/doc/user_guide/rig-config-main.adoc
new file mode 100644
index 0000000..0f2099e
--- /dev/null
+++ b/doc/user_guide/rig-config-main.adoc
@@ -0,0 +1,33 @@
+// Status=review
+:adat: link:rig-config-adat.html[ ADAT]
+:alinco: link:rig-config-alinco.html[ Alinco ]
+:aor: link:rig-config-aor.html[ AOR ]
+:drake: link:rig-config-drake.html[ Drake ]
+:elecraft: link:rig-config-elecraft.html[ Elecraft ]
+:flexrad: link:rig-config-flexrad.html[ Flex Radio ]
+:kenwood: link:rig-config-kenwood.html[ Kenwood ]
+:icom: link:rig-config-icom.html[ Icom ]
+:rig_template: link:rig-config-template.html[Template]
+:softrock: link:rig-config-softrock.html[ Soft Rock ]
+:tentec: link:rig-config-tentec.html[ Ten Tec ]
+:yaesu: link:rig-config-yaesu.html[Yaesu]
+
+Some rigs work with DTR, RTS, Polling, CAT, and PTT while others do
+not. The number of possible combinations is virtually endless.  The
+purpose of this section is to provide configuration information for
+specific rig models, e.g. Icom 756 Pro-III, Kenwood TS-2000, Yaesu
+FT-1000MP, Flex-5000, etc. This is a work-in-progress, and some rigs
+may never be covered.
+
+IMPORTANT: If you have configuration data for a rig that is not listed, or
+comments about a particular rig configuration, please use the
+{rig_template} and send it to {devmail}.
+
+.Select Manufacturer
+[align="center",valign="middle",halign="center"]
+|========
+|{adat}|{aor}|{alinco}|{drake}|{elecraft}
+|{flexrad}|{kenwood}|{icom}|{softrock}|{tentec}
+|{yaesu}|{rig_template}|||
+|========
+
diff --git a/doc/user_guide/rig-config-softrock.adoc b/doc/user_guide/rig-config-softrock.adoc
new file mode 100644
index 0000000..a2319d8
--- /dev/null
+++ b/doc/user_guide/rig-config-softrock.adoc
@@ -0,0 +1,104 @@
+// Status=needsupdate
+// This is a comment line, anything with // is ignored at process time.
+// because the page is not a main page include, we need to add
+// ref-links again, as they are not global.
+:icons:
+:badges:
+:rig_template: link:rig-config-template.html[Template]
+:devmail: mailto:wsjt-devel at lists.berlios.de[wsjt-devel]
+
+= SoftRock Configuration Guide
+Available Configurations
+
+If you have configuration data for a rig that is not listed, or comments about a
+particular rig configuration, please use the {rig_template} and send it to
+{devmail}.
+
+[align="center",valign="middle",halign="center"]
+// 5 Models per line please
+|========
+|<<X1,SR1>>|<<X2,SR2>>|SR3|SR4|SR5
+|========
+
+[[X1]]
+== SR-1
+.Configuration Covers:
+
+* MyCall:
+* MyGrid:
+* PTT Method:
+* Pskreporter:
+* CW Id After 73:
+* CW Interval:
+* CAT NOTES:
+* DTR:
+* RTS:
+* CAT Port:
+* CAT Port Settings:
+* Split:
+* Polling:
+* Audio-In:
+* Audio-In Mono:
+* Audio-Out:
+* Audio-Out:
+
+=== OS Specific Notes
+.Notes Relating To Operating System
+
+* Windows: XP, Vista, Win7, Win8, etc.
+* Linux: Slackaware, Fedora, FreeBSD, Ubuntu, Debian, etc
+* Mac OSx: 
+
+=== Interface Notes
+.Notes Relating To Rig Interface
+
+* Navigator
+* SignaLink
+* ShackLan
+* Kam
+* DX-Doubler
+* Array Solutions
+* Home-Brew
+
+[[X2]]
+== SR-2
+.Configuration Covers:
+
+* MyCall:
+* MyGrid:
+* PTT Method:
+* Pskreporter:
+* CW Id After 73:
+* CW Interval:
+* CAT NOTES:
+- Note-1/2/3
+* DTR:
+* RTS:
+* CAT Port:
+* CAT Port Settings:
+* Split:
+* Polling:
+* Audio
+-In:
+* Audio-In Mono:
+* Audio-Out:
+* Audio-Out:
+
+=== OS Specific Notes
+.Notes Relating To Operating System
+
+* Windows: XP, Vista, Win7, Win8, etc.
+* Linux: Slackaware, Fedora, FreeBSD, Ubuntu, Debian, etc
+* Mac OSx: 
+
+=== Interface Notes
+.Notes Relating To Rig Interface
+
+* Navigator
+* SignaLink
+* ShackLan
+* Kam
+* DX-Doubler
+* Array Solutions
+* Home-Brew
+
diff --git a/doc/user_guide/rig-config-template.adoc b/doc/user_guide/rig-config-template.adoc
new file mode 100644
index 0000000..474dc1a
--- /dev/null
+++ b/doc/user_guide/rig-config-template.adoc
@@ -0,0 +1,60 @@
+// Status=review
+// because the page is not a main page include, we need to add
+// ref-links again, as they are not global.
+:icons:
+:badges:
+:devmail: mailto:wsjt-devel at lists.berlios.de[wsjt-devel]
+= Rig Template
+
+This is a simple guide for providing rig configuration data for the WSJT-X
+User Guide. Try to fill out as much as possible, but do not worry if you cannot
+fill in all the fields. OS Specific & Interface Notes are a bonus.
+
+* Copy and paste the template into a text file.
+* Save as the rig's model.txt: rig-confg-ic756p3.txt
+* Email the file to {devmail} for inclusion.
+* Alternatively, join the team and submit the updates directly.
+
+.Copy & Paste the following:
+----------
+Manufacturer:
+Model:
+.Configuration Covers:
+
+* MyCall:
+* MyGrid:
+* PTT Method:
+* Pskreporter:
+* CW Id After 73:
+* CW Interval:
+* CAT NOTES:
+* DTR:
+* RTS:
+* CAT Port:
+* CAT Port Settings:
+* Split:
+* Polling:
+* Audio-In:
+* Audio-In Mono:
+* Audio-Out:
+* Audio-Out:
+
+=== OS Specific Notes
+.Notes Relating To Operating System
+
+* Windows: XP, Vista, Win7, Win8, etc.
+* Linux: Slackaware, Fedora, FreeBSD, Ubuntu, Debian, etc
+* Mac OSx: 
+
+=== Interface Notes
+.Notes Relating To Rig Interface
+
+* Navigator
+* SignaLink
+* ShackLan
+* Kam
+* DX-Doubler
+* Array Solutions
+* Home-Brew
+----------
+
diff --git a/doc/user_guide/rig-config-tentec.adoc b/doc/user_guide/rig-config-tentec.adoc
new file mode 100644
index 0000000..7d4f14e
--- /dev/null
+++ b/doc/user_guide/rig-config-tentec.adoc
@@ -0,0 +1,104 @@
+// Status=needsupdate
+// This is a comment line, anything with // is ignored at process time.
+// because the page is not a main page include, we need to add
+// ref-links again, as they are not global.
+:icons:
+:badges:
+:rig_template: link:rig-config-template.html[Template]
+:devmail: mailto:wsjt-devel at lists.berlios.de[wsjt-devel]
+
+= Ten Tec Configuration Guide
+Available Configurations
+
+If you have configuration data for a rig that is not listed, or comments about a
+particular rig configuration, please use the {rig_template} and send it to
+{devmail}.
+
+[align="center",valign="middle",halign="center"]
+// 5 Models per line please
+|========
+|<<X1,TenTec1>>|<<X2,TenTec2>>|TenTec3|TenTec4|TenTec5
+|========
+
+[[X1]]
+== TenTec-1
+.Configuration Covers:
+
+* MyCall:
+* MyGrid:
+* PTT Method:
+* Pskreporter:
+* CW Id After 73:
+* CW Interval:
+* CAT NOTES:
+* DTR:
+* RTS:
+* CAT Port:
+* CAT Port Settings:
+* Split:
+* Polling:
+* Audio-In:
+* Audio-In Mono:
+* Audio-Out:
+* Audio-Out:
+
+=== OS Specific Notes
+.Notes Relating To Operating System
+
+* Windows: XP, Vista, Win7, Win8, etc.
+* Linux: Slackaware, Fedora, FreeBSD, Ubuntu, Debian, etc
+* Mac OSx: 
+
+=== Interface Notes
+.Notes Relating To Rig Interface
+
+* Navigator
+* SignaLink
+* ShackLan
+* Kam
+* DX-Doubler
+* Array Solutions
+* Home-Brew
+
+[[X2]]
+== TenTec-2
+.Configuration Covers:
+
+* MyCall:
+* MyGrid:
+* PTT Method:
+* Pskreporter:
+* CW Id After 73:
+* CW Interval:
+* CAT NOTES:
+- Note-1/2/3
+* DTR:
+* RTS:
+* CAT Port:
+* CAT Port Settings:
+* Split:
+* Polling:
+* Audio
+-In:
+* Audio-In Mono:
+* Audio-Out:
+* Audio-Out:
+
+=== OS Specific Notes
+.Notes Relating To Operating System
+
+* Windows: XP, Vista, Win7, Win8, etc.
+* Linux: Slackaware, Fedora, FreeBSD, Ubuntu, Debian, etc
+* Mac OSx: 
+
+=== Interface Notes
+.Notes Relating To Rig Interface
+
+* Navigator
+* SignaLink
+* ShackLan
+* Kam
+* DX-Doubler
+* Array Solutions
+* Home-Brew
+
diff --git a/doc/user_guide/rig-config-yaesu.adoc b/doc/user_guide/rig-config-yaesu.adoc
new file mode 100644
index 0000000..e71d490
--- /dev/null
+++ b/doc/user_guide/rig-config-yaesu.adoc
@@ -0,0 +1,102 @@
+// Status=review
+// This is a comment line, anything with // is ignored at process time.
+// because the page is not a main page include, we need to add
+// ref-links again, as they are not global.
+:icons:
+:badges:
+:rig_template: link:rig-config-template.html[Template]
+:devmail: mailto:wsjt-devel at lists.berlios.de[wsjt-devel]
+
+= Yaesu Configuration Guide
+Available Configurations
+
+If you have configuration data for a rig that is not listed, or comments about a
+particular rig configuration, please use the {rig_template} and send it to
+{devmail}.
+
+[align="center",valign="middle",halign="center"]
+// 5 Models per line please
+|========
+|<<X1,FT-1000>>|<<X2,FT-2000>>|FT-3000|FT-5000|FT-9000
+|========
+
+[[X1]]
+== FT-1000
+.Configuration Covers FT-1000, FT-1000MP, FT-1000D
+
+* MyCall:
+* MyGrid:
+* PTT Method:
+* Pskreporter:
+* CW Id After 73:
+* CW Interval:
+* CAT NOTES:
+* DTR:
+* RTS:
+* CAT Port:
+* CAT Port Settings:
+* Split:
+* Polling:
+* Audio-In:
+* Audio-In Mono:
+* Audio-Out:
+* Audio-Out:
+
+=== OS Specific Notes
+.Notes Relating To Operating System
+
+* Windows: XP, Vista, Win7, Win8, etc.
+* Linux: Slackaware, Fedora, FreeBSD, Ubuntu, Debian, etc
+* Mac OSx: 
+
+=== Interface Notes
+.Notes Relating To Rig Interface
+
+* Navigator
+* SignaLink
+* ShackLan
+* Kam
+* DX-Doubler
+* Array Solutions
+* Home-Brew
+
+[[X2]]
+== FT-2000
+.Configuration Covers FT-2000, FT-2000D
+
+* MyCall:
+* MyGrid:
+* PTT Method:
+* Pskreporter:
+* CW Id After 73:
+* CW Interval:
+* CAT NOTES:
+* DTR:
+* RTS:
+* CAT Port:
+* CAT Port Settings:
+* Split:
+* Polling:
+* Audio-In:
+* Audio-In Mono:
+* Audio-Out:
+* Audio-Out:
+
+=== OS Specific Notes
+.Notes Relating To Operating System
+
+* Windows: XP, Vista, Win7, Win8, etc.
+* Linux: Slackaware, Fedora, FreeBSD, Ubuntu, Debian, etc
+* Mac OSx: 
+
+=== Interface Notes
+.Notes Relating To Rig Interface
+
+* Navigator
+* SignaLink
+* ShackLan
+* Kam
+* DX-Doubler
+* Array Solutions
+* Home-Brew
+
diff --git a/doc/user_guide/settings-audio.adoc b/doc/user_guide/settings-audio.adoc
new file mode 100644
index 0000000..a9ce3fd
--- /dev/null
+++ b/doc/user_guide/settings-audio.adoc
@@ -0,0 +1,20 @@
+// Status=review
+Select the *Audio* tab to configure your sound system.
+
+image::images/settings-audio.png[align="center",alt="WSJT-X Audio Configuration Screen"]
+
+- _Soundcard_: Select the audio devices to be used for *Input* and
+*Output*.  Usually the *Mono* settings will suffice, but in special
+cases you can choose *Left*, *Right*, or *Both* stereo channels.
+
+IMPORTANT: If you select the audio output device that is also your
+computer's default audio device, be sure to turn off all system sounds
+to prevent transmitting them over the air.
+
+- _Save Directory_: _WSJT-X_ can save its received audio sequences as
++.wav+ files.  A default directory for these files is provided; you
+can select another location if desired.
+
+- _JT9W Settings_: JT9W is an experimental mode designed for EME on
+the microwave bands, and is not enabled in current release versions.
+
diff --git a/doc/user_guide/settings-colors.adoc b/doc/user_guide/settings-colors.adoc
new file mode 100644
index 0000000..91df1bc
--- /dev/null
+++ b/doc/user_guide/settings-colors.adoc
@@ -0,0 +1,8 @@
+[[COLORS]]
+
+image::images/colors.png[align="center",alt="Reporting Screen"]
+
+_WSJT-X_ uses colors to highlight decoded messages that contain
+information that may be of particular interest.  Click on one of
+the buttons to select your preferred colors for any message 
+category.
diff --git a/doc/user_guide/settings-frequencies.adoc b/doc/user_guide/settings-frequencies.adoc
new file mode 100644
index 0000000..7f996aa
--- /dev/null
+++ b/doc/user_guide/settings-frequencies.adoc
@@ -0,0 +1,39 @@
+// Status=review
+
+[[FIG_BAND_SETTINGS]]
+image::images/r4148-freq-ui.png[align="center",alt="Frequency Screen"]
+
+_Working Frequencies_: By default the *Frequency* table lists the
+currently recommended dial frequencies for JT65. JT9 frequencies
+generally start 2 kHz higher.  You can modify the frequency table as
+desired.
+
+- To change an existing entry, click to select it, type a desired
+frequency in MHz, and hit *Enter* on the keyboard. The program will
+format your frequency value appropriately and add a band designator.
+
+- To add a new entry, right-click anywhere on the frequency table and
+select *Insert*.  Enter a frequency in MHz in the popup box, then
+click *OK*.  The table may include more than one frequency for a given
+band.
+
+- To delete an entry, right-click it and select *Delete*.
+
+_Station Information_: You can save *Band*, *Offset* and *Antenna
+Description* information for your station.  The antenna information
+will be included in reception reports sent to {pskreporter}.  By
+default the frequency *Offset* for each band is zero.  Nonzero offsets
+may be added if (for example) a transverter is in use.
+
+- For a simple setup approach you might want to delete any unwanted
+bands -- for example, bands where you have no equipment.  Then click
+on a *Frequency* entry and type *Ctrl+A* to ``select all,'' and
+drag-and-drop the entries onto the _Station Information_ table.  You
+can then add any transverter offsets and antenna details.
+
+- To avoid typing the same information multiple times, you can
+drag-and-drop entries between the lines of the _Station Information_
+table.
+
+- When all settings have been configured to your liking, click *OK* to
+dismiss the *Settings* window.
diff --git a/doc/user_guide/settings-general.adoc b/doc/user_guide/settings-general.adoc
new file mode 100644
index 0000000..7c18e75
--- /dev/null
+++ b/doc/user_guide/settings-general.adoc
@@ -0,0 +1,14 @@
+// Status=review
+[[FIG_CONFIG_STATION]]
+image::images/settings-ui.png[align="center",alt="Settings Window"]
+
+Select the *General* tab on the *Settings* window.  Under _Station
+Details_, enter your call sign and 4-digit or 6-digit grid locator.
+This information will be sufficient for initial tests.
+
+Meanings of remaining options on the *General* tab should be
+self-explanatory after you have made some QSOs using _WSJT-X_.  You
+may return to set these options to your preferences later.  
+
+IMPORTANT: If you are using a callsign with an add-on prefix or suffix,
+be sure to read the section <<COMP-CALL,Compound Callsigns>>.
diff --git a/doc/user_guide/settings-radio.adoc b/doc/user_guide/settings-radio.adoc
new file mode 100644
index 0000000..9b93698
--- /dev/null
+++ b/doc/user_guide/settings-radio.adoc
@@ -0,0 +1,75 @@
+// Status=review
+
+_WSJT-X_ offers CAT (Computer Aided Transceiver) control of the
+relevant features of most modern transceivers.  To configure the
+program for your radio, select the *Radio* tab.
+
+image::images/RadioTab.png[align="center",alt="Radio Tab"]
+
+- Select your radio type from the drop-down list labeled *Rig*, or
+*None* if you do not wish to use CAT control.
+
+- Alternatively, if you have configured your station for control by
+*DX Lab Suite Commander*, *Ham Radio Deluxe*, *Hamlib NET rigctl*, or
+*OmniRig*, you may select one of those program names from the *Rig*
+list.  In these cases the entry field immediately under _CAT Control_
+will be relabeled as *Network Server*.  Leave this field blank to
+access the default instance of your control program, running on the
+same computer. If the control program runs on a different computer
+and/or port, specify it here.  Hover the mouse pointer over the entry
+field to see the required formatting details.
+
+- Select *OmniRig Rig 1* or *OmniRig Rig 2* to connect to an _OmniRig_
+server running on the same computer.  Note that _OmniRig_ is available
+only under Windows.
+
+- Set *Poll Interval* to the desired interval for _WSJT-X_ to query
+your radio.  For most radios a small number (say, 1 – 3 s) is
+suitable.
+
+- _CAT Control_: To have _WSJT-X_ control the radio directly rather
+than though another program, make the following settings:
+
+* Select the *Serial Port* used to communicate with your radio. 
+
+* _Serial Port Parameters_: Set values for *Baud Rate*, *Data Bits*,
+*Stop Bits*, and *Handshake* method.  Consult your radio's user guide
+for the proper parameter values.
+
+* _Force Control Lines_: A few station setups require the CAT serial
+port’s *RTS* and/or *DTR* control lines to be forced high or
+low. Check these boxes only if you are sure they are needed.
+
+- _PTT Method_: select *VOX*, *CAT*, *DTR*, or *RTS* as the desired
+method for T/R switching.  If your choice is *DTR* or *RTS*, select
+the desired serial port (which may be the same one as used for
+CAT control).
+
+- _Transmit Audio Source_: some radios permit you to choose the
+connector that will accept Tx audio.  If this choice is enabled,
+select *Rear/Data* or *Front/Mic*.
+
+- _Mode_: _WSJT-X_ uses upper sideband mode for both transmitting and
+receiving.  Select *USB*, or choose *Data/Pkt* if your radio offers
+such an option and uses it to enable the rear-panel audio line input.
+Some radios also offer wider and/or flatter passbands when set to
+*Data/Pkt* mode.  Select *None* if you do not want _WSJT-X_ to change
+the radio's Mode setting.
+
+- _Split Operation_: Significant advantages result from using *Split*
+mode (separate VFOs for Rx and Tx) if your radio supports it.  If it
+does not, _WSJT-X_ can simulate such behavior.  Either method will
+result in a cleaner transmitted signal, by keeping the Tx audio always
+in the range 1500 to 2000 Hz so that audio harmonics cannot pass
+through the Tx sideband filter.  Select *Rig* to use the radio's Split
+mode, or *Fake It* to have _WSJT-X_ adjust the VFO frequency as
+needed, just before T/R switching occurs.  Choose *None* if you do not
+wish to use split operation.
+
+When all required settings have been made, click *Test CAT* to test
+communication between _WSJT-X_ and your radio.  The button should turn
+green to indicate that proper communication has been established.
+Failure of the CAT-control test turns the button red and displays an
+error message.  After a succesful CAT test, toggle the *Test PTT*
+button to confirm that your selected method of T/R control is working
+properly.
diff --git a/doc/user_guide/settings-reporting.adoc b/doc/user_guide/settings-reporting.adoc
new file mode 100644
index 0000000..d80fb8c
--- /dev/null
+++ b/doc/user_guide/settings-reporting.adoc
@@ -0,0 +1,16 @@
+// Status=review
+[[FIG_CONFIG_RPT]]
+image::images/reporting.png[align="center",alt="Reporting Screen"]
+
+- _Logging_: Choose any desired options from this group.  For detailed
+descriptions of their effects, see <<CONFIG_DETAILS,Configuration>> 
+in the <<COMMAND_REF,Command Reference>> section.
+
+- _Network_: Check *Enable PSK Reporter Spotting* to send reception
+reports to the {pskreporter} mapping facility.
+
+- _UDP Server_: This group of options controls the network name or
+address and port number used by a program that will receive status
+updates from WSJT-X.  It is expected that cooperating applications
+like JTAlert-X use this feature to obtain information about a 
+running WSJT-X instance.
diff --git a/doc/user_guide/settings-txmacros.adoc b/doc/user_guide/settings-txmacros.adoc
new file mode 100644
index 0000000..3014c43
--- /dev/null
+++ b/doc/user_guide/settings-txmacros.adoc
@@ -0,0 +1,16 @@
+// Status=review
+
+[[FigTxMacros]]
+image::images/tx-macros.png[align="center",alt="Tx Macros Screen"]
+
+*Tx Macros* are an aid for sending brief, frequently used free-text
+ messages.
+
+- To add a new message to the list, enter the desired text (up to 13
+characters) in the entry field at top, then click *Add*.
+
+- To remove an unwanted message, click on the message and then on
+*Delete*.
+
+- You can reorder your macro messages by using drag-and-drop. The
+new order will be preserved when _WSJT-X_ is restarted.
diff --git a/doc/user_guide/system-requirements.adoc b/doc/user_guide/system-requirements.adoc
new file mode 100644
index 0000000..80e2a94
--- /dev/null
+++ b/doc/user_guide/system-requirements.adoc
@@ -0,0 +1,12 @@
+// Status=review
+
+- SSB transceiver and antenna 
+- Computer running Windows (XP or later), Linux, or OS X
+- 1.5 GHz or faster CPU and 100 MB of available memory
+- Monitor with at least 1024 x 780 resolution
+- Computer-to-radio interface using a serial port for T/R switching, 
+  or CAT control, or VOX, as required for your radio-to-computer connections
+- Audio input and output devices supported by the operating system and 
+  capable of 48 kHz sample rate
+- Audio or equivalent USB connections between transceiver and computer  
+- A means for synchronizing the computer clock to UTC within ±1 second
diff --git a/doc/user_guide/transceiver-setup.adoc b/doc/user_guide/transceiver-setup.adoc
new file mode 100644
index 0000000..a2c6975
--- /dev/null
+++ b/doc/user_guide/transceiver-setup.adoc
@@ -0,0 +1,56 @@
+// Status=review
+.Receiver Noise Level
+
+- If it is not already highlighted in green, click the *Monitor*
+button to return to normal receive operation.  
+
+- Be sure your transceiver is set to *USB* (or *USB Data*) mode.
+
+- Use the receiver gain controls and/or the computer's audio mixer
+controls to set the background noise level (scale at lower left of
+main window) to around 30 dB when no signals are present.  You may
+find it best to reduce the RF gain control so as to minimize AGC
+action.  If necessary you can also adjust the slider next to the dB
+scale, but note that the overall dynamic range will be best with this
+slider not too far from its mid-point.
+
+.Bandwidth and Frequency Setting
+
+- If your transceiver offers more than one bandwidth setting in USB
+mode, you should normally choose the widest one possible, up to about
+5 kHz.  This choice has the desirable effect of allowing the *Wide
+Graph* (waterfall and 2D spectrum) to display the JT65 and JT9
+sub-bands simultaneously on most HF bands.  Further details are
+provided in the <<TUTORIAL,Tutorial>> section.
+
+- If you have only a standard SSB filter you won’t be able to display
+more than about 2.7 kHz bandwidth.  Depending on the exact dial
+frequency setting, you can display the full sub-band generally used
+for one mode (JT65 or JT9) and part of the sub-band for the other
+mode.
+
+- Of course, you might prefer to concentrate on one mode at a time,
+setting your dial frequency to (say) 14.076 for JT65 or 14.078 for
+JT9.  Present conventions have the nominal JT9 dial frequency 2 kHz
+higher than the JT65 dial frequency.  A checkbox labeled *+2 kHz*,
+just below the *Band* selector, makes the appropriate frequency
+settings easy.
+
+.Transmitter Audio Level
+
+* Click the *Tune* button on the main screen to switch the
+radio into transmit mode and generate a steady audio tone. 
+
+* Listen to the generated audio tone using your radio’s *Monitor*
+facility. The transmitted tone should be perfectly smooth, with no
+clicks or glitches.
+
+* Open the computer’s audio mixer controls for output (``Playback'')
+devices and adjust the volume slider downward from its maximum until
+the RF output from your transmitter falls by around ten percent.  This
+will be a good level for audio drive.
+
+* Alternatively, you can make the Tx audio level adjustment using the
+digital slider labeled *Pwr* at the right edge of the main window.
+
+* Toggle the *Tune* button once more to stop your test transmission. 
diff --git a/doc/user_guide/tutorial-example1.adoc b/doc/user_guide/tutorial-example1.adoc
new file mode 100644
index 0000000..66625a4
--- /dev/null
+++ b/doc/user_guide/tutorial-example1.adoc
@@ -0,0 +1,96 @@
+// Status=review
+
+For this step and the next, you may want to pretend you are K1JT
+by entering that callsign temporarily as *My Call* on the 
+*Settings | General* tab.  Your results should then be identical to
+those shown in the screen shot below.
+
+.Open a Wave File:
+
+- Select *File | Open* and select the file
++...\save\samples\130418_1742.wav+. When the file opens you should see
+something similar to the to the following screen shot:
+
+[[X12]]
+image::images/main-ui-1.5.png[align="center",alt="Main UI and Wide Graph"]
+
+.Decoding Overview
+
+Decoding takes place at the end of a receive sequence and is proceeds
+in two steps.  The first decode takes place at the selected Rx
+frequency, indicated by the U-shaped green marker on the waterfall
+scale.  Results appear in both the left (*Band Activity*) and right
+(*Rx Frequency*) text windows on the main screen. The program then
+finds and decodes all signals in the selected mode over the displayed
+frequency range. The red marker indicates your Tx frequency.
+
+Seven JT9 signals are present in the example file, all decodable.
+When this file was recorded KF4RWA was finishing a QSO with K1JT.
+Since the green marker was placed at his audio frequency, 1224 Hz, his
+message ``K1JT KF4RWA 73'' is decoded first and appears in the *Rx
+Frequency* window. The *Band Activity* window shows this message plus
+all decodes at other frequencies.  By default lines containing CQ are
+highlighted in green, and lines with *My Call* (in this case K1JT) in
+red.
+
+[[X13]]
+.Decoding Controls
+
+To gain some feeling for controls frequently used when making QSOs,
+try clicking with the mouse on the decoded text lines and on the
+waterfall spectral display. You should be able to confirm the
+following behavior:
+
+- Double-click on either of the decoded lines highlighted in
+green. This action produces the following results:
+
+** Callsign and locator of a station calling CQ are copied to the *DX
+Call* and *DX Grid* entry fields.
+
+** Messages are generated for a standard minimal QSO.
+
+** The *Tx even* box is checked or cleared appropriately, so that you
+will transmit in the proper (odd or even) minutes.
+
+** The Rx and Tx frequency markers are moved to the frequency of the
+CQing station.
+
+** The *Gen Msg* (``generated message'') radio button at bottom right 
+of the main window is selected.
+
+** If you had checked *Double-click on call sets Tx Enable* on the
+*Setup* menu, *Enable Tx* would be activated and a transmission would
+start automatically at the proper time.
+
+- Double-click on the decoded message ``K1JT N5KDV EM41'',
+highlighted in red.  Results will be similar to those in the
+previous step, except the Tx frequency (red marker) is not
+moved.  Such messages are usually in response to your own CQ, or from
+a tail-ender, and you probably want your Tx frequency to stay where it
+was.
+
+- By holding down the *Ctrl* key when double-clicking on a decoded
+line you can cause both Tx and Rx frequencies to be moved.  This
+behavior can also be forced by checking *Lock Tx=Rx*.
+
+- Double-click on the message from KF4RWA in either window. He is
+sending ``73'' to K1JT, signifying that the QSO is over.  Most likely
+you want to send 73 to him, so the message ``KF4RWA K1JT 73'' is
+automatically generated and selected for your next transmission.
+(Alternatively, you might choose to send a free text message or to
+call CQ again.)
+
+- Click somewhere on the waterfall to set Rx frequency (green marker).
+
+- Ctrl-click on the waterfall to set both Rx and Tx frequencies.
+
+- Double-click on a signal in the waterfall to set Rx frequency and
+start a narrow-band decode there. Decoded text will appear in the
+right window only.
+
+- Ctrl-double-click on a signal to set both Rx and Tx frequencies and
+decode at the new frequency.
+
+- Click *Erase* to clear the right window. 
+
+- Double-click *Erase* to clear both text windows.
diff --git a/doc/user_guide/tutorial-example2.adoc b/doc/user_guide/tutorial-example2.adoc
new file mode 100644
index 0000000..6ac2e2f
--- /dev/null
+++ b/doc/user_guide/tutorial-example2.adoc
@@ -0,0 +1,117 @@
+// Status=review
+.Wide Graph Settings:
+
+- Set *Bins/Pixel* = 7
+- Adjust the width of the Wide Graph window so that the upper
+frequency limit is approximately 4000 Hz.
+
+.Main Window:
+- Select *JT9+JT65* on the *Mode* menu.
+- Toggle the *Tx mode* button to read *Tx JT65*, and set the Tx and Rx
+frequencies to 1718 Hz.
+- Double-click on *Erase* to clear both text windows.
+
+.Open a Wave File:
+
+- Select *File | Open* and navigate to +...\save\samples\130610_2343.wav+.  
+The waterfall should look like this:
+
+//.130610_2343.wav Decode
+[[X14]]
+image::images/130610_2343-wav-80.png[align="left",alt="Wide Graph Decode 130610_2343"]
+
+IMPORTANT: Notice the [blue]*BLUE* marker on the waterfall scale, here
+set at 2500 Hz.  Its position is set by the spinner control *JT65 nnnn
+JT9*, where nnnn is a frequency in Hz. In *JT9+JT65* mode the program
+will automatically decode JT9 signals only above this frequency.
+
+JT9 signals appear in the *Cumulative* spectrum as nearly rectangular
+shapes about 16 Hz wide.  They have no clearly visible sync tone like
+the one at the low-frequency edge of all JT65 signals.  By convention
+the nominal frequency of both JT9 and JT65 signals is taken to be that
+of the lowest tone, at the left edge of its spectrum.
+
+This sample file contains 17 decodable signals — nine in JT65 mode
+(flagged with the character # in the decoded text windows), and eight
+in JT9 mode (flagged with @).  On multi-core computers the decoders
+for JT9 and JT65 modes run simultaneously, so their results will be
+interspersed.  The *Band Activity* window contains all decodes (you
+might need to scroll back in the window to see some of them).  A
+signal at the frequency specified by the green marker is given
+decoding priority, and its message is displayed in the *Rx Frequency*
+window.
+
+[[FigDecodes]]
+image::images/decodes.png[align="center"]
+
+- Confirm that mouse-click behavior is similar to that described
+earlier, in <<TUT_EX1,Example 1>>.  _WSJT-X_ automatically determines
+the mode of each JT9 or JT65 message.
+
+IMPORTANT: When you double-click on a signal in the waterfall it will be
+properly decoded even if on the ``wrong'' side of the *JT65 nnnn JT9*
+marker.  The Tx mode automatically switches to that of the decoded
+signal and the Rx and Tx frequency markers on the waterfall scale
+resize themselves accordingly. When selecting a JT65 signal, click on
+the sync tone at its left edge.
+
+- Double-click on the waterfall near 815 Hz: a JT65 message
+originating from W7VP will be decoded and appear in the *Rx Frequency*
+window.  Between the *UTC* and *Freq* columns on the decoded text line
+you will find *dB*, the measured signal-to-noise ratio, and *DT*, the
+signal's time offset in seconds relative to your computer clock.
+
+[width="70%",cols="3,^3,^3,^4,^4,30",options="header"]
+|=================================
+|UTC|dB|DT|Freq|Mode|Message
+|+2343+|+-7+|+0.3+|+815+|+#+|+KK4DSD W7VP -16+
+|=================================
+
+- Double-click on the waterfall at 3196 Hz.  The program will decode a
+JT9 message from IZ0MIT:
+
+[width="70%",cols="3,^3,^3,^4,^4,30",options="header"]
+|=====================================
+|UTC|dB|DT|Freq|Mode|Message
+|+2343+|+-7+|+0.3+|+3196+|+ at +|+WB8QPG IZ0MIT -11+
+|=====================================
+
+- Scroll back in the *Band Activity* window and double-click on the
+message +CQ DL7ACA JO40+. The program will set *Tx mode* to JT65 and Tx
+and Rx frequencies to that of DL7ACA, 975 Hz.  If you had checked
+*Double-click on call sets Tx Enable* on the *Setup* menu, the program
+would configure itself to start a QSO with DL7ACA.
+
+- Double-click on the decoded JT65 message +CQ TA4A KM37+.  The program
+will set Tx mode to JT9 and the Rx and Tx frequencies to 3567 Hz.  The
+program is now configured properly for a JT9 QSO with TA4A.
+
+.Reopen the First Sample File:
+- Select *File | Open* and navigate to +...\save\samples\130418_1742.wav+.
+
+Taking full advantage of the wide-band, dual-mode capability of
+_WSJT-X_ requires a receiver bandwidth of at least 4 kHz.  These
+data were recorded with a much narrower Rx bandwidth, roughly 200 to
+2400 Hz. If you have no Rx filter wider than about 2.7 kHz, you will
+be using data like this. For best viewing, adjust *Bins/Pixel* and the
+width of the Wide Graph so that only the active part of the spectrum
+shows, say 200 to 2400 Hz.  Re-open the example file after any change of
+*Bins/Pixel* or Wide Graph width, to refresh the waterfall.
+
+The signals in this file are all JT9 signals.  To decode them
+automatically in *JT9+JT65* mode you’ll need to move the *JT65 nnnn JT9*
+delimiter down to 1000 Hz or less.
+
+.Start, Zero, and Gain
+
+Now is a good time to experiment with the *Start*, *Zero*, and *Gain*
+parameters.  *Start* determines the frequency displayed at the left
+side of the waterfall scale.  *Zero* sets the baseline level for
+colors, and *Gain* sets the sensitivity for color changes.  For the
+receiver setup of this file good values are close to *Zero*=0,
+*Gain*=0.  You may want to uncheck *Flatten* when adjusting the *Zero*
+and *Gain* controls.  Re-open the wave file after each change, to see
+the new results.
+
+IMPORTANT: When finished with this Tutorial, don’t forget to re-enter
+your own callsign as *My Call* on the *Settings | General* tab.
diff --git a/doc/user_guide/tutorial-main-window.adoc b/doc/user_guide/tutorial-main-window.adoc
new file mode 100644
index 0000000..438dc81
--- /dev/null
+++ b/doc/user_guide/tutorial-main-window.adoc
@@ -0,0 +1,16 @@
+// Status=review
+
+- Click the *Stop* button on the main window to halt any data acquisition.  
+
+- Select *JT9* from the *Mode* menu and *Deepest* from the *Decode* menu.
+
+- Set the audio frequencies to *Tx 1224 Hz* and *Rx 1224 Hz*.  You
+can type numbers directly into these controls, as well as using their 
+up/down arrows.
+
+- Select *Tab 2* (below the *Decode* button) to choose the alternative
+set of controls for generating and selecting Tx messages.
+
+IMPORTANT: Sliders and spin-box controls respond to arrow key presses
+and Page Up/Down key presses, with the Page keys moving the controls
+in larger steps.
diff --git a/doc/user_guide/tutorial-wide-graph-settings.adoc b/doc/user_guide/tutorial-wide-graph-settings.adoc
new file mode 100644
index 0000000..3e50848
--- /dev/null
+++ b/doc/user_guide/tutorial-wide-graph-settings.adoc
@@ -0,0 +1,14 @@
+// Status=review
+
+- *Bins/Pixel* = 4
+- *JT65 .... JT9* = 2500
+- *Start* = 200
+- *N Avg* = 5
+- *Zero* = 0
+- *Gain* = 0
+- *Palette* = Digipan
+- *Flatten* = checked
+- Select *Cumulative* for data display.
+
+- Use the mouse to adjust the width of the *Wide Graph* so that its
+upper frequency limit is about 2400 Hz.
diff --git a/doc/user_guide/tx-rx.adoc b/doc/user_guide/tx-rx.adoc
new file mode 100644
index 0000000..eb48209
--- /dev/null
+++ b/doc/user_guide/tx-rx.adoc
@@ -0,0 +1,80 @@
+// Status=review
+.Transmitting
+
+Immediately before the start of a transmission _WSJT-X_ encodes a
+user's message and computes the sequence of tones to be sent.  The
+audio waveform is computed on-the-fly, with 16-bit integer samples
+sent to the audio output device at a 48000 Hz rate.  Generated JT65
+and JT9 signals have continuous phase and constant amplitude, and
+there are no key clicks.  The transmitter's power amplifier need not
+be highly linear.
+
+.Receiving
+
+_WSJT-X_ acquires 16-bit integer samples from the audio input device
+at a 48000 Hz rate and immediately downsamples the stream to 12000 Hz.
+Spectra from overlapping segments are computed for the waterfall
+display and saved for the decoder at intervals of 3456/12000 = 0.288
+s, half the JT9 symbol length.
+
+.Decoding
+
+At the end of a reception sequence, about 50 seconds into the UTC
+minute, received data samples are forwarded to the decoder.  For
+operator convenience the decoder goes through its full procedure
+twice: first at the selected Rx frequency, and then over the full
+displayed frequency range.  Each decoding pass can be described as a
+sequence of discrete blocks.  The functional blocks are different for
+the JT65 and JT9 modes.  In dual-mode JT9+JT65 operation on computers
+with more than one CPU, decoding computations for the two modes are
+done in parallel.
+
+The basic decoding algorithm for JT65 mode is described in the 2005
+{jt65protocol} paper.  The following list summarizes the corresponding
+algorithm for JT9 mode. Blocks are labeled here with the names of
+functional procedures in the code.
+
+[horizontal]
++sync9+::    Use sync symbols to find candidate JT9 signals 
+            in the specified frequency range
+
+Then, at the frequency of each plausible candidate:
+
+[horizontal]
++downsam9+::  Mix, filter and downsample to 16 complex 
+            samples/symbol
+
++peakdt9+::   Using sync symbols, time-align to start of JT9 symbol 
+            sequence
+
++afc9+::    Measure frequency offset and possible drift
+
++twkfreq+::   Remove frequency offset and drift
+
++symspec2+::  Compute 8-bin spectra for 69 information-carrying
+            symbols, using the time- and frequency-aligned data;
+            transform to yield 206 single-bit soft symbols
+
++interleave9+:: Remove single-bit interleaving imposed at the
+	    transmitter
+
++decode9+::   Retrieve a 72-bit user message using the sequential
+            Fano algorithm 
+
+
++unpackmsg+:: Unpack a human-readable message from the 72-bit 
+            compressed format
+
+Decoding of clean JT9 signals in a white-noise background starts to
+fail below signal-to-noise ratio -25 dB and reaches 50% copy at -26
+dB.
+
+With marginal or unrecognizable signals the sequential Fano algorithm
+can take exponentially long times.  If the +sync9+ step in the above
+sequence finds many seemingly worthy candidate signals and many of
+them turn out to be undecodable, the decoding loop can take an
+inconveniently long time.  For this reason the step labeled +decode9+
+is programmed to ``time out'' and report failure for a given signal if
+it takes too long.  The choices *Fast | Normal | Deepest* on the
+*Decode* menu provide the user with a three-step adjustment of the
+timeout limit.
diff --git a/doc/user_guide/utilities.adoc b/doc/user_guide/utilities.adoc
new file mode 100644
index 0000000..9eccc61
--- /dev/null
+++ b/doc/user_guide/utilities.adoc
@@ -0,0 +1,59 @@
+// Status=review
+
+Utility programs *+jt9code+* and *+jt65code+* let you explore the
+conversion of user-level messages into channel symbols or ``tone
+numbers,'' and back again.  These programs can be useful to someone
+designing a beacon generator for JT9 or JT65, for understanding the
+permissible structure of transmitted messages, and for studying
+behavior of the error-control codes.
+
+Channel-symbol values for JT9 run from 0 to 8, with 0 representing the
+sync tone.  The total number of symbols in a transmitted message is
+85.  To run +jt9code+, enter the program name followed by a JT9
+message enclosed in quotes.  In Windows the command and program output
+might look like this:
+
+ C:\WSJTX> jt9code "G0XYZ K1ABC FN42"
+ Message:   G0XYZ K1ABC FN42
+ Channel symbols:
+  0 0 7 3 0 3 2 5 4 0 1 7 7 7 8 0 4 8 8 2 2 1 0 1 1 3 5 4 5 6
+  8 7 0 6 0 1 8 3 3 7 8 1 1 2 4 5 8 1 5 2 0 0 8 6 0 5 8 5 1 0
+  5 8 7 7 2 0 4 6 6 6 7 6 0 1 8 8 5 7 2 5 1 5 0 4 0
+ Decoded message: G0XYZ K1ABC FN42
+
+For the corresponding program *+jt65code+* only the
+information-carrying channel symbols are shown, and the symbol values
+range from 0 to 63.  Sync synbols lie two tone intervals below data
+tone 0, and the sequential locations of sync symbols are described in
+the <<JT65PRO,JT65 Protocol>> section of this Guide.
+
+A typical execution of +jt65code+ is shown below.  The program
+displays the packed message of 72 bits, shown here as 12 six-bit
+symbol values, followed by the channel symbols:
+
+ C:\WSJTX> jt65code "G0XYZ K1ABC FN42"
+ Message:   G0XYZ K1ABC FN42
+ Packed message, 6-bit symbols:  61 36 45 30  3 55  3  2 14  5 33 40
+ Information-carrying channel symbols:
+    56 40  8 40 51 47 50 34 44 53 22 53 28 31 13 60 46  2 14 58 43
+    41 58 35  8 35  3 24  1 21 41 43  0 25 54  9 41 54  7 25 21  9
+    62 59  7 43 31 21 57 13 59 41 17 49 19 54 21 39 33 42 18  2 60
+ Decoded message: G0XYZ K1ABC FN42
+
+For an illustration of the power of the strong error-control coding in
+JT9 and JT65, try looking at the channel symbols after changing a
+single character in the message.  For example, change the grid locator
+from +FN42+ to +FN43+ in the JT65 message:
+
+ C:\Users\joe\wsjt\wsjtx_install>jt65code "G0XYZ K1ABC FN43"
+ Message:   G0XYZ K1ABC FN43
+ Packed message, 6-bit symbols:  61 36 45 30  3 55  3  2 14  5 33 41
+ Information-carrying channel symbols:
+    25 35 47  8 13  9 61 40 44  9 51  6  8 40 38 34  8  2 21 23 30
+    51 32 56 39 35  3 50 48 30  8  5 40 18 54  9 24 30 26 61 23 11
+     3 59  7  7 39  1 25 24  4 50 17 49 52 19 34  7  4 34 61  2 61
+ Decoded message: G0XYZ K1ABC FN43
+
+You will discover that every possible JT65 message differs from every
+other possible JT65 message in at least 52 of the 63
+information-carrying channel symbols.
diff --git a/doc/user_guide/wsjtx-main.adoc b/doc/user_guide/wsjtx-main.adoc
new file mode 100644
index 0000000..915d75e
--- /dev/null
+++ b/doc/user_guide/wsjtx-main.adoc
@@ -0,0 +1,205 @@
+// This is a comment line, anything with // is ignored at process time.
+= WSJT-X User Guide
+:Revision: {VERSION}
+// For web-pages, adding :badges: is ok, but is a security issue for
+// package building .deb, .rpm, etc as it exposes the IP address and the images
+// are non-free, so can't be included as part of the Debian package.
+// :badges:
+:icons:
+:numbered:
+:keywords: amateur radio weak signal communication K1JT WSJT JT65 JT9
+:description: Software for Amateur Radio Weak-Signal Communication
+:prog: WSJT-X
+
+// use global link file
+include::../common/links.adoc[]
+
+// These [[xxxx]] labels are HTML anchors, and can be used to
+// navigate though the document easily: <<INTRO,See Introduction>> will
+// place a hyper-link in your text to take you too the anchored section.
+// All major sections or points of interest should have one.
+
+// == is level (2), section 1.0, === would mean section 1.1, === would
+// be section 1.1.1. This method is used throughout the document.
+
+[[INTRO]]
+== Introduction
+include::introduction.adoc[]
+
+[[SYSREQ]]
+== System Requirements
+include::system-requirements.adoc[]
+
+[[INSTALL]]
+== Installation
+
+Installation packages for Windows, Linux, and OS X are found on the
+the {homepage}. Click on the _WSJT-X_ link at the left margin, and
+then select the appropriate package for your operating system.
+
+[[INSTALL_WIN]]
+=== Windows
+include::install-windows.adoc[]
+
+[[INSTALL_LINUX]]
+=== Linux
+include::install-linux.adoc[]
+
+[[INSTALL_OSX]]
+=== Macintosh OS X
+include::install-mac.adoc[]
+
+////
+[[SRC_CODE]]
+=== Source Code
+include::install-from-source.adoc[]
+////
+
+[[CONFIG]] 
+== Settings
+
+Select *Settings* from the *File* menu or by typing *F2* (on
+Macintosh, *Command* or *Cmd*).  The following sections describe setup
+optiions available on each of seven tabs selectable near the top of the
+window.
+
+[[GENERAL]]
+=== General
+include::settings-general.adoc[]
+
+[[RADIO]]
+=== Radio
+include::settings-radio.adoc[]
+
+[[AUDIO]]
+=== Audio
+include::settings-audio.adoc[]
+
+[[TXMACROS]]
+=== Tx Macros
+include::settings-txmacros.adoc[]
+
+[[REPORTING]]
+=== Reporting
+include::settings-reporting.adoc[]
+
+[[BAND_SETTINGS]]
+=== Frequencies
+include::settings-frequencies.adoc[]
+
+[[COLORS]]
+=== Colors
+include::settings-colors.adoc[]
+
+[[TRANSCEIVER]]
+== Transceiver Setup
+include::transceiver-setup.adoc[]
+
+[[TUTORIAL]]
+== Basic Operating Tutorial
+
+[[TUT_MAIN]]
+=== Main Window Settings
+include::tutorial-main-window.adoc[]
+
+[[TUT_WIDE_GRAPH]]
+=== Wide Graph Settings
+include::tutorial-wide-graph-settings.adoc[]
+
+[[TUT_EX1]]
+=== Sample File 1
+include::tutorial-example1.adoc[]
+
+[[TUT_EX2]]
+=== Sample File 2
+include::tutorial-example2.adoc[]
+
+[[MAKE_QSOS]]
+== Making QSOs
+include::make-qso.adoc[]
+
+[[COMMAND_REF]]
+== Command Reference
+
+[[CONTROLS_WIDE]]
+=== Wide Graph
+include::controls-functions-wide-graph.adoc[]
+
+[[CONTROLS_MAIN]]
+=== Main Window
+include::controls-functions-main-window.adoc[]
+
+[[CONTROLS_LEFT]]
+=== Controls Left
+include::controls-functions-left.adoc[]
+
+[[CONTROLS_CENTER]]
+=== Controls Center
+include::controls-functions-center.adoc[]
+
+[[CONTROLS_MSGS]]
+=== Tx Messages
+include::controls-functions-messages.adoc[]
+
+[[STATUS_BAR]]
+=== Status Bar
+include::controls-functions-status-bar.adoc[]
+
+[[MENUS]]
+=== Menus
+include::controls-functions-menus.adoc[]
+
+[[LOGGING]]
+== Logging
+include::logging.adoc[]
+
+[[COOP_PGMS]]
+== Cooperating Programs
+include::cooperating-programs.adoc[]
+
+[[PLATFORM]]
+== Platform Dependencies
+include::platform-dependencies.adoc[]
+
+
+[[FAQ]]
+== Frequently Asked Questions
+include::faq.adoc[]
+
+[[PROTOCOLS]]
+== Protocol Specifications
+
+[[JT65PRO]]
+=== JT65
+include::jt65-protocol.adoc[]
+
+[[JT9PRO]]
+=== JT9
+include::jt9-protocol.adoc[]
+
+[[JT65_JT9]]
+=== JT65 & JT9 Differences
+include::jt65-jt9-differences.adoc[]
+
+[[TXRX]]
+== Implementation Details
+include::tx-rx.adoc[]
+
+////
+[[TROUBLE_SHOOTING]]
+== Troubleshooting
+To be added (?) ...
+////
+
+[[UTIL]]
+== Utility Programs
+include::utilities.adoc[]
+
+[[ACK]]
+== Acknowledgements
+include::acknowledgements.adoc[]
+
+[[LICENSE]]
+== License
+include::../common/license.adoc[]
+
diff --git a/doc/wsjtx.conf.in b/doc/wsjtx.conf.in
new file mode 100644
index 0000000..ac3b0de
--- /dev/null
+++ b/doc/wsjtx.conf.in
@@ -0,0 +1,8 @@
+# This is an  asciidoc configuraiton file which is  processed by CMake
+# as a configuration file to substitute variables
+[attributes]
+themedir=@CMAKE_CURRENT_SOURCE_DIR@/theme/wsjt
+VERSION_MAJOR=@WSJTX_VERSION_MAJOR@
+VERSION_MINOR=@WSJTX_VERSION_MINOR@
+VERSION_PATCH=@WSJTX_VERSION_PATCH@
+VERSION=@wsjtx_VERSION@
diff --git a/ffft.f b/ffft.f
deleted file mode 100644
index 9c3c091..0000000
--- a/ffft.f
+++ /dev/null
@@ -1,69 +0,0 @@
-	subroutine ffft(d,npts,isign,ireal)
-
-C  Fourier transform of length npts=2**k, performed in place.
-C  Input data in array d, treated as complex if ireal=0, and as real if ireal=1.
-C  In either case the transform values are returned in array d, treated as
-C  complex. The DC term is d(1), and d(npts/2+1) is the term at the Nyquist
-C  frequency.  The basic algorithm is the same as Norm Brenner's FOUR1, and
-C  uses radix-2 transforms.
-
-C  J. H. Taylor, Princeton University.
-
-	complex d(npts),t,w,wstep,tt,uu
-	data pi/3.14159265359/
-
-C  Shuffle the data to bit-reversed order.
-
-	imax=npts/(ireal+1)
-	irev=1
-	do 5 i=1,imax
-	if(i.ge.irev) go to 2
-	t=d(i)
-	d(i)=d(irev)
-	d(irev)=t
-2	mmax=imax/2
-3	if(irev.le.mmax) go to 5
-	irev=irev-mmax
-	mmax=mmax/2
-	if(mmax.ge.1) go to 3
-5	irev=irev+mmax
-
-C  The radix-2 transform begins here.
-
-	api=isign*pi/2.
-	mmax=1
-6	istep=2*mmax
-	wstep=cmplx(-2.*sin(api/mmax)**2,sin(2.*api/mmax))
-	w=1.
-	do 9 m=1,mmax
-
-C  This in the inner-most loop -- optimization here is important!
-	do 8 i=m,imax,istep
-	t=w*d(i+mmax)
-	d(i+mmax)=d(i)-t
-8	d(i)=d(i)+t
-
-9	w=w*(1.+wstep)
-	mmax=istep
-	if(mmax.lt.imax) go to 6
-
-	if(ireal.eq.0) return
-
-C  Now complete the last stage of a doubled-up real transform.
-
-	jmax=imax/2 + 1
-	wstep=cmplx(-2.*sin(isign*pi/npts)**2,sin(isign*pi/imax))
-	w=1.0
-	d(imax+1)=d(1)
-
-	do 10 j=1,jmax
-	uu=cmplx(real(d(j))+real(d(2+imax-j)),aimag(d(j)) - 
-     +    aimag(d(2+imax-j)))
-	tt=w*cmplx(aimag(d(j))+aimag(d(2+imax-j)),-real(d(j)) +
-     +    real(d(2+imax-j)))
-	d(j)=uu+tt
-	d(2+imax-j)=conjg(uu-tt)
-10	w=w*(1.+wstep)
-
-	return
-	end
diff --git a/fftw3.f b/fftw3.f
deleted file mode 100644
index 3410184..0000000
--- a/fftw3.f
+++ /dev/null
@@ -1,64 +0,0 @@
-      INTEGER FFTW_R2HC
-      PARAMETER (FFTW_R2HC=0)
-      INTEGER FFTW_HC2R
-      PARAMETER (FFTW_HC2R=1)
-      INTEGER FFTW_DHT
-      PARAMETER (FFTW_DHT=2)
-      INTEGER FFTW_REDFT00
-      PARAMETER (FFTW_REDFT00=3)
-      INTEGER FFTW_REDFT01
-      PARAMETER (FFTW_REDFT01=4)
-      INTEGER FFTW_REDFT10
-      PARAMETER (FFTW_REDFT10=5)
-      INTEGER FFTW_REDFT11
-      PARAMETER (FFTW_REDFT11=6)
-      INTEGER FFTW_RODFT00
-      PARAMETER (FFTW_RODFT00=7)
-      INTEGER FFTW_RODFT01
-      PARAMETER (FFTW_RODFT01=8)
-      INTEGER FFTW_RODFT10
-      PARAMETER (FFTW_RODFT10=9)
-      INTEGER FFTW_RODFT11
-      PARAMETER (FFTW_RODFT11=10)
-      INTEGER FFTW_FORWARD
-      PARAMETER (FFTW_FORWARD=-1)
-      INTEGER FFTW_BACKWARD
-      PARAMETER (FFTW_BACKWARD=+1)
-      INTEGER FFTW_MEASURE
-      PARAMETER (FFTW_MEASURE=0)
-      INTEGER FFTW_DESTROY_INPUT
-      PARAMETER (FFTW_DESTROY_INPUT=1)
-      INTEGER FFTW_UNALIGNED
-      PARAMETER (FFTW_UNALIGNED=2)
-      INTEGER FFTW_CONSERVE_MEMORY
-      PARAMETER (FFTW_CONSERVE_MEMORY=4)
-      INTEGER FFTW_EXHAUSTIVE
-      PARAMETER (FFTW_EXHAUSTIVE=8)
-      INTEGER FFTW_PRESERVE_INPUT
-      PARAMETER (FFTW_PRESERVE_INPUT=16)
-      INTEGER FFTW_PATIENT
-      PARAMETER (FFTW_PATIENT=32)
-      INTEGER FFTW_ESTIMATE
-      PARAMETER (FFTW_ESTIMATE=64)
-      INTEGER FFTW_ESTIMATE_PATIENT
-      PARAMETER (FFTW_ESTIMATE_PATIENT=128)
-      INTEGER FFTW_BELIEVE_PCOST
-      PARAMETER (FFTW_BELIEVE_PCOST=256)
-      INTEGER FFTW_DFT_R2HC_ICKY
-      PARAMETER (FFTW_DFT_R2HC_ICKY=512)
-      INTEGER FFTW_NONTHREADED_ICKY
-      PARAMETER (FFTW_NONTHREADED_ICKY=1024)
-      INTEGER FFTW_NO_BUFFERING
-      PARAMETER (FFTW_NO_BUFFERING=2048)
-      INTEGER FFTW_NO_INDIRECT_OP
-      PARAMETER (FFTW_NO_INDIRECT_OP=4096)
-      INTEGER FFTW_ALLOW_LARGE_GENERIC
-      PARAMETER (FFTW_ALLOW_LARGE_GENERIC=8192)
-      INTEGER FFTW_NO_RANK_SPLITS
-      PARAMETER (FFTW_NO_RANK_SPLITS=16384)
-      INTEGER FFTW_NO_VRANK_SPLITS
-      PARAMETER (FFTW_NO_VRANK_SPLITS=32768)
-      INTEGER FFTW_NO_VRECURSE
-      PARAMETER (FFTW_NO_VRECURSE=65536)
-      INTEGER FFTW_NO_SIMD
-      PARAMETER (FFTW_NO_SIMD=131072)
diff --git a/getdev.cpp b/getdev.cpp
deleted file mode 100644
index 751c87f..0000000
--- a/getdev.cpp
+++ /dev/null
@@ -1,259 +0,0 @@
-#include <stdio.h>
-#define MAXDEVICES 100
-#include <string.h>
-#include <portaudio.h>
-#include <QDebug>
-
-//------------------------------------------------------- pa_get_device_info
-int pa_get_device_info (int  n,
-                        void *pa_device_name,
-                        void *pa_device_hostapi,
-                        double *pa_device_max_speed,
-                        double *pa_device_min_speed,
-                        int *pa_device_max_bytes,
-                        int *pa_device_min_bytes,
-                        int *pa_device_max_channels,
-                        int *pa_device_min_channels )
-{
-
-  (void) n ;
-  (void) pa_device_name;
-  (void) pa_device_hostapi;
-  (void) pa_device_max_speed;
-  (void) pa_device_min_speed;
-  (void) pa_device_max_bytes;
-  (void) pa_device_min_bytes;
-  (void) pa_device_max_channels;
-  (void) pa_device_min_channels;
-  const PaDeviceInfo *deviceInfo;
-  PaError pa_err;
-  PaStreamParameters inputParameters;
-  int i,j, speed_warning;
-  int minBytes, maxBytes;
-  double maxStandardSampleRate;
-  double minStandardSampleRate;
-  int minInputChannels;
-  int maxInputChannels;
-
-// negative terminated  list
-  static double standardSampleRates[] = {8000.0, 9600.0,
-        11025.0, 12000.0, 16000.0, 22050.0, 24000.0, 32000.0,
-        44100.0, 48000.0, 88200.0, 96000.0, 192000.0, -1};
-// *******************************************************
-
-
-  *pa_device_max_speed=0;
-  *pa_device_min_speed=0;
-  *pa_device_max_bytes=0;
-  *pa_device_min_bytes=0;
-  *pa_device_max_channels=0;
-  *pa_device_min_channels=0;
-  minInputChannels=0;
-  if(n >= Pa_GetDeviceCount() ) return -1;
-  deviceInfo = Pa_GetDeviceInfo(n);
-  if (deviceInfo->maxInputChannels==0) return -1;
-  sprintf((char*)(pa_device_name),"%s",deviceInfo->name);
-  sprintf((char*)(pa_device_hostapi),"%s",
-          Pa_GetHostApiInfo( deviceInfo->hostApi )->name);
-  speed_warning=0;
-
-// bypass bug in Juli@ ASIO driver:
-// this driver hangs after a Pa_IsFormatSupported call
-  i = strncmp(deviceInfo->name, "ASIO 2.0 - ESI Juli@", 19);
-  if (i == 0) {
-    minStandardSampleRate=44100;
-    maxStandardSampleRate=192000;
-    minBytes=1;
-    maxBytes=4;
-    maxInputChannels= deviceInfo->maxInputChannels;
-    minInputChannels= 1;
-    goto end_pa_get_device_info;
-  }
-
-// Investigate device capabilities.
-// Check min and max samplerates  with 16 bit data.
-  maxStandardSampleRate=0;
-  minStandardSampleRate=0;
-  inputParameters.device = n;
-  inputParameters.channelCount = deviceInfo->maxInputChannels;
-  inputParameters.sampleFormat = paInt16;
-  inputParameters.suggestedLatency = 0;
-  inputParameters.hostApiSpecificStreamInfo = NULL;
-
-// ************************************************************************
-//filter for portaudio Windows hostapi's with non experts.
-//only allow ASIO or WASAPI or WDM-KS
-  i = strncmp(Pa_GetHostApiInfo(deviceInfo->hostApi)->name, "ASIO", 4);
-  if (i==0 ) goto end_filter_hostapi;
-  i = strncmp(Pa_GetHostApiInfo(deviceInfo->hostApi)->name,
-              "Windows WASAPI", 14);
-  if (i==0 ) goto end_filter_hostapi;
-  i = strncmp(Pa_GetHostApiInfo(deviceInfo->hostApi)->name,
-              "Windows WDM-KS", 14);
-  if (i==0 ) goto end_filter_hostapi;
-  speed_warning=1;
-end_filter_hostapi:;
-
-// ************************************************************************
-  i=0;
-  while(standardSampleRates[i] > 0 && minStandardSampleRate==0) {
-    pa_err=Pa_IsFormatSupported(&inputParameters, NULL,
-                                standardSampleRates[i] );
-    if(pa_err == paDeviceUnavailable) return -1;
-    if(pa_err == paInvalidDevice) return -1;
-    if(pa_err == paFormatIsSupported ) {
-      minStandardSampleRate=standardSampleRates[i];
-    }
-    i++;
-  }
-  if(minStandardSampleRate == 0) return -1;
-  j=i;
-  while(standardSampleRates[i] > 0 ) i++;
-  i--;
-
-  while(i >= j && maxStandardSampleRate==0) {
-    pa_err=Pa_IsFormatSupported(&inputParameters, NULL,
-                                  standardSampleRates[i] );
-    if(pa_err == paDeviceUnavailable) return -1;
-    if(pa_err == paInvalidDevice) return -1;
-    if( pa_err == paFormatIsSupported ) {
-      maxStandardSampleRate=standardSampleRates[i];
-    }
-    i--;
-  }
-
-// check if min SampleRate  = max SampleRate
-  if(maxStandardSampleRate==0 && (minStandardSampleRate != 0)) {
-    maxStandardSampleRate= minStandardSampleRate;
-  }
-
-// check min and max bytes
-  minBytes=2;
-  maxBytes=2;
-  inputParameters.sampleFormat = paUInt8;
-  pa_err=Pa_IsFormatSupported(&inputParameters, NULL,
-                                maxStandardSampleRate );
-  if( pa_err == paFormatIsSupported ) {
-    minBytes=1;
-  }
-    inputParameters.sampleFormat = paInt32;
-    pa_err=Pa_IsFormatSupported(&inputParameters, NULL,
-                                maxStandardSampleRate );
-  if( pa_err == paFormatIsSupported ) {
-    maxBytes=4;
-  }
-
-// check min channel count
-  maxInputChannels= deviceInfo->maxInputChannels;
-  inputParameters.channelCount = 1;
-  inputParameters.sampleFormat = paInt16;
-  pa_err=paFormatIsSupported+32000;
-  while(pa_err != paFormatIsSupported &&
-          ( inputParameters.channelCount < (maxInputChannels+1)) ) {
-    pa_err=Pa_IsFormatSupported(&inputParameters, NULL,
-                                maxStandardSampleRate );
-    inputParameters.channelCount++;
-  }
-  if( pa_err == paFormatIsSupported ) {
-    minInputChannels=inputParameters.channelCount-1;
-  } else {
-    return -1;
-  }
-
-end_pa_get_device_info:;
-
-  *pa_device_max_speed=maxStandardSampleRate;
-  *pa_device_min_speed=minStandardSampleRate;
-  *pa_device_max_bytes=maxBytes;
-  *pa_device_min_bytes=minBytes;
-  *pa_device_max_channels= maxInputChannels;
-  *pa_device_min_channels= minInputChannels;
-
-  return speed_warning;
-}
-
-
-void paInputDevice(int id, char* hostAPI_DeviceName, int* minChan,
-                   int* maxChan, int* minSpeed, int* maxSpeed)
-{
-  int i;
-  char pa_device_name[128];
-  char pa_device_hostapi[128];
-  double pa_device_max_speed;
-  double pa_device_min_speed;
-  int pa_device_max_bytes;
-  int pa_device_min_bytes;
-  int pa_device_max_channels;
-  int pa_device_min_channels;
-  char p2[50];
-  char *p,*p1;
-  static int iret, valid_dev_cnt;
-
-  iret=pa_get_device_info (id,
-                          &pa_device_name,
-                          &pa_device_hostapi,
-                          &pa_device_max_speed,
-                          &pa_device_min_speed,
-                          &pa_device_max_bytes,
-                          &pa_device_min_bytes,
-                          &pa_device_max_channels,
-                          &pa_device_min_channels);
-
-  if (iret >= 0 ) {
-    valid_dev_cnt++;
-
-    p1=(char*)"";
-    p=strstr(pa_device_hostapi,"MME");
-    if(p!=NULL) p1=(char*)"MME";
-    p=strstr(pa_device_hostapi,"Direct");
-    if(p!=NULL) p1=(char*)"DirectX";
-    p=strstr(pa_device_hostapi,"WASAPI");
-    if(p!=NULL) p1=(char*)"WASAPI";
-    p=strstr(pa_device_hostapi,"ASIO");
-    if(p!=NULL) p1=(char*)"ASIO";
-    p=strstr(pa_device_hostapi,"WDM-KS");
-    if(p!=NULL) p1=(char*)"WDM-KS";
-
-    sprintf(p2,"%-8s %-39s",p1,pa_device_name);
-    for(i=0; i<50; i++) {
-      hostAPI_DeviceName[i]=p2[i];
-      if(p2[i]==0) break;
-    }
-    *minChan=pa_device_min_channels;
-    *maxChan=pa_device_max_channels;
-    *minSpeed=(int)pa_device_min_speed;
-    *maxSpeed=(int)pa_device_max_speed;
-  } else {
-    for(i=0; i<50; i++) {
-      hostAPI_DeviceName[i]=0;
-    }
-    *minChan=0;
-    *maxChan=0;
-    *minSpeed=0;
-    *maxSpeed=0;
-  }
-}
-
-void getDev(int* numDevices0, char hostAPI_DeviceName[][50],
-            int minChan[], int maxChan[],
-            int minSpeed[], int maxSpeed[])
-{
-  int i,id,numDevices;
-  int minch,maxch,minsp,maxsp;
-  char apidev[256];
-
-  numDevices=Pa_GetDeviceCount();
-  *numDevices0=numDevices;
-
-  for(id=0; id<numDevices; id++)  {
-    paInputDevice(id,apidev,&minch,&maxch,&minsp,&maxsp);
-    for(i=0; i<50; i++) {
-      hostAPI_DeviceName[id][i]=apidev[i];
-    }
-    hostAPI_DeviceName[id][49]=0;
-    minChan[id]=minch;
-    maxChan[id]=maxch;
-    minSpeed[id]=minsp;
-    maxSpeed[id]=maxsp;
-  }
-}
diff --git a/getfile.cpp b/getfile.cpp
index ecc7bbb..cf1dfa9 100644
--- a/getfile.cpp
+++ b/getfile.cpp
@@ -19,8 +19,10 @@
 void getfile(QString fname, int ntrperiod)
 {
 
-  char name[80];
-  strcpy(name,fname.toLatin1());
+  char name[512];
+  strncpy(name,fname.toLatin1(), sizeof (name) - 1);
+  name[sizeof (name) - 1] = '\0';
+
   FILE* fp=fopen(name,"rb");
 
   int i0=fname.indexOf(".wav");
@@ -60,8 +62,9 @@ void savewav(QString fname, int ntrperiod)
 
   int npts=ntrperiod*12000;
 //  qint16* buf=(qint16*)malloc(2*npts);
-  char name[80];
-  strcpy(name,fname.toLatin1());
+  char name[512];
+  strncpy(name,fname.toLatin1(),sizeof (name) - 1);
+  name[sizeof (name) - 1] = '\0';
   FILE* fp=fopen(name,"wb");
 
   if(fp != NULL) {
diff --git a/getfile.h b/getfile.h
index 2e255d1..4cd1045 100644
--- a/getfile.h
+++ b/getfile.h
@@ -1,3 +1,4 @@
+// -*- Mode: C++ -*-
 #ifndef GETFILE_H
 #define GETFILE_H
 #include <QString>
diff --git a/icons/Darwin/DragNDrop Background.png b/icons/Darwin/DragNDrop Background.png
new file mode 100644
index 0000000..fc230f5
Binary files /dev/null and b/icons/Darwin/DragNDrop Background.png differ
diff --git a/icons/Darwin/wsjt.iconset/icon_128x128.png b/icons/Darwin/wsjt.iconset/icon_128x128.png
new file mode 100644
index 0000000..f27139e
Binary files /dev/null and b/icons/Darwin/wsjt.iconset/icon_128x128.png differ
diff --git a/icons/Darwin/wsjt.iconset/icon_128x128 at 2x.png b/icons/Darwin/wsjt.iconset/icon_128x128 at 2x.png
new file mode 100644
index 0000000..eebc17e
Binary files /dev/null and b/icons/Darwin/wsjt.iconset/icon_128x128 at 2x.png differ
diff --git a/icons/Darwin/wsjt.iconset/icon_16x16.png b/icons/Darwin/wsjt.iconset/icon_16x16.png
new file mode 100644
index 0000000..ecc5868
Binary files /dev/null and b/icons/Darwin/wsjt.iconset/icon_16x16.png differ
diff --git a/icons/Darwin/wsjt.iconset/icon_16x16 at 2x.png b/icons/Darwin/wsjt.iconset/icon_16x16 at 2x.png
new file mode 100644
index 0000000..9a8ee28
Binary files /dev/null and b/icons/Darwin/wsjt.iconset/icon_16x16 at 2x.png differ
diff --git a/icons/Darwin/wsjt.iconset/icon_256x256.png b/icons/Darwin/wsjt.iconset/icon_256x256.png
new file mode 100644
index 0000000..eebc17e
Binary files /dev/null and b/icons/Darwin/wsjt.iconset/icon_256x256.png differ
diff --git a/icons/Darwin/wsjt.iconset/icon_256x256 at 2x.png b/icons/Darwin/wsjt.iconset/icon_256x256 at 2x.png
new file mode 100644
index 0000000..b4701fb
Binary files /dev/null and b/icons/Darwin/wsjt.iconset/icon_256x256 at 2x.png differ
diff --git a/icons/Darwin/wsjt.iconset/icon_32x32.png b/icons/Darwin/wsjt.iconset/icon_32x32.png
new file mode 100644
index 0000000..9a8ee28
Binary files /dev/null and b/icons/Darwin/wsjt.iconset/icon_32x32.png differ
diff --git a/icons/Darwin/wsjt.iconset/icon_32x32 at 2x.png b/icons/Darwin/wsjt.iconset/icon_32x32 at 2x.png
new file mode 100644
index 0000000..88b285e
Binary files /dev/null and b/icons/Darwin/wsjt.iconset/icon_32x32 at 2x.png differ
diff --git a/icons/Darwin/wsjt.iconset/icon_512x512.png b/icons/Darwin/wsjt.iconset/icon_512x512.png
new file mode 100644
index 0000000..b4701fb
Binary files /dev/null and b/icons/Darwin/wsjt.iconset/icon_512x512.png differ
diff --git a/icons/Darwin/wsjt.iconset/icon_512x512 at 2x.png b/icons/Darwin/wsjt.iconset/icon_512x512 at 2x.png
new file mode 100644
index 0000000..9dd961d
Binary files /dev/null and b/icons/Darwin/wsjt.iconset/icon_512x512 at 2x.png differ
diff --git a/icons/Darwin/wsjtx.iconset/icon_128x128.png b/icons/Darwin/wsjtx.iconset/icon_128x128.png
new file mode 100644
index 0000000..9387de4
Binary files /dev/null and b/icons/Darwin/wsjtx.iconset/icon_128x128.png differ
diff --git a/icons/Darwin/wsjtx.iconset/icon_128x128 at 2x.png b/icons/Darwin/wsjtx.iconset/icon_128x128 at 2x.png
new file mode 100644
index 0000000..6b0df8f
Binary files /dev/null and b/icons/Darwin/wsjtx.iconset/icon_128x128 at 2x.png differ
diff --git a/icons/Darwin/wsjtx.iconset/icon_16x16.png b/icons/Darwin/wsjtx.iconset/icon_16x16.png
new file mode 100644
index 0000000..ecc5868
Binary files /dev/null and b/icons/Darwin/wsjtx.iconset/icon_16x16.png differ
diff --git a/icons/Darwin/wsjtx.iconset/icon_16x16 at 2x.png b/icons/Darwin/wsjtx.iconset/icon_16x16 at 2x.png
new file mode 100644
index 0000000..9a8ee28
Binary files /dev/null and b/icons/Darwin/wsjtx.iconset/icon_16x16 at 2x.png differ
diff --git a/icons/Darwin/wsjtx.iconset/icon_256x256.png b/icons/Darwin/wsjtx.iconset/icon_256x256.png
new file mode 100644
index 0000000..6b0df8f
Binary files /dev/null and b/icons/Darwin/wsjtx.iconset/icon_256x256.png differ
diff --git a/icons/Darwin/wsjtx.iconset/icon_256x256 at 2x.png b/icons/Darwin/wsjtx.iconset/icon_256x256 at 2x.png
new file mode 100644
index 0000000..f30a99d
Binary files /dev/null and b/icons/Darwin/wsjtx.iconset/icon_256x256 at 2x.png differ
diff --git a/icons/Darwin/wsjtx.iconset/icon_32x32.png b/icons/Darwin/wsjtx.iconset/icon_32x32.png
new file mode 100644
index 0000000..9a8ee28
Binary files /dev/null and b/icons/Darwin/wsjtx.iconset/icon_32x32.png differ
diff --git a/icons/Darwin/wsjtx.iconset/icon_32x32 at 2x.png b/icons/Darwin/wsjtx.iconset/icon_32x32 at 2x.png
new file mode 100644
index 0000000..88b285e
Binary files /dev/null and b/icons/Darwin/wsjtx.iconset/icon_32x32 at 2x.png differ
diff --git a/icons/Darwin/wsjtx.iconset/icon_512x512.png b/icons/Darwin/wsjtx.iconset/icon_512x512.png
new file mode 100644
index 0000000..f30a99d
Binary files /dev/null and b/icons/Darwin/wsjtx.iconset/icon_512x512.png differ
diff --git a/icons/Darwin/wsjtx.iconset/icon_512x512 at 2x.png b/icons/Darwin/wsjtx.iconset/icon_512x512 at 2x.png
new file mode 100644
index 0000000..b0b4be5
Binary files /dev/null and b/icons/Darwin/wsjtx.iconset/icon_512x512 at 2x.png differ
diff --git a/icons/README b/icons/README
new file mode 100644
index 0000000..dd9b1fc
--- /dev/null
+++ b/icons/README
@@ -0,0 +1,3 @@
+Files under this directory are generated. Even though they are checked
+into  source  control  they  should  not be  modified  directly.   See
+../artwork/README for details of generating these files.
\ No newline at end of file
diff --git a/icons/Unix/wsjtx_icon.png b/icons/Unix/wsjtx_icon.png
new file mode 100644
index 0000000..9387de4
Binary files /dev/null and b/icons/Unix/wsjtx_icon.png differ
diff --git a/icons/windows-icons/installer_logo.bmp b/icons/windows-icons/installer_logo.bmp
new file mode 100644
index 0000000..ef01531
Binary files /dev/null and b/icons/windows-icons/installer_logo.bmp differ
diff --git a/icons/windows-icons/wsjtx.ico b/icons/windows-icons/wsjtx.ico
new file mode 100644
index 0000000..142232e
Binary files /dev/null and b/icons/windows-icons/wsjtx.ico differ
diff --git a/in.dat b/in.dat
deleted file mode 100644
index 5294129..0000000
--- a/in.dat
+++ /dev/null
@@ -1,16 +0,0 @@
-  35  36  22   8  31  11  14  55  20  36  55  13  24  15  56  38  16  28  61  58
-  15  26  45   8  41  53  37  57  59  60  29  29  41  46  44  35  52  61  24  26
-  16  20  53  35   2   6   9  27  47  28  57   6  15   9  16  10  56   9  63  46
-   9  15   3
-  74  61  44 233  29 245 254  64 119  64 250 111  38 145  53  29 140 194 119  99
-  55  86  48 110 142  95  48 120  61  66 252 252 245  88  62  41 124 249 246  68
- 250 249  65  64 140 142  88 190 237  90 240  52  79 216  55  31 112 135  66  44
-  99  57  68
-  54  61  26   5  13  60   3  56  30  58  57   4  16  43  28  43   6  61  13  19
-  56   8   4   9  45  32   9   7  14  52   4  38  40  27   3  26  51  54  40  29
-  36  63  34  43   3  48  36  49  46  30   8  20  40  59  29  28  17  11   8  19
-  11  63   5
-  38  25  35   8  28   0   0  60  60  25   0  31  28  52  14  24   9  30  18  54
-  49  55  48  15  27  54  26  22  30  27   1   1   4  31  35  29  23   2   2  27
-   0   1  25  32  21  84  28  19   5  60   2  27  15   9  39  23  42  12  29  17
-  16  50  49
diff --git a/killbyname.cpp b/killbyname.cpp
index 240ad5a..3fe8841 100644
--- a/killbyname.cpp
+++ b/killbyname.cpp
@@ -1,284 +1,284 @@
-#include <windows.h>
-#include <tlhelp32.h>
-#include <iostream>
-
-int killbyname(const char *szToTerminate)
-// Created: 6/23/2000  (Ravi Kochhar)
-// Last modified: 3/10/2002  (RK)
-// Please report any problems or bugs to kochhar at physiology.wisc.edu
-// The latest version of this routine can be found at:
-//     http://www.neurophys.wisc.edu/ravi/software/killproc/
-// Terminate the process "szToTerminate" if it is currently running
-// This works for Win/95/98/ME and also Win/NT/2000/XP
-// The process name is case-insensitive, i.e. "notepad.exe" and "NOTEPAD.EXE"
-// will both work (for szToTerminate)
-// Return codes are as follows:
-//   0   = Process was successfully terminated
-//   602 = Unable to terminate process for some other reason
-//   603 = Process was not currently running
-//   604 = No permission to terminate process
-//   605 = Unable to load PSAPI.DLL
-//   606 = Unable to identify system type
-//   607 = Unsupported OS
-//   632 = Invalid process name
-//   700 = Unable to get procedure address from PSAPI.DLL
-//   701 = Unable to get process list, EnumProcesses failed
-//   702 = Unable to load KERNEL32.DLL
-//   703 = Unable to get procedure address from KERNEL32.DLL
-//   704 = CreateToolhelp32Snapshot failed
-
-{
-  BOOL bResult,bResultm;
-  DWORD aiPID[1000],iCb=1000,iNumProc;  //,iV2000=0;
-  DWORD iCbneeded,i,iFound=0;
-  char szName[MAX_PATH],szToTermUpper[MAX_PATH];
-  HANDLE hProc,hSnapShot,hSnapShotm;
-  OSVERSIONINFO osvi;
-  HINSTANCE hInstLib;
-//  int iLen,iLenP,indx;
-  int iLenP,indx;
-  HMODULE hMod;
-  PROCESSENTRY32 procentry;
-  MODULEENTRY32 modentry;
-
-  // Transfer Process name into "szToTermUpper" and convert to upper case
-  iLenP=strlen(szToTerminate);
-  if(iLenP<1 || iLenP>MAX_PATH) return 632;
-  for(indx=0;indx<iLenP;indx++)
-    szToTermUpper[indx]=toupper(szToTerminate[indx]);
-  szToTermUpper[iLenP]=0;
-
-  // PSAPI Function Pointers.
-  BOOL (WINAPI *lpfEnumProcesses)( DWORD *, DWORD cb, DWORD * );
-  BOOL (WINAPI *lpfEnumProcessModules)( HANDLE, HMODULE *,
-                                        DWORD, LPDWORD );
-  DWORD (WINAPI *lpfGetModuleBaseName)( HANDLE, HMODULE,
-                                        LPTSTR, DWORD );
-
-  // ToolHelp Function Pointers.
-  HANDLE (WINAPI *lpfCreateToolhelp32Snapshot)(DWORD,DWORD) ;
-  BOOL (WINAPI *lpfProcess32First)(HANDLE,LPPROCESSENTRY32) ;
-  BOOL (WINAPI *lpfProcess32Next)(HANDLE,LPPROCESSENTRY32) ;
-  BOOL (WINAPI *lpfModule32First)(HANDLE,LPMODULEENTRY32) ;
-  BOOL (WINAPI *lpfModule32Next)(HANDLE,LPMODULEENTRY32) ;
-
-  // First check what version of Windows we're in
-  osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
-  bResult=GetVersionEx(&osvi);
-  if(!bResult) return 606;    // Unable to identify system version
-
-  // At Present we only support Win/NT/2000/XP or Win/9x/ME
-  // Seems to work OK in Win7
-  if((osvi.dwPlatformId != VER_PLATFORM_WIN32_NT) &&
-     (osvi.dwPlatformId != VER_PLATFORM_WIN32_WINDOWS)) return 607;
-
-  if(osvi.dwPlatformId==VER_PLATFORM_WIN32_NT)
-  {
-    // Win/NT or 2000 or XP
-
-    // Load library and get the procedures explicitly. We do
-    // this so that we don't have to worry about modules using
-    // this code failing to load under Windows 9x, because
-    // it can't resolve references to the PSAPI.DLL.
-    hInstLib = LoadLibraryA("PSAPI.DLL");
-    if(hInstLib == NULL) return 605;
-
-    // Get procedure addresses.
-    lpfEnumProcesses = (BOOL(WINAPI *)(DWORD *,DWORD,DWORD*))
-        GetProcAddress( hInstLib, "EnumProcesses" ) ;
-    lpfEnumProcessModules = (BOOL(WINAPI *)(HANDLE, HMODULE *,
-        DWORD, LPDWORD)) GetProcAddress( hInstLib,                                                                     "EnumProcessModules" ) ;
-        lpfGetModuleBaseName =(DWORD (WINAPI *)(HANDLE, HMODULE, LPTSTR,
-        DWORD )) GetProcAddress( hInstLib, "GetModuleBaseNameA" ) ;
-
-    if(lpfEnumProcesses == NULL || lpfEnumProcessModules == NULL ||
-         lpfGetModuleBaseName == NULL) {
-      FreeLibrary(hInstLib);
-      return 700;
-    }
-
-    bResult=lpfEnumProcesses(aiPID,iCb,&iCbneeded);
-    if(!bResult) {
-      // Unable to get process list, EnumProcesses failed
-      FreeLibrary(hInstLib);
-      return 701;
-    }
-
-    // How many processes are there?
-    iNumProc=iCbneeded/sizeof(DWORD);
-
-    // Get and match the name of each process
-    for(i=0;i<iNumProc;i++) {
-      // Get the (module) name for this process
-      strcpy(szName,"Unknown");
-      // First, get a handle to the process
-      hProc=OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_VM_READ,FALSE,
-                        aiPID[i]);
-      // Now, get the process name
-      if(hProc) {
-        if(lpfEnumProcessModules(hProc,&hMod,sizeof(hMod),&iCbneeded) ) {
-//          iLen=lpfGetModuleBaseName(hProc,hMod,szName,MAX_PATH);
-          lpfGetModuleBaseName(hProc,hMod,szName,MAX_PATH);
-        }
-      }
-      CloseHandle(hProc);
-      // We will match regardless of lower or upper case
-      if(strcmp(_strupr(szName),szToTermUpper)==0) {
-        // Process found, now terminate it
-        iFound=1;
-        // First open for termination
-        hProc=OpenProcess(PROCESS_TERMINATE,FALSE,aiPID[i]);
-        if(hProc) {
-          if(TerminateProcess(hProc,0)) {
-            // process terminated
-            CloseHandle(hProc);
-            FreeLibrary(hInstLib);
-            return 0;
-          } else {
-            // Unable to terminate process
-            CloseHandle(hProc);
-            FreeLibrary(hInstLib);
-            return 602;
-          }
-        } else {
-          // Unable to open process for termination
-          FreeLibrary(hInstLib);
-          return 604;
-        }
-      }
-    }
-  }
-
-  if(osvi.dwPlatformId==VER_PLATFORM_WIN32_WINDOWS)
-  {
-    // Win/95 or 98 or ME
-
-    hInstLib = LoadLibraryA("Kernel32.DLL");
-    if( hInstLib == NULL )
-      return 702;
-
-    // Get procedure addresses.
-    // We are linking to these functions of Kernel32
-    // explicitly, because otherwise a module using
-    // this code would fail to load under Windows NT,
-    // which does not have the Toolhelp32
-    // functions in the Kernel 32.
-    lpfCreateToolhelp32Snapshot=
-        (HANDLE(WINAPI *)(DWORD,DWORD))
-        GetProcAddress( hInstLib,
-                        "CreateToolhelp32Snapshot" ) ;
-    lpfProcess32First=
-        (BOOL(WINAPI *)(HANDLE,LPPROCESSENTRY32))
-        GetProcAddress( hInstLib, "Process32First" ) ;
-    lpfProcess32Next=
-        (BOOL(WINAPI *)(HANDLE,LPPROCESSENTRY32))
-        GetProcAddress( hInstLib, "Process32Next" ) ;
-    lpfModule32First=
-        (BOOL(WINAPI *)(HANDLE,LPMODULEENTRY32))
-        GetProcAddress( hInstLib, "Module32First" ) ;
-    lpfModule32Next=
-        (BOOL(WINAPI *)(HANDLE,LPMODULEENTRY32))
-        GetProcAddress( hInstLib, "Module32Next" ) ;
-    if( lpfProcess32Next == NULL ||
-        lpfProcess32First == NULL ||
-        lpfModule32Next == NULL ||
-        lpfModule32First == NULL ||
-        lpfCreateToolhelp32Snapshot == NULL )
-    {
-      FreeLibrary(hInstLib);
-      return 703;
-    }
-
-    // The Process32.. and Module32.. routines return names in all uppercase
-
-    // Get a handle to a Toolhelp snapshot of all the systems processes.
-
-    hSnapShot = lpfCreateToolhelp32Snapshot(
-          TH32CS_SNAPPROCESS, 0 ) ;
-    if( hSnapShot == INVALID_HANDLE_VALUE )
-    {
-      FreeLibrary(hInstLib);
-      return 704;
-    }
-
-    // Get the first process' information.
-    procentry.dwSize = sizeof(PROCESSENTRY32);
-    bResult=lpfProcess32First(hSnapShot,&procentry);
-
-    // While there are processes, keep looping and checking.
-    while(bResult)
-    {
-      // Get a handle to a Toolhelp snapshot of this process.
-      hSnapShotm = lpfCreateToolhelp32Snapshot(
-            TH32CS_SNAPMODULE, procentry.th32ProcessID) ;
-      if( hSnapShotm == INVALID_HANDLE_VALUE )
-      {
-        CloseHandle(hSnapShot);
-        FreeLibrary(hInstLib);
-        return 704;
-      }
-      // Get the module list for this process
-      modentry.dwSize=sizeof(MODULEENTRY32);
-      bResultm=lpfModule32First(hSnapShotm,&modentry);
-
-      // While there are modules, keep looping and checking
-      while(bResultm)
-      {
-        if(strcmp(modentry.szModule,szToTermUpper)==0)
-        {
-          // Process found, now terminate it
-          iFound=1;
-          // First open for termination
-          hProc=OpenProcess(PROCESS_TERMINATE,FALSE,procentry.th32ProcessID);
-          if(hProc)
-          {
-            if(TerminateProcess(hProc,0))
-            {
-              // process terminated
-              CloseHandle(hSnapShotm);
-              CloseHandle(hSnapShot);
-              CloseHandle(hProc);
-              FreeLibrary(hInstLib);
-              return 0;
-            }
-            else
-            {
-              // Unable to terminate process
-              CloseHandle(hSnapShotm);
-              CloseHandle(hSnapShot);
-              CloseHandle(hProc);
-              FreeLibrary(hInstLib);
-              return 602;
-            }
-          }
-          else
-          {
-            // Unable to open process for termination
-            CloseHandle(hSnapShotm);
-            CloseHandle(hSnapShot);
-            FreeLibrary(hInstLib);
-            return 604;
-          }
-        }
-        else
-        {  // Look for next modules for this process
-          modentry.dwSize=sizeof(MODULEENTRY32);
-          bResultm=lpfModule32Next(hSnapShotm,&modentry);
-        }
-      }
-
-      //Keep looking
-      CloseHandle(hSnapShotm);
-      procentry.dwSize = sizeof(PROCESSENTRY32);
-      bResult = lpfProcess32Next(hSnapShot,&procentry);
-    }
-    CloseHandle(hSnapShot);
-  }
-  if(iFound==0)
-  {
-    FreeLibrary(hInstLib);
-    return 603;
-  }
-  FreeLibrary(hInstLib);
-  return 0;
-}
+#include <windows.h>
+#include <tlhelp32.h>
+#include <iostream>
+
+int killbyname(const char *szToTerminate)
+// Created: 6/23/2000  (Ravi Kochhar)
+// Last modified: 3/10/2002  (RK)
+// Please report any problems or bugs to kochhar at physiology.wisc.edu
+// The latest version of this routine can be found at:
+//     http://www.neurophys.wisc.edu/ravi/software/killproc/
+// Terminate the process "szToTerminate" if it is currently running
+// This works for Win/95/98/ME and also Win/NT/2000/XP
+// The process name is case-insensitive, i.e. "notepad.exe" and "NOTEPAD.EXE"
+// will both work (for szToTerminate)
+// Return codes are as follows:
+//   0   = Process was successfully terminated
+//   602 = Unable to terminate process for some other reason
+//   603 = Process was not currently running
+//   604 = No permission to terminate process
+//   605 = Unable to load PSAPI.DLL
+//   606 = Unable to identify system type
+//   607 = Unsupported OS
+//   632 = Invalid process name
+//   700 = Unable to get procedure address from PSAPI.DLL
+//   701 = Unable to get process list, EnumProcesses failed
+//   702 = Unable to load KERNEL32.DLL
+//   703 = Unable to get procedure address from KERNEL32.DLL
+//   704 = CreateToolhelp32Snapshot failed
+
+{
+  BOOL bResult,bResultm;
+  DWORD aiPID[1000],iCb=1000,iNumProc;  //,iV2000=0;
+  DWORD iCbneeded,i,iFound=0;
+  char szName[MAX_PATH],szToTermUpper[MAX_PATH];
+  HANDLE hProc,hSnapShot,hSnapShotm;
+  OSVERSIONINFO osvi;
+  HINSTANCE hInstLib;
+//  int iLen,iLenP,indx;
+  int iLenP,indx;
+  HMODULE hMod;
+  PROCESSENTRY32 procentry;
+  MODULEENTRY32 modentry;
+
+  // Transfer Process name into "szToTermUpper" and convert to upper case
+  iLenP=strlen(szToTerminate);
+  if(iLenP<1 || iLenP>MAX_PATH) return 632;
+  for(indx=0;indx<iLenP;indx++)
+    szToTermUpper[indx]=toupper(szToTerminate[indx]);
+  szToTermUpper[iLenP]=0;
+
+  // PSAPI Function Pointers.
+  BOOL (WINAPI *lpfEnumProcesses)( DWORD *, DWORD cb, DWORD * );
+  BOOL (WINAPI *lpfEnumProcessModules)( HANDLE, HMODULE *,
+                                        DWORD, LPDWORD );
+  DWORD (WINAPI *lpfGetModuleBaseName)( HANDLE, HMODULE,
+                                        LPTSTR, DWORD );
+
+  // ToolHelp Function Pointers.
+  HANDLE (WINAPI *lpfCreateToolhelp32Snapshot)(DWORD,DWORD) ;
+  BOOL (WINAPI *lpfProcess32First)(HANDLE,LPPROCESSENTRY32) ;
+  BOOL (WINAPI *lpfProcess32Next)(HANDLE,LPPROCESSENTRY32) ;
+  BOOL (WINAPI *lpfModule32First)(HANDLE,LPMODULEENTRY32) ;
+  BOOL (WINAPI *lpfModule32Next)(HANDLE,LPMODULEENTRY32) ;
+
+  // First check what version of Windows we're in
+  osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+  bResult=GetVersionEx(&osvi);
+  if(!bResult) return 606;    // Unable to identify system version
+
+  // At Present we only support Win/NT/2000/XP or Win/9x/ME
+  // Seems to work OK in Win7
+  if((osvi.dwPlatformId != VER_PLATFORM_WIN32_NT) &&
+     (osvi.dwPlatformId != VER_PLATFORM_WIN32_WINDOWS)) return 607;
+
+  if(osvi.dwPlatformId==VER_PLATFORM_WIN32_NT)
+  {
+    // Win/NT or 2000 or XP
+
+    // Load library and get the procedures explicitly. We do
+    // this so that we don't have to worry about modules using
+    // this code failing to load under Windows 9x, because
+    // it can't resolve references to the PSAPI.DLL.
+    hInstLib = LoadLibraryA("PSAPI.DLL");
+    if(hInstLib == NULL) return 605;
+
+    // Get procedure addresses.
+    lpfEnumProcesses = (BOOL(WINAPI *)(DWORD *,DWORD,DWORD*))
+        GetProcAddress( hInstLib, "EnumProcesses" ) ;
+    lpfEnumProcessModules = (BOOL(WINAPI *)(HANDLE, HMODULE *,
+        DWORD, LPDWORD)) GetProcAddress( hInstLib,                                                                     "EnumProcessModules" ) ;
+        lpfGetModuleBaseName =(DWORD (WINAPI *)(HANDLE, HMODULE, LPTSTR,
+        DWORD )) GetProcAddress( hInstLib, "GetModuleBaseNameA" ) ;
+
+    if(lpfEnumProcesses == NULL || lpfEnumProcessModules == NULL ||
+         lpfGetModuleBaseName == NULL) {
+      FreeLibrary(hInstLib);
+      return 700;
+    }
+
+    bResult=lpfEnumProcesses(aiPID,iCb,&iCbneeded);
+    if(!bResult) {
+      // Unable to get process list, EnumProcesses failed
+      FreeLibrary(hInstLib);
+      return 701;
+    }
+
+    // How many processes are there?
+    iNumProc=iCbneeded/sizeof(DWORD);
+
+    // Get and match the name of each process
+    for(i=0;i<iNumProc;i++) {
+      // Get the (module) name for this process
+      strcpy(szName,"Unknown");
+      // First, get a handle to the process
+      hProc=OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_VM_READ,FALSE,
+                        aiPID[i]);
+      // Now, get the process name
+      if(hProc) {
+        if(lpfEnumProcessModules(hProc,&hMod,sizeof(hMod),&iCbneeded) ) {
+//          iLen=lpfGetModuleBaseName(hProc,hMod,szName,MAX_PATH);
+          lpfGetModuleBaseName(hProc,hMod,szName,MAX_PATH);
+        }
+      }
+      CloseHandle(hProc);
+      // We will match regardless of lower or upper case
+      if(strcmp(_strupr(szName),szToTermUpper)==0) {
+        // Process found, now terminate it
+        iFound=1;
+        // First open for termination
+        hProc=OpenProcess(PROCESS_TERMINATE,FALSE,aiPID[i]);
+        if(hProc) {
+          if(TerminateProcess(hProc,0)) {
+            // process terminated
+            CloseHandle(hProc);
+            FreeLibrary(hInstLib);
+            return 0;
+          } else {
+            // Unable to terminate process
+            CloseHandle(hProc);
+            FreeLibrary(hInstLib);
+            return 602;
+          }
+        } else {
+          // Unable to open process for termination
+          FreeLibrary(hInstLib);
+          return 604;
+        }
+      }
+    }
+  }
+
+  if(osvi.dwPlatformId==VER_PLATFORM_WIN32_WINDOWS)
+  {
+    // Win/95 or 98 or ME
+
+    hInstLib = LoadLibraryA("Kernel32.DLL");
+    if( hInstLib == NULL )
+      return 702;
+
+    // Get procedure addresses.
+    // We are linking to these functions of Kernel32
+    // explicitly, because otherwise a module using
+    // this code would fail to load under Windows NT,
+    // which does not have the Toolhelp32
+    // functions in the Kernel 32.
+    lpfCreateToolhelp32Snapshot=
+        (HANDLE(WINAPI *)(DWORD,DWORD))
+        GetProcAddress( hInstLib,
+                        "CreateToolhelp32Snapshot" ) ;
+    lpfProcess32First=
+        (BOOL(WINAPI *)(HANDLE,LPPROCESSENTRY32))
+        GetProcAddress( hInstLib, "Process32First" ) ;
+    lpfProcess32Next=
+        (BOOL(WINAPI *)(HANDLE,LPPROCESSENTRY32))
+        GetProcAddress( hInstLib, "Process32Next" ) ;
+    lpfModule32First=
+        (BOOL(WINAPI *)(HANDLE,LPMODULEENTRY32))
+        GetProcAddress( hInstLib, "Module32First" ) ;
+    lpfModule32Next=
+        (BOOL(WINAPI *)(HANDLE,LPMODULEENTRY32))
+        GetProcAddress( hInstLib, "Module32Next" ) ;
+    if( lpfProcess32Next == NULL ||
+        lpfProcess32First == NULL ||
+        lpfModule32Next == NULL ||
+        lpfModule32First == NULL ||
+        lpfCreateToolhelp32Snapshot == NULL )
+    {
+      FreeLibrary(hInstLib);
+      return 703;
+    }
+
+    // The Process32.. and Module32.. routines return names in all uppercase
+
+    // Get a handle to a Toolhelp snapshot of all the systems processes.
+
+    hSnapShot = lpfCreateToolhelp32Snapshot(
+          TH32CS_SNAPPROCESS, 0 ) ;
+    if( hSnapShot == INVALID_HANDLE_VALUE )
+    {
+      FreeLibrary(hInstLib);
+      return 704;
+    }
+
+    // Get the first process' information.
+    procentry.dwSize = sizeof(PROCESSENTRY32);
+    bResult=lpfProcess32First(hSnapShot,&procentry);
+
+    // While there are processes, keep looping and checking.
+    while(bResult)
+    {
+      // Get a handle to a Toolhelp snapshot of this process.
+      hSnapShotm = lpfCreateToolhelp32Snapshot(
+            TH32CS_SNAPMODULE, procentry.th32ProcessID) ;
+      if( hSnapShotm == INVALID_HANDLE_VALUE )
+      {
+        CloseHandle(hSnapShot);
+        FreeLibrary(hInstLib);
+        return 704;
+      }
+      // Get the module list for this process
+      modentry.dwSize=sizeof(MODULEENTRY32);
+      bResultm=lpfModule32First(hSnapShotm,&modentry);
+
+      // While there are modules, keep looping and checking
+      while(bResultm)
+      {
+        if(strcmp(modentry.szModule,szToTermUpper)==0)
+        {
+          // Process found, now terminate it
+          iFound=1;
+          // First open for termination
+          hProc=OpenProcess(PROCESS_TERMINATE,FALSE,procentry.th32ProcessID);
+          if(hProc)
+          {
+            if(TerminateProcess(hProc,0))
+            {
+              // process terminated
+              CloseHandle(hSnapShotm);
+              CloseHandle(hSnapShot);
+              CloseHandle(hProc);
+              FreeLibrary(hInstLib);
+              return 0;
+            }
+            else
+            {
+              // Unable to terminate process
+              CloseHandle(hSnapShotm);
+              CloseHandle(hSnapShot);
+              CloseHandle(hProc);
+              FreeLibrary(hInstLib);
+              return 602;
+            }
+          }
+          else
+          {
+            // Unable to open process for termination
+            CloseHandle(hSnapShotm);
+            CloseHandle(hSnapShot);
+            FreeLibrary(hInstLib);
+            return 604;
+          }
+        }
+        else
+        {  // Look for next modules for this process
+          modentry.dwSize=sizeof(MODULEENTRY32);
+          bResultm=lpfModule32Next(hSnapShotm,&modentry);
+        }
+      }
+
+      //Keep looking
+      CloseHandle(hSnapShotm);
+      procentry.dwSize = sizeof(PROCESSENTRY32);
+      bResult = lpfProcess32Next(hSnapShot,&procentry);
+    }
+    CloseHandle(hSnapShot);
+  }
+  if(iFound==0)
+  {
+    FreeLibrary(hInstLib);
+    return 603;
+  }
+  FreeLibrary(hInstLib);
+  return 0;
+}
diff --git a/lib/Makefile.MinGW b/lib/Makefile.MinGW
index e09924b..1cdc665 100644
--- a/lib/Makefile.MinGW
+++ b/lib/Makefile.MinGW
@@ -1,9 +1,34 @@
 # Makefile for MinGW on Windows
+#
+# Needed libraries are located using the following variables:
+#
+#   QT_DIR - point this at the root of your Qt installation
+#   FFTW3_DIR - point this at the fftw v3 installation directory
+#
+# e.g.
+#   make -f Makefile.MinGW \
+#    QT_DIR=c:/Qt/5.2.1/mingw48_32 \
+#    FFTW3_DIR = c:/fftw-3.3.3-dll32-2
+#
 # Windows re-direct:
 #   C> make > junk1 2>&1
 
+# Set paths
+EXE_DIR = ..\\..\\wsjtx_install
+QT_DIR = C:/wsjt-env/Qt5/5.2.1/mingw48_32
+FFTW3_DIR = ..
+
+INCPATH = -I${QT_DIR}/include/QtCore -I${QT_DIR}/include 
+
+# Compilers
 CC = gcc
-FC = g95
+CXX = g++
+FC = gfortran
+AR = ar cr
+RANLIB = ranlib
+MKDIR = mkdir -p
+CP = cp
+RM = rm -f
 
 FFLAGS = -O2 -fbounds-check -Wall -Wno-precision-loss -fno-second-underscore
 CFLAGS = -I. -fbounds-check -mno-stack-arg-probe
@@ -20,14 +45,14 @@ CFLAGS = -I. -fbounds-check -mno-stack-arg-probe
 %.o: %.F90
 	${FC} ${FFLAGS} -c $<
 
-all:    libjt9.a jt9sim.exe jt9.exe jt9code.exe jt65.exe
+all:    libjt9.a libastro.a jt9.exe jt9code.exe jt65code.exe 
 
-OBJS1 = pctile.o graycode.o sort.o ssort.o \
+OBJS1 = prog_args.o options.o pctile.o graycode.o sort.o ssort.o chkmsg.o \
 	unpackmsg.o igray.o unpackcall.o unpackgrid.o \
-	grid2k.o unpacktext.o getpfx2.o packmsg.o deg2grid.o \
+	fmtmsg.o grid2k.o unpacktext.o getpfx2.o packmsg.o deg2grid.o \
 	packtext.o getpfx1.o packcall.o k2grid.o packgrid.o \
 	nchar.o four2a.o grid2deg.o pfxdump.o f77_wisdom.o \
-	symspec.o analytic.o db.o genjt9.o \
+	symspec.o analytic.o db.o genjt9.o flat1.o smo.o \
 	packbits.o unpackbits.o encode232.o interleave9.o \
 	entail.o fano232.o gran.o sync9.o decode9.o \
 	fil3.o decoder.o grid2n.o n2grid.o timer.o \
@@ -38,18 +63,20 @@ OBJS1 = pctile.o graycode.o sort.o ssort.o \
 	filbig.o fil6521.o afc65b.o decode65b.o setup65.o \
 	extract.o fchisq65.o demod64a.o chkhist.o interleave63.o ccf2.o \
 	move.o indexx.o graycode65.o twkfreq65.o smo121.o \
-	wrapkarn.o init_rs.o encode_rs.o decode_rs.o gen65.o
+	wrapkarn.o init_rs.o encode_rs.o decode_rs.o gen65.o fil4.o \
+	flat3.o polfit.o determ.o baddata.o
 
 libjt9.a: $(OBJS1)
-	ar cr libjt9.a $(OBJS1) 
-	ranlib libjt9.a
+	$(AR) libjt9.a $(OBJS1) 
+	$(RANLIB) libjt9.a
 
-OBJS2 = jt9.o jt9a.o jt9b.o jt9c.o ipcomm.o sec_midn.o cutil.o
-LIBS2 = -L'c:/QtSDK/Desktop/Qt/4.7.4/mingw/lib' -lQtCore4
+OBJS2 = jt9.o jt9a.o jt9b.o jt9c.o ipcomm.o sec_midn.o usleep.o
+LIBS2 = -L${QT_DIR}/lib -lQt5Core
 jt9.exe: $(OBJS2) libjt9.a
-	g++ -o jt9.exe $(OBJS2) $(LIBS2) libjt9.a ../libfftw3f_win.a \
-	c:/MinGW/lib/libf95.a
-	cp jt9.exe ../../wsjtx_install
+	$(CXX) -o jt9.exe $(OBJS2) $(LIBS2) libjt9.a \
+	-L$(FFTW3_DIR) -lfftw3f-3 $(shell $(FC) -print-file-name=lib$(FC).a)
+	-$(MKDIR) $(EXE_DIR)
+	$(CP) jt9.exe $(EXE_DIR)
 
 OBJS3 = jt9sim.o 
 jt9sim.exe: $(OBJS3) libjt9.a
@@ -58,15 +85,24 @@ jt9sim.exe: $(OBJS3) libjt9.a
 OBJS4 = jt9code.o 
 jt9code.exe: $(OBJS4) libjt9.a
 	$(FC) -o jt9code.exe $(OBJS4) libjt9.a
+	$(CP) jt9code.exe $(EXE_DIR)
 
 OBJS5 = jt65.o 
 jt65.exe: $(OBJS5) libjt9.a 
-	$(FC) -o jt65.exe $(OBJS5) libjt9.a ../libfftw3f_win.a
+	$(FC) -o jt65.exe $(OBJS5) libjt9.a -L$(FFTW3_DIR) -lfftw3f-3
+
+OBJS7 = astrosub.o astro0.o astro.o tm2.o grid2deg.o sun.o moondop.o \
+	coord.o dot.o moon2.o tmoonsub.o toxyz.o geocentric.o \
+	dcoord.o
+
+libastro.a: $(OBJS7)
+	$(AR) libastro.a $(OBJS7)
+	$(RANLIB) libastro.a
 
-INCPATH = -I'c:/QtSDK/Desktop/Qt/4.7.4/mingw/include/QtCore' \
-	 -I'c:/QtSDK/Desktop/Qt/4.7.4/mingw/include' \
-	 -I'c:/QtSDK/Desktop/Qt/4.7.4/mingw/include/ActiveQt' \
-	 -I'release' -I'.' -I'c:/QtSDK/Desktop/Qt/4.7.4/mingw/mkspecs/win32-g++'
+OBJS6 = jt65code.o
+jt65code.exe: $(OBJS6) libjt9.a
+	$(FC) -o jt65code.exe $(OBJS6) libjt9.a
+	$(CP) jt65code.exe $(EXE_DIR)
 
 sync9.o: sync9.f90 jt9sync.f90
 	$(FC) $(FFLAGS) -c sync9.f90
@@ -90,7 +126,7 @@ unpackmsg.o: unpackmsg.f90
 	$(FC) -c -O0 -fbounds-check -Wall -Wno-precision-loss unpackmsg.f90
 
 ipcomm.o: ipcomm.cpp
-	g++ -c $(INCPATH) ipcomm.cpp
+	$(CXX) -c $(INCPATH) ipcomm.cpp
 
 sec_midn.o: sec_midn.f90
 	$(FC) -c -fno-second-underscore sec_midn.f90
@@ -114,4 +150,4 @@ decode_rs.o: decode_rs.c
 .PHONY : clean
 
 clean:
-	rm -f *.o libjt9.a wsjtx.exe jt9sim.exe jt9.exe jt65.exe
+	$(RM) *.o libjt9.a wsjtx.exe jt9sim.exe jt9.exe jt65.exe
diff --git a/lib/Makefile.MinGW b/lib/Makefile.MinGW.qt4
similarity index 88%
copy from lib/Makefile.MinGW
copy to lib/Makefile.MinGW.qt4
index e09924b..df90745 100644
--- a/lib/Makefile.MinGW
+++ b/lib/Makefile.MinGW.qt4
@@ -1,117 +1,122 @@
-# Makefile for MinGW on Windows
-# Windows re-direct:
-#   C> make > junk1 2>&1
-
-CC = gcc
-FC = g95
-
-FFLAGS = -O2 -fbounds-check -Wall -Wno-precision-loss -fno-second-underscore
-CFLAGS = -I. -fbounds-check -mno-stack-arg-probe
-
-# Default rules
-%.o: %.c
-	${CC} ${CFLAGS} -c $<
-%.o: %.f
-	${FC} ${FFLAGS} -c $<
-%.o: %.F
-	${FC} ${FFLAGS} -c $<
-%.o: %.f90
-	${FC} ${FFLAGS} -c $<
-%.o: %.F90
-	${FC} ${FFLAGS} -c $<
-
-all:    libjt9.a jt9sim.exe jt9.exe jt9code.exe jt65.exe
-
-OBJS1 = pctile.o graycode.o sort.o ssort.o \
-	unpackmsg.o igray.o unpackcall.o unpackgrid.o \
-	grid2k.o unpacktext.o getpfx2.o packmsg.o deg2grid.o \
-	packtext.o getpfx1.o packcall.o k2grid.o packgrid.o \
-	nchar.o four2a.o grid2deg.o pfxdump.o f77_wisdom.o \
-	symspec.o analytic.o db.o genjt9.o \
-	packbits.o unpackbits.o encode232.o interleave9.o \
-	entail.o fano232.o gran.o sync9.o decode9.o \
-	fil3.o decoder.o grid2n.o n2grid.o timer.o \
-	softsym.o getlags.o afc9.o fchisq.o twkfreq.o downsam9.o \
-	peakdt9.o symspec2.o stdmsg.o morse.o azdist.o geodist.o \
-	fillcom.o chkss2.o zplot9.o flat2.o \
-	jt65a.o symspec65.o flat65.o ccf65.o decode65a.o \
-	filbig.o fil6521.o afc65b.o decode65b.o setup65.o \
-	extract.o fchisq65.o demod64a.o chkhist.o interleave63.o ccf2.o \
-	move.o indexx.o graycode65.o twkfreq65.o smo121.o \
-	wrapkarn.o init_rs.o encode_rs.o decode_rs.o gen65.o
-
-libjt9.a: $(OBJS1)
-	ar cr libjt9.a $(OBJS1) 
-	ranlib libjt9.a
-
-OBJS2 = jt9.o jt9a.o jt9b.o jt9c.o ipcomm.o sec_midn.o cutil.o
-LIBS2 = -L'c:/QtSDK/Desktop/Qt/4.7.4/mingw/lib' -lQtCore4
-jt9.exe: $(OBJS2) libjt9.a
-	g++ -o jt9.exe $(OBJS2) $(LIBS2) libjt9.a ../libfftw3f_win.a \
-	c:/MinGW/lib/libf95.a
-	cp jt9.exe ../../wsjtx_install
-
-OBJS3 = jt9sim.o 
-jt9sim.exe: $(OBJS3) libjt9.a
-	$(FC) -o jt9sim.exe $(OBJS3) libjt9.a
-
-OBJS4 = jt9code.o 
-jt9code.exe: $(OBJS4) libjt9.a
-	$(FC) -o jt9code.exe $(OBJS4) libjt9.a
-
-OBJS5 = jt65.o 
-jt65.exe: $(OBJS5) libjt9.a 
-	$(FC) -o jt65.exe $(OBJS5) libjt9.a ../libfftw3f_win.a
-
-INCPATH = -I'c:/QtSDK/Desktop/Qt/4.7.4/mingw/include/QtCore' \
-	 -I'c:/QtSDK/Desktop/Qt/4.7.4/mingw/include' \
-	 -I'c:/QtSDK/Desktop/Qt/4.7.4/mingw/include/ActiveQt' \
-	 -I'release' -I'.' -I'c:/QtSDK/Desktop/Qt/4.7.4/mingw/mkspecs/win32-g++'
-
-sync9.o: sync9.f90 jt9sync.f90
-	$(FC) $(FFLAGS) -c sync9.f90
-
-spec9.o: spec9.f90 jt9sync.f90
-	$(FC) $(FFLAGS) -c spec9.f90
-
-peakdt9.o: peakdt9.f90 jt9sync.f90
-	$(FC) $(FFLAGS) -c peakdt9.f90
-
-jt9sim.o: jt9sim.f90 jt9sync.f90
-	$(FC) $(FFLAGS) -c jt9sim.f90
-
-genjt9.o: genjt9.f90 jt9sync.f90
-	$(FC) $(FFLAGS) -c genjt9.f90
-
-redsync.o: redsync.f90 jt9sync.f90
-	$(FC) $(FFLAGS) -c redsync.f90
-
-unpackmsg.o: unpackmsg.f90
-	$(FC) -c -O0 -fbounds-check -Wall -Wno-precision-loss unpackmsg.f90
-
-ipcomm.o: ipcomm.cpp
-	g++ -c $(INCPATH) ipcomm.cpp
-
-sec_midn.o: sec_midn.f90
-	$(FC) -c -fno-second-underscore sec_midn.f90
-
-#rig_control.o: rig_control.c
-#	$(CC) -c -Wall -I..\..\..\hamlib-1.2.15.3\include rig_control.c
-
-tstrig.o: tstrig.c
-	$(CC) -c -Wall -I..\..\..\hamlib-1.2.15.3\include tstrig.c
-
-init_rs.o: init_rs.c
-	$(CC) -c -DBIGSYM=1 -o init_rs.o init_rs.c
-
-encode_rs.o: encode_rs.c
-	$(CC) -c -DBIGSYM=1 -o encode_rs.o encode_rs.c
-
-decode_rs.o: decode_rs.c
-	$(CC) -c -DBIGSYM=1 -o decode_rs.o decode_rs.c
-
-
-.PHONY : clean
-
-clean:
-	rm -f *.o libjt9.a wsjtx.exe jt9sim.exe jt9.exe jt65.exe
+# Makefile for MinGW on Windows
+# Windows re-direct:
+#   C> make > junk1 2>&1
+
+# Set paths
+EXE_DIR = ../../wsjtx_install
+INCPATH = -I'c:/QtSDK/Desktop/Qt/4.7.4/mingw/include/QtCore' \
+	 -I'c:/QtSDK/Desktop/Qt/4.7.4/mingw/include' \
+	 -I'c:/QtSDK/Desktop/Qt/4.7.4/mingw/include/ActiveQt' \
+	 -I'release' -I'.' -I'c:/QtSDK/Desktop/Qt/4.7.4/mingw/mkspecs/win32-g++'
+
+# Compilers
+CC = gcc
+CXX = g++
+FC = g95
+
+FFLAGS = -O2 -fbounds-check -Wall -Wno-precision-loss -fno-second-underscore
+CFLAGS = -I. -fbounds-check -mno-stack-arg-probe
+
+# Default rules
+%.o: %.c
+	${CC} ${CFLAGS} -c $<
+%.o: %.f
+	${FC} ${FFLAGS} -c $<
+%.o: %.F
+	${FC} ${FFLAGS} -c $<
+%.o: %.f90
+	${FC} ${FFLAGS} -c $<
+%.o: %.F90
+	${FC} ${FFLAGS} -c $<
+
+all:    libjt9.a jt9sim.exe jt9.exe jt9code.exe jt65.exe
+
+OBJS1 = pctile.o graycode.o sort.o ssort.o \
+	unpackmsg.o igray.o unpackcall.o unpackgrid.o \
+	grid2k.o unpacktext.o getpfx2.o packmsg.o deg2grid.o \
+	packtext.o getpfx1.o packcall.o k2grid.o packgrid.o \
+	nchar.o four2a.o grid2deg.o pfxdump.o f77_wisdom.o \
+	symspec.o analytic.o db.o genjt9.o \
+	packbits.o unpackbits.o encode232.o interleave9.o \
+	entail.o fano232.o gran.o sync9.o decode9.o \
+	fil3.o decoder.o grid2n.o n2grid.o timer.o \
+	softsym.o getlags.o afc9.o fchisq.o twkfreq.o downsam9.o \
+	peakdt9.o symspec2.o stdmsg.o morse.o azdist.o geodist.o \
+	fillcom.o chkss2.o zplot9.o flat2.o \
+	jt65a.o symspec65.o flat65.o ccf65.o decode65a.o \
+	filbig.o fil6521.o afc65b.o decode65b.o setup65.o \
+	extract.o fchisq65.o demod64a.o chkhist.o interleave63.o ccf2.o \
+	move.o indexx.o graycode65.o twkfreq65.o smo121.o \
+	wrapkarn.o init_rs.o encode_rs.o decode_rs.o gen65.o
+
+libjt9.a: $(OBJS1)
+	ar cr libjt9.a $(OBJS1) 
+	ranlib libjt9.a
+
+OBJS2 = jt9.o jt9a.o jt9b.o jt9c.o ipcomm.o sec_midn.o usleep.o
+LIBS2 = -L'c:/QtSDK/Desktop/Qt/4.7.4/mingw/lib' -lQtCore4
+jt9.exe: $(OBJS2) libjt9.a
+	$(CXX) -o jt9.exe $(OBJS2) $(LIBS2) libjt9.a ../libfftw3f_win.a \
+	c:/MinGW/lib/libf95.a
+	mkdir -p $(EXE_DIR)
+	cp jt9.exe $(EXE_DIR)
+
+OBJS3 = jt9sim.o 
+jt9sim.exe: $(OBJS3) libjt9.a
+	$(FC) -o jt9sim.exe $(OBJS3) libjt9.a
+
+OBJS4 = jt9code.o 
+jt9code.exe: $(OBJS4) libjt9.a
+	$(FC) -o jt9code.exe $(OBJS4) libjt9.a
+
+OBJS5 = jt65.o 
+jt65.exe: $(OBJS5) libjt9.a 
+	$(FC) -o jt65.exe $(OBJS5) libjt9.a ../libfftw3f_win.a
+
+sync9.o: sync9.f90 jt9sync.f90
+	$(FC) $(FFLAGS) -c sync9.f90
+
+spec9.o: spec9.f90 jt9sync.f90
+	$(FC) $(FFLAGS) -c spec9.f90
+
+peakdt9.o: peakdt9.f90 jt9sync.f90
+	$(FC) $(FFLAGS) -c peakdt9.f90
+
+jt9sim.o: jt9sim.f90 jt9sync.f90
+	$(FC) $(FFLAGS) -c jt9sim.f90
+
+genjt9.o: genjt9.f90 jt9sync.f90
+	$(FC) $(FFLAGS) -c genjt9.f90
+
+redsync.o: redsync.f90 jt9sync.f90
+	$(FC) $(FFLAGS) -c redsync.f90
+
+unpackmsg.o: unpackmsg.f90
+	$(FC) -c -O0 -fbounds-check -Wall -Wno-precision-loss unpackmsg.f90
+
+ipcomm.o: ipcomm.cpp
+	$(CXX) -c $(INCPATH) ipcomm.cpp
+
+sec_midn.o: sec_midn.f90
+	$(FC) -c -fno-second-underscore sec_midn.f90
+
+#rig_control.o: rig_control.c
+#	$(CC) -c -Wall -I..\..\..\hamlib-1.2.15.3\include rig_control.c
+
+tstrig.o: tstrig.c
+	$(CC) -c -Wall -I..\..\..\hamlib-1.2.15.3\include tstrig.c
+
+init_rs.o: init_rs.c
+	$(CC) -c -DBIGSYM=1 -o init_rs.o init_rs.c
+
+encode_rs.o: encode_rs.c
+	$(CC) -c -DBIGSYM=1 -o encode_rs.o encode_rs.c
+
+decode_rs.o: decode_rs.c
+	$(CC) -c -DBIGSYM=1 -o decode_rs.o decode_rs.c
+
+
+.PHONY : clean
+
+clean:
+	rm -f *.o libjt9.a wsjtx.exe jt9sim.exe jt9.exe jt65.exe
diff --git a/lib/Makefile.MinGW b/lib/Makefile.jtsdk
similarity index 61%
copy from lib/Makefile.MinGW
copy to lib/Makefile.jtsdk
index e09924b..ce113a5 100644
--- a/lib/Makefile.MinGW
+++ b/lib/Makefile.jtsdk
@@ -2,11 +2,19 @@
 # Windows re-direct:
 #   C> make > junk1 2>&1
 
-CC = gcc
-FC = g95
+# Set paths
+EXE_DIR = ../../wsjtx_install
 
-FFLAGS = -O2 -fbounds-check -Wall -Wno-precision-loss -fno-second-underscore
-CFLAGS = -I. -fbounds-check -mno-stack-arg-probe
+INCPATH = -I'C:/JTSDK/Qt5/5.2.1/mingw48_32/include/QtCore' \
+	-I'C:/JTSDK/Qt5/5.2.1/mingw48_32/include/' 
+
+# Compilers
+CC  = c:/JTSDK/Qt5/Tools/mingw48_32/bin/gcc
+FC = c:/JTSDK/Qt5/Tools/mingw48_32/bin/gfortran
+CXX = c:/JTSDK/Qt5/Tools/mingw48_32/bin/g++
+
+FFLAGS = -O3 -Wall -Wno-conversion -fno-second-underscore -DWIN32
+CFLAGS = -I. -DWIN32
 
 # Default rules
 %.o: %.c
@@ -20,16 +28,16 @@ CFLAGS = -I. -fbounds-check -mno-stack-arg-probe
 %.o: %.F90
 	${FC} ${FFLAGS} -c $<
 
-all:    libjt9.a jt9sim.exe jt9.exe jt9code.exe jt65.exe
+all:    libjt9.a libastro.a jt9.exe jt9code.exe jt65code.exe jt9sim.exe
 
-OBJS1 = pctile.o graycode.o sort.o ssort.o \
+OBJS1 = pctile.o graycode.o sort.o chkmsg.o \
 	unpackmsg.o igray.o unpackcall.o unpackgrid.o \
 	grid2k.o unpacktext.o getpfx2.o packmsg.o deg2grid.o \
 	packtext.o getpfx1.o packcall.o k2grid.o packgrid.o \
-	nchar.o four2a.o grid2deg.o pfxdump.o f77_wisdom.o \
-	symspec.o analytic.o db.o genjt9.o \
+	nchar.o four2a.o grid2deg.o pfxdump.o wisdom.o \
+	symspec.o analytic.o db.o genjt9.o flat1.o smo.o \
 	packbits.o unpackbits.o encode232.o interleave9.o \
-	entail.o fano232.o gran.o sync9.o decode9.o \
+	entail.o fano232.o gran.o sync9.o jt9fano.o \
 	fil3.o decoder.o grid2n.o n2grid.o timer.o \
 	softsym.o getlags.o afc9.o fchisq.o twkfreq.o downsam9.o \
 	peakdt9.o symspec2.o stdmsg.o morse.o azdist.o geodist.o \
@@ -38,18 +46,21 @@ OBJS1 = pctile.o graycode.o sort.o ssort.o \
 	filbig.o fil6521.o afc65b.o decode65b.o setup65.o \
 	extract.o fchisq65.o demod64a.o chkhist.o interleave63.o ccf2.o \
 	move.o indexx.o graycode65.o twkfreq65.o smo121.o \
-	wrapkarn.o init_rs.o encode_rs.o decode_rs.o gen65.o
+	wrapkarn.o init_rs.o encode_rs.o decode_rs.o gen65.o fil4.o \
+	flat4.o polfit.o determ.o baddata.o prog_args.o \
+	options.o fmtmsg.o decjt9.o
 
 libjt9.a: $(OBJS1)
 	ar cr libjt9.a $(OBJS1) 
 	ranlib libjt9.a
 
-OBJS2 = jt9.o jt9a.o jt9b.o jt9c.o ipcomm.o sec_midn.o cutil.o
-LIBS2 = -L'c:/QtSDK/Desktop/Qt/4.7.4/mingw/lib' -lQtCore4
+OBJS2 = jt9.o jt9a.o jt9b.o jt9c.o ipcomm.o sec_midn.o usleep.o 
+LIBS2 = -L'C:/JTSDK/Qt5/5.2.1/mingw48_32/lib' -lQt5Core
 jt9.exe: $(OBJS2) libjt9.a
-	g++ -o jt9.exe $(OBJS2) $(LIBS2) libjt9.a ../libfftw3f_win.a \
-	c:/MinGW/lib/libf95.a
-	cp jt9.exe ../../wsjtx_install
+	$(CXX) -o jt9.exe -static $(OBJS2) $(LIBS2) libjt9.a \
+	C:\JTSDK\fftw3f\libfftw3f-3.dll -lgfortran
+#	mkdir -p $(EXE_DIR)
+	cp jt9.exe $(EXE_DIR)
 
 OBJS3 = jt9sim.o 
 jt9sim.exe: $(OBJS3) libjt9.a
@@ -58,15 +69,24 @@ jt9sim.exe: $(OBJS3) libjt9.a
 OBJS4 = jt9code.o 
 jt9code.exe: $(OBJS4) libjt9.a
 	$(FC) -o jt9code.exe $(OBJS4) libjt9.a
+	cp jt9code.exe $(EXE_DIR)
 
 OBJS5 = jt65.o 
 jt65.exe: $(OBJS5) libjt9.a 
 	$(FC) -o jt65.exe $(OBJS5) libjt9.a ../libfftw3f_win.a
 
-INCPATH = -I'c:/QtSDK/Desktop/Qt/4.7.4/mingw/include/QtCore' \
-	 -I'c:/QtSDK/Desktop/Qt/4.7.4/mingw/include' \
-	 -I'c:/QtSDK/Desktop/Qt/4.7.4/mingw/include/ActiveQt' \
-	 -I'release' -I'.' -I'c:/QtSDK/Desktop/Qt/4.7.4/mingw/mkspecs/win32-g++'
+OBJS7 = astrosub.o astro0.o astro.o tm2.o grid2deg.o sun.o moondop.o \
+	coord.o dot.o moon2.o tmoonsub.o toxyz.o geocentric.o \
+	dcoord.o
+
+libastro.a: $(OBJS7)
+	ar cr libastro.a $(OBJS7)
+	ranlib libastro.a
+
+OBJS6 = jt65code.o
+jt65code.exe: $(OBJS6) libjt9.a
+	$(FC) -o jt65code.exe $(OBJS6) libjt9.a
+	cp jt65code.exe $(EXE_DIR)
 
 sync9.o: sync9.f90 jt9sync.f90
 	$(FC) $(FFLAGS) -c sync9.f90
@@ -90,7 +110,7 @@ unpackmsg.o: unpackmsg.f90
 	$(FC) -c -O0 -fbounds-check -Wall -Wno-precision-loss unpackmsg.f90
 
 ipcomm.o: ipcomm.cpp
-	g++ -c $(INCPATH) ipcomm.cpp
+	$(CXX) -c $(INCPATH) ipcomm.cpp
 
 sec_midn.o: sec_midn.f90
 	$(FC) -c -fno-second-underscore sec_midn.f90
diff --git a/lib/Makefile.linux b/lib/Makefile.linux
index 19e6096..14bc077 100644
--- a/lib/Makefile.linux
+++ b/lib/Makefile.linux
@@ -1,8 +1,19 @@
+# Set paths
+EXE_DIR = ../../wsjtx_install
+QT_DIR = /usr/include/qt5
+INCPATH = -I${QT_DIR} -I${QT_DIR}/QtCore
+
 CC = gcc
+CXX = g++
 FC = gfortran
+AR = ar cr
+MKDIR = mkdir -p
+CP = cp
+RANLIB = ranlib
+RM = rm -f
 
-FFLAGS = -O2 -fbounds-check -Wall -Wno-conversion -fno-second-underscore
-CFLAGS = -I. -fbounds-check -mno-stack-arg-probe
+FFLAGS = -O3 -funroll-loops -Wall -Wno-conversion -fno-second-underscore -DUNIX
+CFLAGS = -I. -fbounds-check -fPIE
 
 # Default rules
 %.o: %.c
@@ -16,54 +27,54 @@ CFLAGS = -I. -fbounds-check -mno-stack-arg-probe
 %.o: %.F90
 	${FC} ${FFLAGS} -c $<
 
-all:    libjt9.a jt9sim jt9 jt9code
+all:    libjt9.a jt9sim jt9 jt9code jt65code
 
-OBJS1 = pctile.o graycode.o sort.o ssort.o \
+OBJS1 = astrosub.o astro0.o astro.o tm2.o sun.o moondop.o coord.o tmoonsub.o \
+        fmtmsg.o geocentric.o moon2.o toxyz.o dot.o dcoord.o \
+        prog_args.o options.o pctile.o graycode.o sort.o chkmsg.o \
 	unpackmsg.o igray.o unpackcall.o unpackgrid.o \
 	grid2k.o unpacktext.o getpfx2.o packmsg.o deg2grid.o \
 	packtext.o getpfx1.o packcall.o k2grid.o packgrid.o \
-	nchar.o four2a.o grid2deg.o pfxdump.o f77_wisdom.o \
-	symspec.o analytic.o db.o genjt9.o \
+	nchar.o four2a.o grid2deg.o pfxdump.o wisdom.o \
+	symspec.o analytic.o db.o genjt9.o jt9fano.o \
 	packbits.o unpackbits.o encode232.o interleave9.o \
-	entail.o fano232.o gran.o sync9.o decode9.o \
+	entail.o fano232.o gran.o sync9.o decjt9.o \
 	fil3.o decoder.o grid2n.o n2grid.o timer.o \
 	softsym.o peakdt9.o getlags.o afc9.o fchisq.o \
 	twkfreq.o downsam9.o symspec2.o ipcomm.o sleep_msec.o \
-	stdmsg.o sec_midn.o cutil.o azdist.o geodist.o morse.o \
-	fillcom.o chkss2.o zplot9.o flat2.o \
+	stdmsg.o sec_midn.o usleep.o azdist.o geodist.o morse.o \
+	fillcom.o chkss2.o zplot9.o flat1.o flat2.o \
 	jt65a.o symspec65.o flat65.o ccf65.o decode65a.o \
 	filbig.o fil6521.o afc65b.o decode65b.o setup65.o \
 	extract.o fchisq65.o demod64a.o chkhist.o interleave63.o ccf2.o \
-	move.o indexx.o graycode65.o twkfreq65.o smo121.o \
-	wrapkarn.o init_rs.o encode_rs.o decode_rs.o gen65.o
+	move.o indexx.o graycode65.o twkfreq65.o smo.o smo121.o \
+	wrapkarn.o init_rs.o encode_rs.o decode_rs.o gen65.o fil4.o \
+	flat4.o polfit.o determ.o baddata.o
 
 libjt9.a: $(OBJS1)
-	ar cr libjt9.a $(OBJS1) 
-	ranlib libjt9.a
+	$(AR) libjt9.a $(OBJS1) 
+	$(RANLIB) libjt9.a
 
 OBJS2 = jt9.o jt9a.o jt9b.o jt9c.o
 
 jt9: 	$(OBJS2) libjt9.a 
-	g++ -o jt9 $(OBJS2) libjt9.a -lfftw3f -lgfortran -lQtCore
-	cp jt9 ../../wsjtx_install
+	$(CXX) -o jt9 $(OBJS2) -L. -ljt9 -lQt5Core -lfftw3f_threads -lfftw3f `$(FC) -print-file-name=libgfortran.so`
+	$(MKDIR) -p $(EXE_DIR)
+	$(CP) jt9 $(EXE_DIR)
 
 OBJS3 = jt9sim.o 
 jt9sim: $(OBJS3) libjt9.a
-	$(FC) -o jt9sim $(OBJS3) libjt9.a
+	$(FC) -o jt9sim $(OBJS3) -L. -ljt9
 
 OBJS4 = jt9code.o 
 jt9code: $(OBJS4) libjt9.a
-	$(FC) -o jt9code $(OBJS4) libjt9.a
-
-#INCPATH = -I'c:/QtSDK/Desktop/Qt/4.7.4/mingw/include/QtCore' \
-#	 -I'c:/QtSDK/Desktop/Qt/4.7.4/mingw/include' \
-#	 -I'c:/QtSDK/Desktop/Qt/4.7.4/mingw/include/ActiveQt' \
-#	 -I'release' -I'.' -I'c:/QtSDK/Desktop/Qt/4.7.4/mingw/mkspecs/win32-g++'
-
-INCPATH =  -I'/usr/include/qt4' -I'/usr/include/qt4/QtCore' 
+	$(FC) -o jt9code $(OBJS4) -L. -ljt9
+	$(CP) jt9code $(EXE_DIR)
 
-#jt9.o:	jt9.f90
-#	$(FC) -O0 -c jt9.f90
+OBJS6 = jt65code.o
+jt65code: $(OBJS6) libjt9.a
+	$(FC) -o jt65code $(OBJS6) libjt9.a
+	$(CP) jt65code $(EXE_DIR)
 
 sync9.o: sync9.f90 jt9sync.f90
 	$(FC) $(FFLAGS) -c sync9.f90
@@ -84,7 +95,7 @@ redsync.o: redsync.f90 jt9sync.f90
 	$(FC) $(FFLAGS) -c redsync.f90
 
 ipcomm.o: ipcomm.cpp
-	g++ -c $(INCPATH) ipcomm.cpp
+	$(CXX) -c $(INCPATH) -fPIE ipcomm.cpp
 
 sec_midn.o: sec_midn.f90
 	$(FC) -c -fno-second-underscore sec_midn.f90
@@ -101,4 +112,4 @@ decode_rs.o: decode_rs.c
 .PHONY : clean
 
 clean:
-	rm -f *.o libjt9.a wsjtx jt9sim jt9 jt9code
+	$(RM) *.o libjt9.a wsjtx jt9sim jt9 jt9code
diff --git a/lib/afc65b.f90 b/lib/afc65b.f90
index f78f275..848ba85 100644
--- a/lib/afc65b.f90
+++ b/lib/afc65b.f90
@@ -1,59 +1,59 @@
-subroutine afc65b(cx,npts,fsample,nflip,a,ccfbest,dtbest)
-
-! Find delta f, f1, f2 ==> a(1:3)
-
-  complex cx(npts)
-  real a(5),deltaa(5)
-
-  a(1)=0.
-  a(2)=0.
-  a(3)=0.
-  a(4)=0.
-  deltaa(1)=2.0
-  deltaa(2)=2.0
-  deltaa(3)=2.0
-  deltaa(4)=0.05
-  nterms=3                                  !Maybe 2 is enough?
-
-!  Start the iteration
-  chisqr=0.
-  chisqr0=1.e6
-  do iter=1,3                               !One iteration is enough?
-     do j=1,nterms
-        chisq1=fchisq65(cx,npts,fsample,nflip,a,ccfmax,dtmax)
-        fn=0.
-        delta=deltaa(j)
-10      a(j)=a(j)+delta
-        chisq2=fchisq65(cx,npts,fsample,nflip,a,ccfmax,dtmax)
-        if(chisq2.eq.chisq1) go to 10
-        if(chisq2.gt.chisq1) then
-           delta=-delta                      !Reverse direction
-           a(j)=a(j)+delta
-           tmp=chisq1
-           chisq1=chisq2
-           chisq2=tmp
-        endif
-20      fn=fn+1.0
-        a(j)=a(j)+delta
-        chisq3=fchisq65(cx,npts,fsample,nflip,a,ccfmax,dtmax)
-        if(chisq3.lt.chisq2) then
-           chisq1=chisq2
-           chisq2=chisq3
-           go to 20
-        endif
-
-! Find minimum of parabola defined by last three points
-        delta=delta*(1./(1.+(chisq1-chisq2)/(chisq3-chisq2))+0.5)
-        a(j)=a(j)-delta
-        deltaa(j)=deltaa(j)*fn/3.
-     enddo
-     chisqr=fchisq65(cx,npts,fsample,nflip,a,ccfmax,dtmax)
-     if(chisqr/chisqr0.gt.0.9999) go to 30
-     chisqr0=chisqr
-  enddo
-
-30 ccfbest=ccfmax * (1378.125/fsample)**2
-  dtbest=dtmax
-
-  return
-end subroutine afc65b
+subroutine afc65b(cx,npts,fsample,nflip,a,ccfbest,dtbest)
+
+! Find delta f, f1, f2 ==> a(1:3)
+
+  complex cx(npts)
+  real a(5),deltaa(5)
+
+  a(1)=0.
+  a(2)=0.
+  a(3)=0.
+  a(4)=0.
+  deltaa(1)=2.0
+  deltaa(2)=2.0
+  deltaa(3)=2.0
+  deltaa(4)=0.05
+  nterms=3                                  !Maybe 2 is enough?
+
+!  Start the iteration
+  chisqr=0.
+  chisqr0=1.e6
+  do iter=1,3                               !One iteration is enough?
+     do j=1,nterms
+        chisq1=fchisq65(cx,npts,fsample,nflip,a,ccfmax,dtmax)
+        fn=0.
+        delta=deltaa(j)
+10      a(j)=a(j)+delta
+        chisq2=fchisq65(cx,npts,fsample,nflip,a,ccfmax,dtmax)
+        if(chisq2.eq.chisq1) go to 10
+        if(chisq2.gt.chisq1) then
+           delta=-delta                      !Reverse direction
+           a(j)=a(j)+delta
+           tmp=chisq1
+           chisq1=chisq2
+           chisq2=tmp
+        endif
+20      fn=fn+1.0
+        a(j)=a(j)+delta
+        chisq3=fchisq65(cx,npts,fsample,nflip,a,ccfmax,dtmax)
+        if(chisq3.lt.chisq2) then
+           chisq1=chisq2
+           chisq2=chisq3
+           go to 20
+        endif
+
+! Find minimum of parabola defined by last three points
+        delta=delta*(1./(1.+(chisq1-chisq2)/(chisq3-chisq2))+0.5)
+        a(j)=a(j)-delta
+        deltaa(j)=deltaa(j)*fn/3.
+     enddo
+     chisqr=fchisq65(cx,npts,fsample,nflip,a,ccfmax,dtmax)
+     if(chisqr/chisqr0.gt.0.9999) go to 30
+     chisqr0=chisqr
+  enddo
+
+30 ccfbest=ccfmax * (1378.125/fsample)**2
+  dtbest=dtmax
+
+  return
+end subroutine afc65b
diff --git a/lib/afc9.f90 b/lib/afc9.f90
index 1fbcf2f..4432373 100644
--- a/lib/afc9.f90
+++ b/lib/afc9.f90
@@ -1,58 +1,79 @@
-subroutine afc9(c3,npts,fsample,a,syncpk)
-
-  complex c3(0:npts-1)
-  real a(3),deltaa(3)
-
-  a(1)=0.                                   !f0
-  a(2)=0.                                   !f1
-  a(3)=0.                                   !f2
-  deltaa(1)=0.2
-  deltaa(2)=0.01
-  deltaa(3)=0.01
-  nterms=3
-
-! Start the iteration
-  chisqr=0.
-  chisqr0=1.e6
-  do iter=1,4                               !One iteration is enough?
-     do j=1,nterms
-        chisq1=fchisq(c3,npts,fsample,a)
-        fn=0.
-        delta=deltaa(j)
-10      a(j)=a(j)+delta
-        chisq2=fchisq(c3,npts,fsample,a)
-        if(chisq2.eq.chisq1) go to 10
-        if(chisq2.gt.chisq1) then
-           delta=-delta                      !Reverse direction
-           a(j)=a(j)+delta
-           tmp=chisq1
-           chisq1=chisq2
-           chisq2=tmp
-        endif
-20      fn=fn+1.0
-        a(j)=a(j)+delta
-        chisq3=fchisq(c3,npts,fsample,a)
-        if(chisq3.lt.chisq2) then
-           chisq1=chisq2
-           chisq2=chisq3
-           go to 20
-        endif
-
-! Find minimum of parabola defined by last three points
-        delta=delta*(1./(1.+(chisq1-chisq2)/(chisq3-chisq2))+0.5)
-        a(j)=a(j)-delta
-        deltaa(j)=deltaa(j)*fn/3.
-!        write(*,4000) iter,j,a,deltaa,-chisq2
-!4000    format(i1,i2,6f10.4,f9.3)
-     enddo
-     chisqr=fchisq(c3,npts,fsample,a)
-     if(chisqr/chisqr0.gt.0.9999) exit
-     chisqr0=chisqr
-  enddo
-
-  syncpk=-chisqr
-!  write(*,4001) a,deltaa,-chisq2
-!4001 format(3x,6f10.4,f9.3)
-
-  return
-end subroutine afc9
+subroutine afc9(c3a,npts,fsample,a,syncpk)
+
+  complex c3a(0:npts-1)
+  complex c3(0:1360-1)
+  real a(3),deltaa(3)
+
+  a(1)=0.                                   !f0
+  a(2)=0.                                   !f1
+  a(3)=0.                                   !f2
+  deltaa(1)=1.736
+  deltaa(2)=1.736
+  deltaa(3)=1.0
+  nterms=3
+
+! Start the iteration
+  chisqr=0.
+  chisqr0=1.e6
+  c3=c3a
+  a3=a(3)
+  do iter=1,4
+     do j=1,nterms
+        if(a(3).ne.a3) call shft(c3a,a(3),a3,c3)
+        chisq1=fchisq(c3,npts,fsample,a)
+        fn=0.
+        delta=deltaa(j)
+10      a(j)=a(j)+delta
+        if(a(3).ne.a3) call shft(c3a,a(3),a3,c3)
+        chisq2=fchisq(c3,npts,fsample,a)
+        if(chisq2.eq.chisq1) go to 10
+        if(chisq2.gt.chisq1) then
+           delta=-delta                      !Reverse direction
+           a(j)=a(j)+delta
+           tmp=chisq1
+           chisq1=chisq2
+           chisq2=tmp
+        endif
+20      fn=fn+1.0
+        a(j)=a(j)+delta
+        if(a(3).ne.a3) call shft(c3a,a(3),a3,c3)
+        chisq3=fchisq(c3,npts,fsample,a)
+        if(chisq3.lt.chisq2) then
+           chisq1=chisq2
+           chisq2=chisq3
+           go to 20
+        endif
+
+! Find minimum of parabola defined by last three points
+        delta=delta*(1./(1.+(chisq1-chisq2)/(chisq3-chisq2))+0.5)
+        a(j)=a(j)-delta
+        if(j.lt.3) deltaa(j)=deltaa(j)*fn/3.
+!        write(*,4000) iter,j,a,-chisq2
+!4000    format(i1,i2,3f10.4,f11.3)
+     enddo
+     if(a(3).ne.a3) call shft(c3a,a(3),a3,c3)
+     chisqr=fchisq(c3,npts,fsample,a)
+     if(chisqr/chisqr0.gt.0.99) exit
+     chisqr0=chisqr
+  enddo
+
+  syncpk=-chisqr
+  c3a=c3
+!  write(*,4001) a,-chisq2
+!4001 format(3x,3f10.4,f11.3)
+
+  return
+end subroutine afc9
+
+subroutine shft(c3a,a3a,a3,c3)
+  complex c3a(0:1359)
+  complex  c3(0:1359)
+
+  a3=a3a
+  n=nint(a3)
+  c3=cshift(c3a,n)
+  if(n.gt.0) c3(1360-n:)=0.0
+  if(n.lt.0) c3(:n-1)=0.0
+
+  return
+end subroutine shft
diff --git a/lib/all_fft.out b/lib/all_fft.out
new file mode 100644
index 0000000..adb335f
--- /dev/null
+++ b/lib/all_fft.out
@@ -0,0 +1,2069 @@
+    NFFT     Time        rms      MHz   MFlops  iters  tplan
+-------------------------------------------------------------
+       8  0.0000002  0.00000007  32.00   480.0 1000000   0.0
+       9  0.0000002  0.00000011  37.16   589.0 1000000   0.0
+      10  0.0000003  0.00000008  37.65   625.3 1000000   0.0
+      12  0.0000003  0.00000008  43.89   786.6 1000000   0.0
+      14  0.0000003  0.00000009  42.67   812.2 1000000   0.0
+      15  0.0000003  0.00000011  51.89  1013.7 1000000   0.0
+      16  0.0000004  0.00000005  40.16   803.1 1000000   0.0
+      18  0.0000006  0.00000013  30.72   640.5 1000000   0.0
+      20  0.0000005  0.00000013  38.79   838.2 1000000   0.0
+      21  0.0000008  0.00000010  26.35   578.8 1000000   0.0
+      24  0.0000006  0.00000012  42.67   978.1 1000000   0.0
+      25  0.0000008  0.00000011  32.65   758.2 1000000   0.0
+      27  0.0000009  0.00000015  28.56   679.0 1000000   0.0
+      28  0.0000007  0.00000013  42.16  1013.5 1000000   0.0
+      30  0.0000007  0.00000013  43.64  1070.6 1000000   0.0
+      32  0.0000006  0.00000014  50.57  1264.2 1000000   0.0
+      35  0.0000011  0.00000012  30.48   781.6 1000000   0.0
+      36  0.0000008  0.00000015  47.51  1228.0 1000000   0.0
+      40  0.0000008  0.00000020  51.20  1362.4 1000000   0.0
+      42  0.0000010  0.00000014  40.42  1089.8 1000000   0.0
+      45  0.0000013  0.00000013  35.34   970.3 1000000   0.0
+      48  0.0000009  0.00000016  54.86  1531.9 1000000   0.0
+      49  0.0000015  0.00000015  32.84   921.9 1000000   0.0
+      50  0.0000011  0.00000015  46.38  1308.7 1000000   0.0
+      54  0.0000012  0.00000019  46.39  1334.8 1000000   0.0
+      56  0.0000010  0.00000016  58.28  1692.2 1000000   0.0
+      60  0.0000010  0.00000019  62.44  1844.1 1000000   0.0
+      63  0.0000019  0.00000016  33.05   987.7 1000000   0.0
+      64  0.0000010  0.00000019  62.53  1876.0 1000000   0.0
+      70  0.0000014  0.00000020  48.43  1484.3 1000000   0.0
+      72  0.0000010  0.00000021  69.82  2153.9 1000000   0.0
+      75  0.0000019  0.00000014  38.87  1210.5 1000000   0.0
+      80  0.0000012  0.00000018  68.27  2157.9 1000000   0.0
+      81  0.0000020  0.00000016  39.88  1264.1 1000000   0.0
+      84  0.0000012  0.00000019  68.05  2175.0 1000000   0.0
+      90  0.0000017  0.00000020  54.34  1763.8 1000000   0.0
+      96  0.0000013  0.00000019  75.85  2497.4 1000000   0.0
+      98  0.0000020  0.00000015  49.98  1652.9 1000000   0.0
+     100  0.0000015  0.00000022  67.72  2249.8 1000000   0.0
+     105  0.0000027  0.00000013  38.51  1292.8 1000000   0.0
+     108  0.0000016  0.00000020  65.52  2212.8 1000000   0.0
+     112  0.0000015  0.00000020  73.52  2502.3 1000000   0.0
+     120  0.0000014  0.00000020  88.79  3066.2 1000000   0.0
+     125  0.0000037  0.00000015  33.47  1165.8 1000000   0.0
+     126  0.0000025  0.00000021  50.40  1758.3 1000000   0.0
+     128  0.0000017  0.00000021  74.81  2618.4 1000000   0.0
+     135  0.0000032  0.00000017  41.54  1469.8 1000000   0.0
+     140  0.0000020  0.00000020  71.68  2555.1 1000000   0.0
+     144  0.0000018  0.00000019  82.29  2949.9 1000000   0.0
+     147  0.0000043  0.00000015  34.15  1229.3 1000000   0.0
+     150  0.0000024  0.00000023  63.37  2290.3 1000000   0.0
+     160  0.0000019  0.00000022  84.98  3111.1 1000000   0.0
+     162  0.0000033  0.00000023  49.49  1816.2 1000000   0.0
+     168  0.0000020  0.00000018  83.35  3080.7 1000000   0.0
+     175  0.0000048  0.00000015  36.72  1368.1 1000000   0.0
+     180  0.0000024  0.00000021  73.61  2757.4 1000000   0.0
+     189  0.0000051  0.00000018  37.25  1408.5  985442   0.0
+     192  0.0000020  0.00000021  97.91  3713.3 1000000   0.0
+     196  0.0000028  0.00000024  69.11  2631.4 1000000   0.0
+     200  0.0000024  0.00000022  83.12  3176.7 1000000   0.0
+     210  0.0000033  0.00000022  63.85  2462.7 1000000   0.0
+     216  0.0000029  0.00000022  75.75  2937.1 1000000   0.0
+     224  0.0000024  0.00000023  94.63  3693.9 1000000   0.0
+     225  0.0000051  0.00000014  43.87  1713.9  974881   0.0
+     240  0.0000029  0.00000021  82.36  3256.0 1000000   0.0
+     243  0.0000096  0.00000019  25.39  1005.9  522354   0.0
+     245  0.0000072  0.00000015  34.04  1350.9  694716   0.0
+     250  0.0000043  0.00000023  58.72  2338.6 1000000   0.0
+     252  0.0000033  0.00000023  77.17  3077.9 1000000   0.0
+     256  0.0000026  0.00000019  96.66  3866.4 1000000   0.0
+     270  0.0000046  0.00000024  58.68  2369.6 1000000   0.0
+     280  0.0000034  0.00000023  82.39  3348.9 1000000   0.0
+     288  0.0000029  0.00000021  97.78  3994.4 1000000   0.0
+     294  0.0000045  0.00000023  64.66  2650.9 1000000   0.0
+     300  0.0000039  0.00000023  76.19  3134.8 1000000   0.0
+     315  0.0000087  0.00000015  36.03  1495.2  571949   0.0
+     320  0.0000035  0.00000022  90.82  3779.0 1000000   0.0
+     324  0.0000047  0.00000025  69.00  2877.5 1000000   0.0
+     336  0.0000037  0.00000023  89.79  3767.6 1000000   0.0
+     343  0.0000107  0.00000016  32.08  1351.1  467702   0.0
+     350  0.0000059  0.00000022  59.39  2509.4  848381   0.0
+     360  0.0000044  0.00000023  82.73  3512.6 1000000   0.0
+     375  0.0000100  0.00000018  37.39  1598.5  498528   0.0
+     378  0.0000070  0.00000027  53.99  2311.5  714202   0.0
+     384  0.0000040  0.00000023  96.76  4153.2 1000000   0.0
+     392  0.0000049  0.00000024  79.39  3419.7 1000000   0.0
+     400  0.0000048  0.00000024  83.66  3615.7 1000000   0.0
+     405  0.0000111  0.00000017  36.58  1584.1  451556   0.0
+     420  0.0000052  0.00000022  80.62  3512.6  959733   0.0
+     432  0.0000052  0.00000024  82.69  3619.9  957101   0.0
+     441  0.0000143  0.00000019  30.86  1355.3  349835   0.0
+     448  0.0000047  0.00000024  94.94  4180.9 1000000   0.0
+     450  0.0000062  0.00000023  72.13  3178.5  801407   0.0
+     480  0.0000055  0.00000022  88.04  3920.8  917089   0.0
+     486  0.0000098  0.00000026  49.72  2218.8  511535   0.0
+     490  0.0000084  0.00000023  58.35  2607.1  595360   0.0
+     500  0.0000062  0.00000024  80.31  3600.0  803056   0.0
+     504  0.0000058  0.00000025  86.53  3883.9  858405   0.0
+     512  0.0000051  0.00000022 100.06  4502.6  977120   0.0
+     525  0.0000157  0.00000015  33.52  1514.5  319246   0.0
+     540  0.0000064  0.00000024  84.13  3818.0  778940   0.0
+     560  0.0000065  0.00000024  85.52  3903.6  763550   0.0
+     567  0.0000200  0.00000020  28.39  1298.4  250342   0.0
+     576  0.0000063  0.00000023  91.77  4207.4  796578   0.0
+     588  0.0000073  0.00000025  80.20  3689.2  681989   0.0
+     600  0.0000075  0.00000024  80.29  3705.0  669108   0.0
+     625  0.0000209  0.00000019  29.92  1389.4  239358   0.0
+     630  0.0000155  0.00000025  40.77  1895.5  323539   0.0
+     640  0.0000064  0.00000022 100.15  4667.9  782411   0.0
+     648  0.0000085  0.00000024  76.24  3560.6  588306   0.0
+     672  0.0000074  0.00000023  90.43  4246.7  672841   0.0
+     675  0.0000178  0.00000016  37.99  1785.5  281443   0.0
+     686  0.0000121  0.00000022  56.54  2663.5  412075   0.0
+     700  0.0000087  0.00000024  80.67  3812.1  576207   0.0
+     720  0.0000083  0.00000023  86.93  4125.4  603649   0.0
+     729  0.0000246  0.00000020  29.65  1409.9  203371   0.0
+     735  0.0000229  0.00000016  32.15  1530.6  218709   0.0
+     750  0.0000121  0.00000026  61.91  2956.3  412712   0.0
+     756  0.0000105  0.00000027  72.00  3442.5  476205   0.0
+     768  0.0000075  0.00000023 103.04  4938.1  670825   0.0
+     784  0.0000152  0.00000024  51.68  2484.7  329622   0.0
+     800  0.0000154  0.00000023  52.02  2508.3  325122   0.0
+     810  0.0000144  0.00000027  56.29  2719.1  347443   0.0
+     840  0.0000105  0.00000024  79.71  3871.4  474438   0.0
+     864  0.0000102  0.00000023  84.95  4143.4  491612   0.0
+     875  0.0000304  0.00000019  28.75  1405.1  164312   0.0
+     882  0.0000208  0.00000027  42.35  2071.9  240080   0.0
+     896  0.0000156  0.00000025  57.34  2812.0  320004   0.0
+     900  0.0000168  0.00000025  53.70  2635.2  298351   0.0
+     945  0.0000293  0.00000018  32.21  1591.7  170410   0.0
+     960  0.0000106  0.00000023  90.19  4467.6  469752   0.0
+     972  0.0000155  0.00000027  62.79  3116.1  323010   0.0
+     980  0.0000120  0.00000025  81.64  4056.1  416530   0.0
+    1000  0.0000174  0.00000026  57.41  2860.5  287032   0.0
+    1008  0.0000118  0.00000025  85.48  4264.2  423997   0.0
+    1024  0.0000099  0.00000024 103.50  5175.0  505373   0.0
+    1029  0.0000444  0.00000017  23.17  1159.4  112593   0.0
+    1050  0.0000239  0.00000025  43.89  2202.2  208978   0.0
+    1080  0.0000126  0.00000024  85.71  4318.2  396785   0.0
+    1120  0.0000205  0.00000024  54.63  2766.7  243874   0.0
+    1125  0.0000333  0.00000017  33.74  1709.7  149936   0.0
+    1134  0.0000286  0.00000027  39.60  2008.9  174586   0.0
+    1152  0.0000204  0.00000023  56.58  2876.9  245558   0.0
+    1176  0.0000146  0.00000025  80.45  4103.0  342062   0.0
+    1200  0.0000194  0.00000025  61.90  3166.0  257930   0.0
+    1215  0.0000406  0.00000018  29.91  1532.2  123073   0.0
+    1225  0.0000447  0.00000017  27.38  1404.1  111735   0.0
+    1250  0.0000303  0.00000027  41.28  2123.4  165125   0.0
+    1260  0.0000234  0.00000025  53.82  2771.4  213566   0.0
+    1280  0.0000242  0.00000023  52.98  2734.4  206960   0.0
+    1296  0.0000161  0.00000025  80.45  4159.0  310365   0.0
+    1323  0.0000512  0.00000020  25.82  1338.8   97586   0.0
+    1344  0.0000235  0.00000025  57.21  2972.5  212821   0.0
+    1350  0.0000276  0.00000026  48.91  2543.2  181165   0.0
+    1372  0.0000275  0.00000026  49.90  2600.3  181849   0.0
+    1400  0.0000247  0.00000025  56.60  2957.8  202147   0.0
+    1440  0.0000239  0.00000024  60.35  3166.1  209561   0.0
+    1458  0.0000385  0.00000028  37.87  1989.8  129858   0.0
+    1470  0.0000291  0.00000026  50.52  2657.6  171824   0.0
+    1500  0.0000179  0.00000026  83.78  4419.8  279271   0.0
+    1512  0.0000198  0.00000026  76.51  4040.7  253014   0.0
+    1536  0.0000329  0.00000024  46.74  2473.8  152156   0.0
+    1568  0.0000191  0.00000026  82.28  4366.9  262371   0.0
+    1575  0.0000486  0.00000016  32.39  1719.9  102814   0.0
+    1600  0.0000288  0.00000025  55.46  2951.5  173313   0.0
+    1620  0.0000316  0.00000026  51.34  2736.7  158447   0.0
+    1680  0.0000201  0.00000025  83.65  4481.4  248966   0.0
+    1701  0.0000574  0.00000021  29.61  1589.0   87045   0.0
+    1715  0.0000633  0.00000017  27.08  1454.9   78962   0.0
+    1728  0.0000192  0.00000024  90.09  4844.4  260672   0.0
+    1750  0.0000347  0.00000027  50.45  2717.3  144133   0.0
+    1764  0.0000356  0.00000028  49.62  2675.6  140641   0.0
+    1792  0.0000312  0.00000026  57.51  3107.6  160460   0.0
+    1800  0.0000333  0.00000025  54.09  2924.5  150245   0.0
+    1875  0.0000753  0.00000019  24.92  1354.5   66444   0.0
+    1890  0.0000424  0.00000028  44.62  2428.1  118037   0.0
+    1920  0.0000336  0.00000025  57.16  3117.0  148845   0.0
+    1944  0.0000383  0.00000028  50.82  2775.9  130706   0.0
+    1960  0.0000361  0.00000026  54.23  2965.5  138342   0.0
+    2000  0.0000362  0.00000026  55.20  3026.7  138005   0.0
+    2016  0.0000340  0.00000025  59.21  3250.0  146859   0.0
+    2025  0.0000666  0.00000018  30.42  1670.7   75114   0.0
+    2048  0.0000356  0.00000026  57.59  3167.3  140596   0.0
+    2058  0.0000452  0.00000027  45.52  2505.2  110594   0.0
+    2100  0.0000377  0.00000026  55.77  3077.4  132784   0.0
+    2160  0.0000365  0.00000025  59.19  3278.4  137021   0.0
+    2187  0.0001085  0.00000024  20.16  1118.4   46091   0.0
+    2205  0.0000874  0.00000017  25.22  1400.6   57189   0.0
+    2240  0.0000393  0.00000026  56.98  3171.0  127197   0.0
+    2250  0.0000359  0.00000027  62.60  3485.3  139104   0.0
+    2268  0.0000351  0.00000028  64.63  3602.1  142478   0.0
+    2304  0.0000391  0.00000026  58.92  3290.4  127856   0.0
+    2352  0.0000429  0.00000026  54.83  3070.4  116562   0.0
+    2400  0.0000435  0.00000026  55.14  3095.8  114876   0.0
+    2401  0.0001024  0.00000018  23.45  1316.4   48824   0.0
+    2430  0.0000477  0.00000028  50.94  2864.6  104817   0.0
+    2450  0.0000451  0.00000026  54.27  3054.9  110750   0.0
+    2500  0.0000359  0.00000028  69.62  3929.4  139245   0.0
+    2520  0.0000433  0.00000025  58.16  3285.6  115388   0.0
+    2560  0.0000302  0.00000025  84.90  4806.2  165822   0.0
+    2592  0.0000471  0.00000027  55.05  3121.1  106184   0.0
+    2625  0.0000961  0.00000019  27.32  1551.7   52045   0.0
+    2646  0.0000626  0.00000029  42.29  2404.2   79918   0.0
+    2688  0.0000312  0.00000026  86.27  4914.2  160478   0.0
+    2700  0.0000367  0.00000027  73.63  4196.5  136355   0.0
+    2744  0.0000550  0.00000027  49.91  2850.3   90942   0.0
+    2800  0.0000498  0.00000026  56.20  3218.0  100365   0.0
+    2835  0.0001106  0.00000019  25.62  1469.3   45188   0.0
+    2880  0.0000323  0.00000026  89.11  5120.0  154699   0.1
+    2916  0.0000654  0.00000030  44.56  2564.5   76411   0.0
+    2940  0.0000568  0.00000026  51.73  2980.3   87982   0.0
+    3000  0.0000544  0.00000027  55.17  3186.4   91953   0.0
+    3024  0.0000554  0.00000027  54.60  3156.7   90284   0.0
+    3072  0.0000571  0.00000026  53.82  3117.6   87601   0.0
+    3087  0.0001333  0.00000020  23.16  1342.2   37507   0.0
+    3125  0.0001327  0.00000022  23.56  1367.4   37689   0.0
+    3136  0.0000396  0.00000027  79.21  4600.2  126298   0.0
+    3150  0.0000672  0.00000026  46.89  2724.3   74422   0.0
+    3200  0.0000608  0.00000025  52.60  3062.5   82192   0.0
+    3240  0.0000599  0.00000026  54.10  3154.7   83493   0.0
+    3360  0.0000556  0.00000026  60.41  3538.1   89891   0.0
+    3375  0.0001065  0.00000017  31.70  1857.5   46956   0.0
+    3402  0.0000755  0.00000030  45.06  2643.5   66233   0.0
+    3430  0.0000629  0.00000026  54.52  3201.3   79472   0.0
+    3456  0.0000436  0.00000025  79.29  4660.2  114712   0.0
+    3500  0.0000509  0.00000028  68.70  4044.0   98142   0.0
+    3528  0.0000487  0.00000027  72.44  4268.6  102669   0.0
+    3584  0.0000437  0.00000027  81.96  4838.4  114336   0.0
+    3600  0.0000463  0.00000026  77.73  4591.2  107953   0.1
+    3645  0.0001266  0.00000020  28.79  1703.2   39493   0.0
+    3675  0.0001391  0.00000018  26.43  1565.0   35957   0.0
+    3750  0.0000726  0.00000030  51.65  3065.8   68860   0.0
+    3780  0.0000535  0.00000027  70.66  4198.6   93464   0.0
+    3840  0.0000455  0.00000025  84.43  5026.2  109929   0.0
+    3888  0.0000583  0.00000028  66.73  3978.7   85816   0.0
+    3920  0.0000562  0.00000026  69.77  4164.3   88996   0.0
+    3969  0.0001694  0.00000022  23.43  1400.3   29513   0.0
+    4000  0.0000554  0.00000027  72.17  4317.8   90212   0.0
+    4032  0.0000533  0.00000026  75.65  4530.4   93811   0.0
+    4050  0.0000871  0.00000027  46.49  2785.4   57391   0.0
+    4096  0.0000437  0.00000026  93.79  5627.5  114491   0.0
+    4116  0.0000621  0.00000028  66.31  3980.8   80549   0.0
+    4200  0.0000742  0.00000026  56.63  3408.3   67422   0.0
+    4320  0.0000714  0.00000026  60.48  3652.3   70005   0.1
+    4374  0.0001229  0.00000030  35.59  2152.1   40681   0.0
+    4375  0.0001865  0.00000021  23.46  1418.9   26815   0.0
+    4410  0.0001021  0.00000028  43.18  2613.8   48957   0.0
+    4480  0.0000760  0.00000026  58.91  3572.9   65752   0.0
+    4500  0.0000841  0.00000027  53.54  3248.6   59486   0.0
+    4536  0.0000895  0.00000028  50.66  3076.7   55839   0.0
+    4608  0.0000523  0.00000026  88.14  5363.1   95635   0.0
+    4704  0.0000883  0.00000027  53.29  3250.7   56645   0.0
+    4725  0.0001885  0.00000017  25.07  1530.0   26529   0.0
+    4800  0.0000875  0.00000026  54.88  3355.3   57162   0.1
+    4802  0.0000955  0.00000026  50.28  3074.3   52350   0.0
+    4860  0.0000809  0.00000028  60.10  3680.2   61833   0.0
+    4900  0.0000913  0.00000028  53.67  3289.8   54769   0.0
+    5000  0.0000911  0.00000029  54.86  3370.3   54856   0.0
+    5040  0.0000872  0.00000026  57.82  3555.9   57365   0.1
+    5103  0.0002313  0.00000023  22.06  1358.7   21616   0.0
+    5120  0.0000915  0.00000026  55.97  3448.1   54655   0.0
+    5145  0.0002207  0.00000018  23.31  1437.2   22657   0.0
+    5184  0.0000896  0.00000026  57.86  3570.0   55807   0.1
+    5250  0.0001237  0.00000029  42.44  2622.3   40417   0.0
+    5292  0.0001086  0.00000030  48.74  3014.2   46047   0.0
+    5376  0.0000925  0.00000027  58.13  3601.7   54063   0.0
+    5400  0.0001014  0.00000026  53.27  3302.5   49326   0.1
+    5488  0.0001039  0.00000028  52.84  3282.0   48143   0.0
+    5600  0.0001036  0.00000027  54.07  3366.3   48279   0.0
+    5625  0.0002091  0.00000019  26.90  1675.4   23909   0.0
+    5670  0.0001190  0.00000029  47.67  2971.8   42034   0.0
+    5760  0.0001060  0.00000027  54.35  3394.8   47181   0.1
+    5832  0.0001294  0.00000030  45.08  2819.5   38646   0.0
+    5880  0.0000863  0.00000028  68.12  4264.6   57922   0.0
+    6000  0.0001117  0.00000027  53.70  3369.8   44749   0.0
+    6048  0.0001099  0.00000028  55.03  3456.6   45496   0.1
+    6075  0.0002366  0.00000019  25.68  1613.5   21132   0.0
+    6125  0.0002655  0.00000019  23.07  1451.3   18835   0.0
+    6144  0.0001157  0.00000026  53.11  3342.2   43224   0.0
+    6174  0.0001560  0.00000030  39.59  2492.3   32058   0.0
+    6250  0.0001565  0.00000030  39.94  2518.2   31953   0.0
+    6272  0.0001148  0.00000028  54.64  3446.4   43560   0.0
+    6300  0.0001222  0.00000027  51.56  3253.5   40918   0.0
+    6400  0.0001180  0.00000026  54.23  3428.3   42366   0.0
+    6480  0.0001182  0.00000026  54.81  3469.8   42290   0.1
+    6561  0.0002934  0.00000025  22.37  1417.9   17044   0.0
+    6615  0.0002858  0.00000019  23.15  1469.0   17497   0.0
+    6720  0.0001179  0.00000027  57.00  3623.2   42407   0.1
+    6750  0.0001184  0.00000028  57.03  3627.5   42247   0.0
+    6804  0.0001505  0.00000031  45.21  2878.0   33222   0.0
+    6860  0.0001322  0.00000028  51.90  3307.1   37828   0.0
+    6912  0.0001279  0.00000026  54.04  3446.5   39093   0.1
+    7000  0.0001380  0.00000028  50.71  3238.4   36219   0.0
+    7056  0.0001340  0.00000028  52.64  3364.8   37300   0.0
+    7168  0.0001256  0.00000028  57.06  3654.2   39805   0.0
+    7200  0.0001333  0.00000027  54.02  3460.9   37513   0.1
+    7203  0.0003197  0.00000019  22.53  1443.4   15638   0.0
+    7290  0.0001970  0.00000030  37.00  2374.1   25380   0.0
+    7350  0.0001705  0.00000029  43.10  2767.6   29318   0.0
+    7500  0.0001120  0.00000029  66.97  4310.7   44650   0.0
+    7560  0.0001398  0.00000028  54.09  3484.3   35771   0.1
+    7680  0.0000947  0.00000026  81.10  5233.7   52799   0.1
+    7776  0.0001192  0.00000029  65.22  4214.6   41935   0.1
+    7840  0.0001480  0.00000027  52.96  3425.6   33775   0.0
+    7875  0.0003302  0.00000018  23.85  1543.3   15141   0.0
+    7938  0.0002099  0.00000031  37.82  2449.5   23820   0.0
+    8000  0.0001197  0.00000028  66.83  4332.3   41767   0.0
+    8064  0.0001486  0.00000027  54.26  3520.6   33642   0.1
+    8100  0.0001253  0.00000027  64.63  4195.7   39895   0.0
+    8192  0.0001520  0.00000027  53.89  3503.0   32893   0.0
+    8232  0.0001578  0.00000028  52.18  3393.7   31695   0.0
+    8400  0.0001557  0.00000027  53.97  3517.6   32123   0.1
+    8505  0.0003652  0.00000021  23.29  1520.2   13692   0.0
+    8575  0.0004191  0.00000019  20.46  1336.6   11930   0.0
+    8640  0.0001517  0.00000027  56.96  3724.5   32965   0.1
+    8748  0.0002103  0.00000032  41.59  2723.0   23771   0.0
+    8750  0.0002150  0.00000029  40.70  2664.9   23258   0.0
+    8820  0.0001679  0.00000028  52.52  3441.8   29773   0.0
+    8960  0.0001595  0.00000027  56.16  3686.7   31339   0.0
+    9000  0.0001729  0.00000028  52.05  3418.8   28919   0.1
+    9072  0.0001877  0.00000029  48.34  3177.7   26643   0.1
+    9216  0.0001671  0.00000027  55.15  3631.5   29920   0.1
+    9261  0.0004381  0.00000021  21.14  1392.7   11413   0.0
+    9375  0.0003846  0.00000021  24.38  1608.1   13000   0.0
+    9408  0.0001389  0.00000028  67.73  4469.8   35994   0.0
+    9450  0.0001876  0.00000029  50.38  3326.9   26658   0.0
+    9600  0.0001217  0.00000027  78.88  5217.4   41083   0.1
+    9604  0.0001722  0.00000030  55.76  3688.5   29031   0.0
+    9720  0.0001591  0.00000028  61.09  4046.1   31424   0.1
+    9800  0.0001503  0.00000029  65.19  4321.6   33260   0.0
+   10000  0.0001520  0.00000030  65.79  4371.0   32895   0.0
+   10080  0.0001453  0.00000027  69.37  4613.1   34412   0.1
+   10125  0.0003706  0.00000018  27.32  1817.4   13490   0.0
+   10206  0.0002497  0.00000032  40.88  2721.7   20025   0.0
+   10240  0.0001329  0.00000027  77.04  5131.3   37615   0.0
+   10290  0.0002037  0.00000029  50.51  3366.2   24543   0.0
+   10368  0.0001458  0.00000028  71.13  4744.1   34301   0.1
+   10500  0.0001582  0.00000029  66.38  4433.5   31609   0.0
+   10584  0.0001759  0.00000030  60.17  4022.4   28426   0.0
+   10752  0.0001429  0.00000028  75.27  5039.9   35001   0.1
+   10800  0.0001600  0.00000028  67.50  4522.2   31251   0.1
+   10935  0.0004906  0.00000022  22.29  1495.3   10192   0.0
+   10976  0.0001666  0.00000030  65.89  4422.0   30016   0.0
+   11025  0.0004408  0.00000018  25.01  1679.3   11343   0.0
+   11200  0.0002225  0.00000028  50.34  3385.5   22472   0.0
+   11250  0.0002747  0.00000031  40.96  2755.9   18203   0.0
+   11340  0.0002344  0.00000029  48.37  3257.5   21327   0.1
+   11520  0.0002043  0.00000027  56.38  3803.4   24471   0.1
+   11664  0.0002511  0.00000031  46.45  3137.4   19910   0.1
+   11760  0.0002230  0.00000028  52.73  3564.8   22418   0.0
+   11907  0.0005564  0.00000023  21.40  1448.7    8986   0.0
+   12000  0.0001828  0.00000028  65.65  4448.3   27356   0.1
+   12005  0.0005669  0.00000019  21.18  1434.9    8820   0.0
+   12096  0.0001818  0.00000028  66.54  4511.8   27503   0.1
+   12150  0.0003172  0.00000030  38.31  2598.8   15764   0.0
+   12250  0.0002984  0.00000029  41.05  2787.7   16757   0.0
+   12288  0.0002265  0.00000028  54.25  3685.2   22076   0.0
+   12348  0.0002598  0.00000031  47.53  3230.1   19246   0.0
+   12500  0.0002676  0.00000032  46.71  3178.5   18684   0.0
+   12544  0.0002392  0.00000029  52.44  3569.7   20902   0.0
+   12600  0.0002404  0.00000028  52.40  3569.0   20795   0.1
+   12800  0.0002560  0.00000027  50.00  3410.7   19530   0.1
+   12960  0.0002621  0.00000028  49.44  3377.2   19074   0.1
+   13122  0.0004087  0.00000033  32.11  2196.2   12235   0.0
+   13125  0.0006187  0.00000020  21.21  1450.9    8081   0.0
+   13230  0.0003438  0.00000031  38.48  2634.3   14543   0.0
+   13440  0.0002683  0.00000028  50.10  3435.3   18638   0.1
+   13500  0.0002695  0.00000029  50.10  3437.1   18556   0.1
+   13608  0.0003012  0.00000032  45.17  3101.6   16598   0.1
+   13720  0.0002828  0.00000030  48.52  3334.4   17683   0.0
+   13824  0.0002561  0.00000028  53.98  3712.3   19523   0.1
+   14000  0.0002831  0.00000030  49.45  3405.7   17662   0.0
+   14112  0.0002866  0.00000029  49.23  3393.4   17444   0.1
+   14175  0.0006101  0.00000020  23.23  1602.0    8195   0.0
+   14336  0.0002476  0.00000030  57.90  3997.0   20193   0.0
+   14400  0.0002809  0.00000028  51.27  3541.1   17802   0.1
+   14406  0.0003519  0.00000031  40.93  2827.3   14207   0.0
+   14580  0.0003342  0.00000031  43.62  3016.7   14959   0.0
+   14700  0.0002949  0.00000029  49.84  3449.9   16953   0.0
+   15000  0.0002934  0.00000030  51.13  3546.7   17044   0.0
+   15120  0.0002805  0.00000029  53.91  3742.6   17828   0.1
+   15309  0.0007220  0.00000025  21.20  1473.8    6925   0.0
+   15360  0.0002958  0.00000028  51.93  3611.1   16905   0.1
+   15435  0.0007356  0.00000019  20.98  1459.7    6797   0.0
+   15552  0.0003195  0.00000030  48.67  3388.7   15648   0.1
+   15625  0.0007816  0.00000025  19.99  1392.5    6397   0.0
+   15680  0.0002990  0.00000030  52.44  3654.2   16722   0.0
+   15750  0.0003775  0.00000030  41.72  2908.4   13244   0.0
+   15876  0.0003823  0.00000032  41.53  2897.3   13078   0.0
+   16000  0.0003197  0.00000029  50.05  3495.2   15642   0.1
+   16128  0.0003075  0.00000028  52.45  3665.6   16261   0.1
+   16200  0.0003190  0.00000028  50.78  3550.7   15674   0.1
+   16384  0.0003121  0.00000029  52.49  3674.4   16019   0.0
+   16464  0.0004225  0.00000030  38.97  2729.3   11835   0.0
+   16800  0.0004064  0.00000029  41.34  2901.1   12303   0.0
+   16807  0.0008811  0.00000020  19.08  1338.8    5675   0.0
+   16875  0.0007395  0.00000020  22.82  1602.1    6761   0.0
+   17010  0.0005292  0.00000029  32.15  2258.9    9449   0.0
+   17150  0.0005862  0.00000025  29.25  2057.5    8529   0.0
+   17280  0.0004072  0.00000028  42.43  2986.6   12278   0.1
+   17496  0.0005508  0.00000032  31.77  2238.6    9078   0.0
+   17500  0.0006523  0.00000028  26.83  1890.7    7665   0.0
+   17640  0.0004459  0.00000030  39.56  2790.5   11214   0.0
+   17920  0.0003422  0.00000028  52.37  3699.7   14612   0.0
+   18000  0.0004923  0.00000029  36.56  2584.1   10156   0.1
+   18144  0.0004081  0.00000031  44.46  3144.7   12251   0.1
+   18225  0.0008109  0.00000022  22.48  1590.5    6166   0.0
+   18375  0.0008784  0.00000020  20.92  1481.6    5692   0.0
+   18432  0.0004809  0.00000028  38.33  2715.5   10397   0.1
+   18522  0.0005449  0.00000030  33.99  2409.5    9176   0.0
+   18750  0.0006266  0.00000030  29.92  2123.6    7979   0.0
+   18816  0.0004812  0.00000029  39.10  2776.0   10390   0.0
+   18900  0.0004548  0.00000028  41.55  2951.6   10993   0.0
+   19200  0.0004522  0.00000028  42.46  3020.4   11056   0.1
+   19208  0.0005821  0.00000029  33.00  2347.8    8590   0.0
+   19440  0.0005187  0.00000030  37.48  2669.9    9640   0.1
+   19600  0.0005130  0.00000030  38.21  2724.0    9747   0.0
+   19683  0.0012080  0.00000027  16.29  1162.1    4139   0.0
+   19845  0.0009337  0.00000021  21.25  1517.2    5355   0.0
+   20000  0.0005164  0.00000031  38.73  2767.0    9683   0.0
+   20160  0.0005004  0.00000028  40.29  2880.7    9993   0.1
+   20250  0.0005921  0.00000028  34.20  2446.4    8445   0.0
+   20412  0.0005655  0.00000032  36.10  2584.0    8842   0.0
+   20480  0.0005245  0.00000028  39.05  2796.2    9533   0.0
+   20580  0.0010638  0.00000020  19.35  1386.0    4700   0.0
+   20736  0.0005076  0.00000028  40.85  2929.2    9851   0.1
+   21000  0.0006244  0.00000031  33.63  2414.6    8008   0.0
+   21168  0.0005705  0.00000031  37.11  2666.1    8765   0.0
+   21504  0.0004951  0.00000029  43.43  3125.3   10098   0.0
+   21600  0.0005391  0.00000028  40.07  2884.6    9275   0.1
+   21609  0.0010951  0.00000022  19.73  1420.7    4566   0.0
+   21870  0.0007083  0.00000030  30.88  2225.6    7059   0.0
+   21875  0.0011351  0.00000024  19.27  1389.2    4405   0.0
+   21952  0.0005677  0.00000030  38.67  2788.6    8808   0.0
+   22050  0.0006672  0.00000028  33.05  2384.2    7494   0.0
+   22400  0.0006109  0.00000029  36.66  2649.2    8184   0.0
+   22500  0.0007044  0.00000029  31.94  2309.0    7098   0.0
+   22680  0.0006210  0.00000031  36.52  2642.0    8051   0.1
+   23040  0.0004213  0.00000028  54.69  3963.0   11869   0.1
+   23328  0.0005473  0.00000031  42.62  3092.1    9135   0.1
+   23520  0.0005104  0.00000029  46.09  3346.1    9797   0.0
+   23625  0.0011030  0.00000020  21.42  1555.8    4533   0.0
+   23814  0.0007635  0.00000031  31.19  2267.6    6549   0.0
+   24000  0.0004985  0.00000029  48.14  3502.7   10030   0.1
+   24010  0.0005144  0.00000030  46.68  3396.0    9720   0.1
+   24192  0.0004989  0.00000029  48.50  3531.0   10023   0.1
+   24300  0.0007742  0.00000028  31.39  2286.3    6458   0.0
+   24500  0.0007221  0.00000028  33.93  2473.4    6924   0.0
+   24576  0.0004608  0.00000028  53.33  3889.1   10850   0.0
+   24696  0.0006932  0.00000031  35.63  2599.3    7213   0.0
+   25000  0.0006889  0.00000032  36.29  2650.9    7258   0.0
+   25088  0.0005925  0.00000030  42.34  3094.2    8439   0.0
+   25200  0.0006510  0.00000029  38.71  2829.7    7680   0.1
+   25515  0.0012960  0.00000022  19.69  1441.0    3858   0.0
+   25600  0.0004787  0.00000028  53.48  3915.6   10445   0.1
+   25725  0.0013441  0.00000020  19.14  1402.0    3720   0.0
+   25920  0.0006472  0.00000029  40.05  2935.8    7725   0.1
+   26244  0.0008798  0.00000033  29.83  2189.4    5683   0.0
+   26250  0.0008887  0.00000029  29.54  2168.0    5626   0.0
+   26460  0.0008240  0.00000029  32.11  2358.9    6068   0.0
+   26880  0.0005164  0.00000029  52.06  3829.8    9683   0.1
+   27000  0.0006492  0.00000030  41.59  3061.2    7702   0.1
+   27216  0.0007853  0.00000032  34.66  2552.9    6367   0.1
+   27440  0.0007086  0.00000030  38.72  2854.7    7056   0.0
+   27648  0.0006702  0.00000028  41.26  3043.7    7461   0.1
+   27783  0.0015337  0.00000024  18.11  1337.0    3260   0.0
+   28000  0.0006075  0.00000030  46.09  3404.3    8230   0.0
+   28125  0.0012990  0.00000022  21.65  1599.9    3849   0.0
+   28224  0.0005987  0.00000030  47.15  3485.1    8352   0.1
+   28350  0.0008318  0.00000029  34.08  2520.6    6011   0.0
+   28672  0.0006654  0.00000030  43.09  3190.1    7514   0.0
+   28800  0.0007367  0.00000029  39.09  2895.6    6787   0.1
+   28812  0.0016287  0.00000022  17.69  1310.4    3070   0.0
+   29160  0.0009764  0.00000032  29.87  2214.8    5121   0.1
+   29400  0.0008798  0.00000031  33.42  2480.1    5683   0.0
+   30000  0.0007664  0.00000031  39.14  2910.9    6524   0.0
+   30240  0.0006426  0.00000030  47.06  3502.2    7781   0.1
+   30375  0.0013189  0.00000020  23.03  1714.7    3791   0.0
+   30618  0.0010489  0.00000033  29.19  2175.0    4767   0.0
+   30625  0.0016113  0.00000021  19.01  1416.2    3103   0.0
+   30720  0.0007343  0.00000028  41.83  3118.1    6809   0.1
+   30870  0.0009430  0.00000029  32.73  2441.0    5302   0.0
+   31104  0.0008159  0.00000030  38.12  2844.7    6128   0.1
+   31250  0.0011114  0.00000031  28.12  2099.3    4499   0.0
+   31360  0.0008001  0.00000029  39.19  2927.1    6249   0.0
+   31500  0.0008381  0.00000029  37.59  2808.2    5966   0.0
+   31752  0.0010593  0.00000033  29.97  2241.2    4720   0.0
+   32000  0.0008046  0.00000030  39.77  2975.9    6214   0.0
+   32256  0.0008121  0.00000029  39.72  2974.5    6157   0.1
+   32400  0.0008281  0.00000029  39.13  2931.3    6038   0.1
+   32768  0.0007732  0.00000029  42.38  3178.7    6467   0.0
+   32805  0.0015305  0.00000024  21.43  1607.8    3267   0.0
+   32928  0.0008331  0.00000031  39.53  2965.9    6002   0.0
+   33075  0.0016739  0.00000021  19.76  1483.3    2987   0.0
+   33600  0.0008495  0.00000029  39.55  2973.7    5886   0.1
+   33614  0.0008898  0.00000030  37.78  2840.1    5619   0.0
+   33750  0.0010598  0.00000030  31.85  2395.3    4718   0.0
+   34020  0.0010389  0.00000029  32.75  2464.9    4813   0.0
+   34300  0.0010916  0.00000028  31.42  2367.0    4584   0.0
+   34560  0.0008384  0.00000028  41.22  3107.6    5964   0.1
+   34992  0.0010432  0.00000034  33.54  2531.6    4793   0.1
+   35000  0.0010816  0.00000031  32.36  2442.3    4630   0.0
+   35280  0.0008968  0.00000030  39.34  2971.4    5584   0.1
+   35721  0.0019615  0.00000026  18.21  1377.1    2553   0.0
+   35840  0.0009223  0.00000029  38.86  2939.4    5421   0.1
+   36000  0.0009244  0.00000030  38.94  2947.2    5413   0.1
+   36015  0.0018748  0.00000020  19.21  1453.9    2667   0.1
+   36288  0.0009638  0.00000031  37.65  2851.6    5192   0.1
+   36450  0.0011163  0.00000030  32.65  2474.0    4479   0.0
+   36750  0.0012352  0.00000029  29.75  2256.0    4051   0.0
+   36864  0.0008856  0.00000029  41.63  3157.4    5646   0.1
+   37044  0.0009972  0.00000031  37.15  2818.9    5014   0.0
+   37500  0.0010960  0.00000030  34.22  2599.4    4562   0.0
+   37632  0.0009541  0.00000030  39.44  2997.7    5249   0.1
+   37800  0.0011325  0.00000030  33.38  2537.7    4415   0.1
+   38400  0.0009429  0.00000029  40.73  3101.0    5307   0.1
+   38416  0.0011698  0.00000032  32.84  2500.7    4281   0.0
+   38880  0.0010404  0.00000030  37.37  2849.0    4806   0.1
+   39200  0.0010168  0.00000030  38.55  2941.2    4925   0.0
+   39366  0.0016252  0.00000034  24.22  1848.8    3079   0.0
+   39375  0.0019142  0.00000021  20.57  1570.0    2612   0.0
+   39690  0.0014152  0.00000031  28.04  2142.1    3533   0.0
+   40000  0.0010433  0.00000031  38.34  2930.5    4796   0.0
+   40320  0.0010277  0.00000029  39.23  3001.2    4869   0.1
+   40500  0.0012463  0.00000029  32.50  2486.9    4015   0.1
+   40824  0.0014432  0.00000034  28.29  2166.4    3470   0.0
+   40960  0.0011654  0.00000029  35.15  2692.5    4297   0.0
+   41160  0.0013354  0.00000031  30.82  2362.3    3750   0.0
+   41472  0.0010252  0.00000029  40.45  3102.6    4877   0.2
+   42000  0.0010832  0.00000031  38.77  2977.5    4616   0.1
+   42336  0.0011563  0.00000032  36.61  2813.6    4324   0.1
+   42525  0.0020333  0.00000021  20.91  1607.9    2459   0.0
+   42875  0.0026028  0.00000020  16.47  1267.4    1921   0.0
+   43008  0.0010410  0.00000030  41.32  3179.7    4807   0.1
+   43200  0.0011353  0.00000029  38.05  2929.7    4404   0.2
+   43218  0.0014055  0.00000030  30.75  2367.6    3563   0.0
+   43740  0.0012444  0.00000031  35.15  2709.4    4018   0.0
+   43750  0.0015738  0.00000030  27.80  2142.9    3177   0.0
+   43904  0.0011157  0.00000031  39.35  3034.4    4485   0.0
+   44100  0.0011872  0.00000030  37.15  2865.6    4215   0.0
+   44800  0.0011518  0.00000030  38.90  3005.1    4348   0.1
+   45000  0.0013660  0.00000032  32.94  2546.1    3666   0.1
+   45360  0.0012385  0.00000031  36.62  2832.7    4037   0.1
+   45927  0.0027248  0.00000028  16.86  1305.2    1835   0.0
+   46080  0.0008662  0.00000029  53.20  4120.8    5777   0.2
+   46305  0.0025569  0.00000021  18.11  1403.4    1957   0.0
+   46656  0.0011044  0.00000032  42.25  3276.2    4531   0.1
+   46875  0.0026137  0.00000024  17.93  1391.4    1916   0.0
+   47040  0.0010208  0.00000030  46.08  3576.3    4902   0.1
+   47250  0.0017082  0.00000030  27.66  2147.5    2927   0.0
+   47628  0.0016238  0.00000032  29.33  2279.0    3084   0.0
+   48000  0.0012318  0.00000030  38.97  3029.8    4059   0.1
+   48020  0.0028891  0.00000021  16.62  1292.4    1732   0.0
+   48384  0.0012116  0.00000030  39.93  3107.3    4130   0.1
+   48600  0.0015216  0.00000031  31.94  2486.3    3286   0.1
+   49000  0.0015031  0.00000031  32.60  2539.5    3329   0.0
+   49152  0.0012307  0.00000030  39.94  3112.3    4066   0.1
+   49392  0.0013549  0.00000032  36.45  2841.9    3696   0.0
+   50000  0.0014265  0.00000034  35.05  2735.6    3505   0.0
+   50176  0.0012880  0.00000031  38.96  3041.5    3882   0.0
+   50400  0.0012794  0.00000030  39.39  3076.7    3911   0.2
+   50421  0.0029360  0.00000022  17.17  1341.4    1703   0.1
+   50625  0.0025445  0.00000021  19.90  1554.6    1965   0.0
+   51030  0.0016756  0.00000032  30.45  2381.4    2984   0.0
+   51200  0.0013245  0.00000029  38.66  3023.7    3778   0.1
+   51450  0.0018038  0.00000028  28.52  2232.1    2772   0.0
+   51840  0.0013362  0.00000029  38.80  3038.2    3742   0.2
+   52488  0.0019562  0.00000035  26.83  2103.6    2556   0.1
+   52500  0.0015499  0.00000029  33.87  2655.6    3231   0.0
+   52920  0.0015397  0.00000032  34.37  2696.7    3250   0.1
+   53760  0.0014634  0.00000029  36.74  2886.4    3422   0.1
+   54000  0.0014017  0.00000031  38.53  3028.3    3570   0.1
+   54432  0.0015610  0.00000033  34.87  2742.8    3208   0.1
+   54675  0.0027917  0.00000023  19.58  1541.2    1791   0.0
+   54880  0.0014944  0.00000031  36.72  2890.8    3351   0.0
+   55125  0.0028399  0.00000020  19.41  1528.6    1762   0.0
+   55296  0.0014184  0.00000029  38.98  3070.9    3525   0.1
+   55566  0.0020964  0.00000033  26.50  2088.8    2385   0.0
+   56000  0.0014802  0.00000031  37.83  2983.8    3378   0.1
+   56250  0.0019731  0.00000030  28.51  2249.2    2536   0.0
+   56448  0.0015432  0.00000031  36.58  2886.8    3245   0.1
+   56700  0.0017502  0.00000029  32.40  2557.8    2859   0.1
+   57344  0.0011284  0.00000031  50.82  4016.6    4438   0.0
+   57600  0.0012002  0.00000029  47.99  3794.7    4166   0.2
+   57624  0.0015939  0.00000032  36.15  2858.7    3137   0.0
+   58320  0.0021851  0.00000032  26.69  2112.8    2299   0.1
+   58800  0.0016303  0.00000031  36.07  2857.2    3067   0.1
+   59049  0.0034626  0.00000029  17.05  1351.4    1444   0.0
+   59535  0.0032787  0.00000023  18.16  1440.1    1525   0.0
+   60000  0.0013038  0.00000032  46.02  3652.3    3835   0.1
+   60025  0.0034037  0.00000020  17.64  1399.7    1469   0.0
+   60480  0.0015528  0.00000030  38.95  3093.4    3220   0.2
+   60750  0.0017775  0.00000030  34.18  2715.5    2813   0.0
+   61236  0.0018149  0.00000034  33.74  2682.8    2755   0.1
+   61250  0.0021701  0.00000029  28.22  2244.1    2304   0.0
+   61440  0.0015625  0.00000030  39.32  3127.4    3200   0.1
+   61740  0.0016678  0.00000031  37.02  2945.6    2998   0.0
+   62208  0.0017065  0.00000031  36.45  2902.6    2930   0.2
+   62500  0.0019952  0.00000033  31.33  2495.3    2506   0.0
+   62720  0.0016573  0.00000031  37.85  3015.6    3017   0.1
+   63000  0.0019128  0.00000032  32.94  2625.5    2614   0.1
+   63504  0.0018268  0.00000034  34.76  2773.1    2737   0.1
+   64000  0.0013816  0.00000030  46.32  3697.9    3619   0.1
+   64512  0.0015995  0.00000030  40.33  3222.1    3126   0.1
+   64800  0.0016335  0.00000030  39.67  3170.4    3061   0.2
+   64827  0.0039124  0.00000024  16.57  1324.3    1278   0.0
+   65536  0.0012953  0.00000031  50.59  4047.5    3860   0.0
+   65610  0.0025189  0.00000032  26.05  2084.0    1985   0.0
+   65625  0.0037651  0.00000023  17.43  1394.6    1328   0.0
+   65856  0.0016518  0.00000031  39.87  3190.9    3027   0.0
+   66150  0.0024667  0.00000031  26.82  2147.2    2027   0.0
+   67200  0.0019433  0.00000030  34.58  2772.7    2573   0.1
+   67228  0.0016250  0.00000033  41.37  3317.4    3077   0.1
+   67500  0.0021106  0.00000030  31.98  2565.3    2369   0.1
+   68040  0.0020825  0.00000030  32.67  2622.7    2401   0.1
+   68600  0.0021768  0.00000029  31.51  2531.6    2297   0.0
+   69120  0.0020342  0.00000029  33.98  2731.4    2458   0.2
+   69984  0.0027071  0.00000033  25.85  2080.4    1847   0.1
+   70000  0.0024925  0.00000030  28.08  2260.1    2006   0.0
+   70560  0.0023256  0.00000031  30.34  2443.4    2150   0.1
+   70875  0.0035336  0.00000021  20.06  1615.9    1415   0.0
+   71442  0.0024522  0.00000034  29.13  2348.9    2039   0.0
+   71680  0.0018954  0.00000029  37.82  3049.9    2638   0.1
+   72000  0.0020868  0.00000030  34.50  2783.6    2396   0.2
+   72030  0.0019216  0.00000033  37.48  3024.3    2602   0.2
+   72576  0.0022114  0.00000031  32.82  2649.7    2261   0.2
+   72900  0.0022272  0.00000030  32.73  2643.7    2245   0.1
+   73500  0.0023540  0.00000029  31.22  2523.7    2124   0.0
+   73728  0.0015738  0.00000029  46.85  3787.5    3177   0.2
+   74088  0.0023170  0.00000031  31.98  2586.4    2158   0.0
+   75000  0.0023202  0.00000031  32.33  2617.5    2155   0.0
+   75264  0.0021968  0.00000030  34.26  2775.0    2276   0.1
+   75600  0.0022292  0.00000029  33.91  2748.1    2243   0.1
+   76545  0.0042337  0.00000025  18.08  1466.6    1181   0.0
+   76800  0.0021106  0.00000029  36.39  2952.7    2369   0.2
+   76832  0.0026539  0.00000029  28.95  2349.2    1884   0.0
+   77175  0.0043328  0.00000021  17.81  1446.0    1154   0.0
+   77760  0.0024027  0.00000031  32.36  2629.0    2081   0.2
+   78125  0.0046253  0.00000027  16.89  1372.7    1081   0.0
+   78400  0.0023116  0.00000031  33.92  2757.1    2163   0.1
+   78732  0.0025240  0.00000035  31.19  2536.8    1981   0.0
+   78750  0.0030694  0.00000030  25.66  2086.5    1629   0.0
+   79380  0.0021450  0.00000031  37.01  3011.7    2331   0.1
+   80000  0.0019936  0.00000032  40.13  3268.0    2508   0.1
+   80640  0.0019223  0.00000029  41.95  3418.7    2601   0.2
+   81000  0.0021730  0.00000030  37.28  3039.1    2301   0.1
+   81648  0.0026441  0.00000032  30.88  2519.3    1891   0.1
+   81920  0.0022894  0.00000029  35.78  2920.2    2184   0.1
+   82320  0.0048733  0.00000022  16.89  1379.1    1026   0.0
+   82944  0.0023923  0.00000030  34.67  2832.6    2090   0.2
+   83349  0.0046685  0.00000025  17.85  1459.2    1071   0.0
+   84000  0.0028506  0.00000032  29.47  2410.1    1754   0.1
+   84035  0.0051921  0.00000021  16.19  1323.8     963   0.1
+   84375  0.0043860  0.00000022  19.24  1574.1    1140   0.0
+   84672  0.0026302  0.00000032  32.19  2634.9    1901   0.1
+   85050  0.0032031  0.00000031  26.55  2174.1    1561   0.1
+   85750  0.0034435  0.00000029  24.90  2040.4    1452   0.0
+   86016  0.0022831  0.00000030  37.68  3087.9    2190   0.1
+   86400  0.0024402  0.00000029  35.41  2903.1    2049   0.3
+   86436  0.0029189  0.00000033  29.61  2428.2    1713   0.0
+   87480  0.0029019  0.00000031  30.15  2474.5    1723   0.1
+   87500  0.0032154  0.00000032  27.21  2233.7    1555   0.0
+   87808  0.0025602  0.00000031  34.30  2816.2    1953   0.0
+   88200  0.0027563  0.00000030  32.00  2628.5    1814   0.1
+   89600  0.0025934  0.00000030  34.55  2841.9    1928   0.1
+   90000  0.0029053  0.00000030  30.98  2549.1    1721   0.1
+   90720  0.0027624  0.00000032  32.84  2704.3    1810   0.2
+   91125  0.0045086  0.00000021  20.21  1665.0    1109   0.0
+   91854  0.0037037  0.00000035  24.80  2044.4    1350   0.0
+   91875  0.0050352  0.00000022  18.25  1504.2     993   0.0
+   92160  0.0019486  0.00000030  47.30  3900.0    2566   0.1
+   92610  0.0034083  0.00000032  27.17  2241.5    1467   0.0
+   93312  0.0025368  0.00000032  36.78  3036.4    1971   0.1
+   93750  0.0034602  0.00000033  27.09  2237.5    1445   0.0
+   94080  0.0027594  0.00000030  34.09  2816.5    1812   0.1
+   94500  0.0030048  0.00000030  31.45  2599.0    1664   0.1
+   95256  0.0031706  0.00000033  30.04  2484.5    1577   0.1
+   96000  0.0027042  0.00000030  35.50  2937.8    1849   0.1
+   96040  0.0025176  0.00000032  38.15  3156.9    1986   0.2
+   96768  0.0029586  0.00000030  32.71  2708.6    1690   0.1
+   97200  0.0025988  0.00000030  37.40  3098.6    1924   0.2
+   98000  0.0035361  0.00000029  27.71  2297.6    1414   0.0
+   98304  0.0021240  0.00000030  46.28  3837.9    2354   0.1
+   98415  0.0058207  0.00000026  16.91  1402.2     859   0.0
+   98784  0.0031387  0.00000032  31.47  2611.0    1593   0.1
+   99225  0.0051975  0.00000022  19.09  1584.4     962   0.0
+  100000  0.0031095  0.00000033  32.16  2670.8    1608   0.1
+  100352  0.0026954  0.00000031  37.23  3092.9    1855   0.0
+  100800  0.0029377  0.00000030  34.31  2851.5    1702   0.2
+  100842  0.0028969  0.00000034  34.81  2893.1    1726   0.1
+  101250  0.0036523  0.00000032  27.72  2304.8    1369   0.1
+  102060  0.0033852  0.00000032  30.15  2508.2    1477   0.1
+  102400  0.0022202  0.00000029  46.12  3838.2    2252   0.1
+  102900  0.0033003  0.00000030  31.18  2595.8    1515   0.0
+  103680  0.0031726  0.00000030  32.68  2722.5    1576   0.3
+  104976  0.0036684  0.00000033  28.62  2386.6    1363   0.1
+  105000  0.0032744  0.00000030  32.07  2674.4    1527   0.1
+  105840  0.0033445  0.00000031  31.65  2641.1    1495   0.1
+  107163  0.0064433  0.00000027  16.63  1389.5     776   0.0
+  107520  0.0028539  0.00000030  37.68  3148.5    1752   0.1
+  108000  0.0029815  0.00000031  36.22  3028.4    1677   0.3
+  108045  0.0068681  0.00000023  15.73  1315.2     728   0.0
+  108864  0.0035511  0.00000033  30.66  2564.7    1408   0.2
+  109350  0.0040064  0.00000032  27.29  2284.3    1248   0.1
+  109375  0.0065531  0.00000026  16.69  1396.9     763   0.0
+  109760  0.0033670  0.00000031  32.60  2729.2    1485   0.0
+  110250  0.0041528  0.00000031  26.55  2223.5    1204   0.1
+  110592  0.0025214  0.00000029  43.86  3674.4    1983   0.2
+  111132  0.0037764  0.00000033  29.43  2466.3    1324   0.1
+  112000  0.0033422  0.00000031  33.51  2810.4    1496   0.1
+  112500  0.0038880  0.00000033  28.93  2427.6    1286   0.1
+  112896  0.0032701  0.00000031  34.52  2897.3    1529   0.1
+  113400  0.0036179  0.00000030  31.34  2631.5    1382   0.2
+  114688  0.0032489  0.00000031  35.30  2966.6    1539   0.1
+  115200  0.0033852  0.00000030  34.03  2860.9    1477   0.3
+  115248  0.0073855  0.00000024  15.60  1311.9     677   0.0
+  116640  0.0037850  0.00000032  30.82  2593.5    1321   0.2
+  117600  0.0041220  0.00000032  28.53  2402.7    1213   0.1
+  117649  0.0077640  0.00000022  15.15  1276.2     644   0.0
+  118098  0.0047755  0.00000036  24.73  2083.4    1047   0.0
+  118125  0.0068120  0.00000021  17.34  1461.0     734   0.1
+  119070  0.0044643  0.00000033  26.67  2248.6    1120   0.1
+  120000  0.0035765  0.00000032  33.55  2830.6    1398   0.2
+  120050  0.0051600  0.00000028  23.27  1962.8     969   0.0
+  120960  0.0040420  0.00000030  29.93  2526.3    1237   0.2
+  121500  0.0055371  0.00000030  21.94  1853.1     903   0.2
+  122472  0.0036982  0.00000034  33.12  2798.7    1352   0.1
+  122500  0.0046642  0.00000031  26.26  2219.6    1072   0.1
+  122880  0.0034916  0.00000029  35.19  2975.0    1432   0.1
+  123480  0.0040883  0.00000032  30.20  2554.3    1223   0.0
+  124416  0.0037509  0.00000031  33.17  2806.9    1333   0.2
+  125000  0.0046598  0.00000033  26.82  2270.9    1073   0.1
+  125440  0.0038197  0.00000030  32.84  2781.0    1309   0.1
+  126000  0.0040917  0.00000030  30.79  2608.8    1222   0.2
+  127008  0.0047214  0.00000033  26.90  2280.4    1059   0.1
+  127575  0.0069252  0.00000023  18.42  1562.3     722   0.1
+  128000  0.0041017  0.00000031  31.21  2647.2    1219   0.1
+  128625  0.0079618  0.00000021  16.16  1371.0     628   0.0
+  129024  0.0038521  0.00000030  33.49  2843.2    1298   0.1
+  129600  0.0038790  0.00000031  33.41  2837.2    1289   0.3
+  129654  0.0048733  0.00000033  26.61  2259.3    1026   0.0
+  131072  0.0036232  0.00000030  36.18  3074.9    1380   0.1
+  131220  0.0046083  0.00000033  28.47  2420.6    1085   0.1
+  131250  0.0055249  0.00000032  23.76  2019.5     905   0.1
+  131712  0.0034247  0.00000031  38.46  3270.4    1460   0.1
+  132300  0.0043215  0.00000031  30.61  2604.3    1157   0.1
+  134400  0.0034176  0.00000030  39.33  3349.8    1463   0.2
+  134456  0.0038551  0.00000034  34.88  2971.0    1297   0.1
+  135000  0.0045413  0.00000031  29.73  2533.1    1101   0.2
+  136080  0.0044366  0.00000031  30.67  2615.5    1127   0.2
+  137200  0.0045126  0.00000030  30.40  2594.3    1108   0.1
+  137781  0.0084459  0.00000029  16.31  1392.5     592   0.1
+  138240  0.0035186  0.00000029  39.29  3354.6    1421   0.3
+  138915  0.0086059  0.00000023  16.14  1378.8     581   0.0
+  139968  0.0044563  0.00000034  31.41  2684.6    1122   0.2
+  140000  0.0045496  0.00000032  30.77  2630.2    1099   0.1
+  140625  0.0077640  0.00000024  18.11  1548.8     644   0.1
+  141120  0.0036525  0.00000031  38.64  3304.7    1370   0.1
+  141750  0.0051440  0.00000032  27.56  2357.8     972   0.1
+  142884  0.0050865  0.00000035  28.09  2405.2     983   0.1
+  143360  0.0035088  0.00000030  40.86  3499.3    1425   0.1
+  144000  0.0037258  0.00000031  38.65  3311.4    1342   0.2
+  144060  0.0040617  0.00000033  35.47  3038.9    1231   0.4
+  145152  0.0038850  0.00000032  37.36  3203.3    1287   0.2
+  145800  0.0047574  0.00000030  30.65  2628.6    1051   0.2
+  147000  0.0054466  0.00000030  26.99  2316.4     918   0.1
+  147456  0.0034200  0.00000030  43.12  3701.5    1462   0.2
+  148176  0.0046729  0.00000032  31.71  2723.4    1070   0.0
+  150000  0.0055804  0.00000031  26.88  2311.0     896   0.1
+  150528  0.0038314  0.00000031  39.29  3378.7    1305   0.1
+  151200  0.0046339  0.00000032  32.63  2807.1    1079   0.2
+  151263  0.0100558  0.00000024  15.04  1294.1     498   0.1
+  151875  0.0080128  0.00000021  18.95  1631.2     624   0.1
+  153090  0.0069541  0.00000032  22.01  1895.9     719   0.1
+  153125  0.0095057  0.00000023  16.11  1387.3     526   0.1
+  153600  0.0036258  0.00000030  42.36  3649.3    1379   0.2
+  153664  0.0044484  0.00000032  34.54  2975.8    1124   0.0
+  154350  0.0060241  0.00000031  25.62  2208.1     830   0.0
+  155520  0.0042845  0.00000031  36.30  3130.1    1167   0.2
+  156250  0.0060606  0.00000035  25.78  2224.1     825   0.0
+  156800  0.0041391  0.00000031  37.88  3269.0    1208   0.1
+  157464  0.0065445  0.00000034  24.06  2077.0     764   0.1
+  157500  0.0051600  0.00000030  30.52  2634.9     969   0.1
+  158760  0.0065274  0.00000031  24.32  2101.0     766   0.1
+  160000  0.0042808  0.00000032  37.38  3230.7    1168   0.1
+  161280  0.0039185  0.00000030  41.16  3560.1    1276   0.2
+  162000  0.0059453  0.00000029  27.25  2357.8     841   0.2
+  163296  0.0059382  0.00000035  27.50  2381.0     842   0.1
+  163840  0.0039809  0.00000030  41.16  3564.6    1256   0.1
+  164025  0.0098039  0.00000025  16.73  1449.2     510   0.1
+  164640  0.0051230  0.00000032  32.14  2784.6     976   0.0
+  165375  0.0094877  0.00000022  17.43  1510.8     527   0.1
+  165888  0.0041597  0.00000030  39.88  3457.5    1202   0.2
+  166698  0.0075075  0.00000033  22.20  1925.9     666   0.0
+  168000  0.0044444  0.00000032  37.80  3280.7    1125   0.2
+  168070  0.0058343  0.00000033  28.81  2500.3     857   0.1
+  168750  0.0067024  0.00000031  25.18  2186.0     746   0.1
+  169344  0.0046041  0.00000032  36.78  3194.4    1086   0.1
+  170100  0.0068399  0.00000032  24.87  2160.6     731   0.1
+  171500  0.0065445  0.00000031  26.21  2278.3     764   0.1
+  172032  0.0041771  0.00000031  41.18  3581.5    1197   0.1
+  172800  0.0045496  0.00000030  37.98  3304.1    1099   0.2
+  172872  0.0064020  0.00000030  27.00  2349.1     781   0.0
+  174960  0.0057737  0.00000031  30.30  2638.9     866   0.1
+  175000  0.0057604  0.00000032  30.38  2645.6     868   0.1
+  175616  0.0044053  0.00000032  39.86  3472.6    1135   0.1
+  176400  0.0066667  0.00000030  26.46  2305.8     750   0.1
+  177147  0.0136612  0.00000031  12.97  1130.4     366   0.1
+  178605  0.0109649  0.00000024  16.29  1420.9     456   0.1
+  179200  0.0046904  0.00000030  38.21  3333.7    1066   0.2
+  180000  0.0055494  0.00000033  32.44  2831.3     901   0.2
+  180075  0.0120380  0.00000022  14.96  1305.8     416   0.1
+  181440  0.0050659  0.00000032  35.82  3128.4     987   0.2
+  182250  0.0081699  0.00000031  22.31  1949.2     612   0.1
+  183708  0.0076103  0.00000035  24.14  2110.6     657   0.1
+  183750  0.0076805  0.00000032  23.92  2091.9     651   0.1
+  184320  0.0043554  0.00000030  42.32  3701.3    1148   0.3
+  185220  0.0113895  0.00000022  16.26  1422.9     439   0.1
+  186624  0.0053135  0.00000033  35.12  3074.9     941   0.2
+  187500  0.0072359  0.00000033  25.91  2269.5     691   0.1
+  188160  0.0050454  0.00000031  37.29  3267.2     991   0.1
+  189000  0.0071023  0.00000030  26.61  2332.2     704   0.1
+  190512  0.0074627  0.00000033  25.53  2238.8     670   0.1
+  192000  0.0047985  0.00000031  40.01  3511.3    1042   0.2
+  192080  0.0129534  0.00000023  14.83  1301.3     386   0.1
+  193536  0.0050352  0.00000031  38.44  3375.1     993   0.2
+  194400  0.0062657  0.00000032  31.03  2725.4     798   0.2
+  194481  0.0127877  0.00000026  15.21  1336.0     391   0.1
+  196000  0.0068399  0.00000031  28.66  2518.9     731   0.1
+  196608  0.0049407  0.00000031  39.79  3498.8    1012   0.1
+  196830  0.0091743  0.00000033  21.45  1886.6     545   0.1
+  196875  0.0119048  0.00000023  16.54  1454.2     420   0.1
+  197568  0.0055804  0.00000033  35.40  3114.2     896   0.1
+  198450  0.0089928  0.00000032  22.07  1941.8     556   0.1
+  200000  0.0058411  0.00000035  34.24  3014.8     856   0.1
+  200704  0.0052301  0.00000032  38.37  3379.8     956   0.1
+  201600  0.0054645  0.00000031  36.89  3250.5     915   0.3
+  201684  0.0061728  0.00000035  32.67  2878.8     810   0.2
+  202500  0.0066756  0.00000030  30.33  2673.6     749   0.1
+  204120  0.0092593  0.00000032  22.04  1944.3     540   0.1
+  204800  0.0053248  0.00000030  38.46  3393.0     939   0.2
+  205800  0.0078864  0.00000030  26.10  2303.0     634   0.1
+  207360  0.0052521  0.00000030  39.48  3486.6     952   0.3
+  209952  0.0082031  0.00000035  25.59  2262.5     610   0.1
+  210000  0.0078493  0.00000031  26.75  2365.1     637   0.1
+  211680  0.0069156  0.00000033  30.61  2707.6     723   0.1
+  212625  0.0130752  0.00000022  16.26  1439.0     383   0.1
+  214326  0.0100000  0.00000034  21.43  1897.8     500   0.1
+  214375  0.0147059  0.00000022  14.58  1290.8     340   0.1
+  215040  0.0056117  0.00000030  38.32  3394.1     891   0.2
+  216000  0.0055804  0.00000031  38.71  3429.6     896   0.2
+  216090  0.0077760  0.00000035  27.79  2462.3     643   0.4
+  217728  0.0063857  0.00000034  34.10  3023.0     783   0.2
+  218700  0.0094340  0.00000033  23.18  2056.1     530   0.1
+  218750  0.0095602  0.00000033  22.88  2029.4     523   0.1
+  219520  0.0060753  0.00000032  36.13  3205.7     823   0.1
+  220500  0.0083612  0.00000030  26.37  2340.6     598   0.1
+  221184  0.0055804  0.00000030  39.64  3518.7     896   0.2
+  222264  0.0097466  0.00000033  22.80  2025.2     513   0.1
+  224000  0.0061652  0.00000032  36.33  3228.7     811   0.2
+  225000  0.0086059  0.00000032  26.15  2324.2     581   0.1
+  225792  0.0060386  0.00000032  37.39  3324.9     828   0.2
+  226800  0.0073314  0.00000030  30.94  2751.9     682   0.2
+  229376  0.0055556  0.00000032  41.29  3676.1     900   0.1
+  229635  0.0140449  0.00000026  16.35  1455.9     356   0.1
+  230400  0.0059737  0.00000030  38.57  3435.3     837   0.3
+  230496  0.0076687  0.00000033  30.06  2677.2     652   0.1
+  231525  0.0155763  0.00000023  14.86  1324.4     321   0.1
+  233280  0.0070621  0.00000033  33.03  2945.1     708   0.2
+  234375  0.0140275  0.00000027  16.71  1490.2     357   0.1
+  235200  0.0062972  0.00000032  37.35  3332.3     794   0.1
+  235298  0.0088810  0.00000034  26.49  2363.9     563   0.1
+  236196  0.0102459  0.00000036  23.05  2057.4     488   0.1
+  236250  0.0098232  0.00000032  24.05  2146.5     509   0.1
+  238140  0.0109890  0.00000032  21.67  1935.4     455   0.1
+  240000  0.0066050  0.00000032  36.34  3247.1     757   0.2
+  240100  0.0097656  0.00000031  24.59  2197.2     512   0.1
+  241920  0.0064851  0.00000031  37.30  3335.8     771   0.2
+  243000  0.0083056  0.00000030  29.26  2617.1     602   0.2
+  244944  0.0098232  0.00000034  24.94  2232.0     509   0.1
+  245000  0.0096154  0.00000031  25.48  2280.8     520   0.1
+  245760  0.0063211  0.00000031  38.88  3481.0     791   0.2
+  246960  0.0095238  0.00000031  25.93  2322.6     525   0.1
+  248832  0.0068681  0.00000032  36.23  3247.1     728   0.2
+  250000  0.0082645  0.00000034  30.25  2712.1     605   0.1
+  250047  0.0163934  0.00000027  15.25  1367.6     305   0.6
+  250880  0.0064516  0.00000032  38.89  3487.5     775   0.1
+  252000  0.0079872  0.00000033  31.55  2830.6     626   0.2
+  252105  0.0182482  0.00000022  13.82  1239.5     274   0.2
+  253125  0.0140845  0.00000022  17.97  1612.9     355   0.1
+  254016  0.0077160  0.00000034  32.92  2955.4     648   0.2
+  255150  0.0108394  0.00000033  23.54  2113.9     462   0.1
+  256000  0.0066756  0.00000031  38.35  3444.8     749   0.1
+  257250  0.0097809  0.00000032  26.30  2363.5     512   0.1
+  258048  0.0067024  0.00000031  38.50  3460.7     746   0.2
+  259200  0.0071531  0.00000031  36.24  3258.3     699   0.3
+  259308  0.0173281  0.00000024  14.96  1345.6     289   0.1
+  262144  0.0067476  0.00000032  38.85  3496.5     741   0.1
+  262440  0.0119904  0.00000033  21.89  1970.1     417   0.1
+  262500  0.0101626  0.00000032  25.83  2325.0     492   0.1
+  263424  0.0080000  0.00000033  32.93  2964.7     625   0.1
+  264600  0.0106610  0.00000031  24.82  2235.4     469   0.1
+  268800  0.0095602  0.00000031  28.12  2535.6     523   0.2
+  268912  0.0090909  0.00000035  29.58  2667.7     550   0.2
+  270000  0.0103734  0.00000031  26.03  2348.1     482   0.2
+  272160  0.0102041  0.00000031  26.67  2407.7     490   0.2
+  273375  0.0158228  0.00000023  17.28  1560.2     316   0.1
+  274400  0.0105263  0.00000031  26.07  2354.7     475   0.1
+  275562  0.0144509  0.00000036  19.07  1723.1     346   0.1
+  275625  0.0174216  0.00000022  15.82  1429.6     287   0.1
+  276480  0.0096712  0.00000030  28.59  2583.9     517   0.2
+  277830  0.0138337  0.00000031  20.08  1815.9     362   0.1
+  279936  0.0129067  0.00000035  21.69  1962.3     388   0.2
+  280000  0.0107066  0.00000031  26.15  2366.1     467   0.1
+  281250  0.0119332  0.00000034  23.57  2133.1     419   0.1
+  282240  0.0099404  0.00000032  28.39  2570.5     503   0.1
+  283500  0.0113636  0.00000031  24.95  2259.4     440   0.2
+  285768  0.0129067  0.00000034  22.14  2006.5     388   0.1
+  286720  0.0096154  0.00000031  29.82  2703.0     520   0.1
+  288000  0.0111607  0.00000031  25.80  2339.9     448   0.2
+  288120  0.0100806  0.00000034  28.58  2591.8     496   0.7
+  290304  0.0109580  0.00000033  26.49  2403.8     457   0.2
+  291600  0.0109890  0.00000031  26.54  2408.6     455   0.2
+  294000  0.0114073  0.00000030  25.77  2340.9     439   0.1
+  294912  0.0102459  0.00000032  28.78  2615.0     488   0.2
+  295245  0.0193352  0.00000028  15.27  1387.4     259   0.1
+  296352  0.0096899  0.00000032  30.58  2779.6     516   0.1
+  297675  0.0204401  0.00000024  14.56  1324.1     245   0.1
+  300000  0.0116370  0.00000032  25.78  2345.3     430   0.2
+  300125  0.0212195  0.00000022  14.14  1286.7     236   0.1
+  301056  0.0107527  0.00000032  28.00  2547.8     465   0.1
+  302400  0.0100604  0.00000030  30.06  2736.2     497   0.2
+  302526  0.0130208  0.00000036  23.23  2115.1     384   0.2
+  303750  0.0134258  0.00000032  22.62  2060.2     373   0.1
+  306180  0.0124069  0.00000032  24.68  2248.7     403   0.1
+  306250  0.0125195  0.00000032  24.46  2229.0     400   0.1
+  307200  0.0106383  0.00000031  28.88  2631.9     470   0.2
+  307328  0.0111359  0.00000031  27.60  2515.5     449   0.1
+  308700  0.0125824  0.00000032  24.53  2237.0     398   0.1
+  311040  0.0115207  0.00000033  27.00  2463.2     434   0.2
+  312500  0.0129199  0.00000036  24.19  2207.5     387   0.1
+  313600  0.0122440  0.00000032  25.61  2338.2     409   0.1
+  314928  0.0123345  0.00000036  25.53  2331.7     406   0.1
+  315000  0.0121255  0.00000031  25.98  2372.5     413   0.2
+  317520  0.0107296  0.00000032  29.59  2704.3     466   0.1
+  320000  0.0097809  0.00000032  32.72  2991.6     512   0.1
+  321489  0.0224916  0.00000030  14.29  1307.5     223   0.1
+  322560  0.0096154  0.00000031  33.55  3069.3     520   0.2
+  324000  0.0108225  0.00000030  29.94  2740.1     462   0.3
+  324135  0.0245481  0.00000023  13.20  1208.6     204   0.4
+  326592  0.0113122  0.00000033  28.87  2644.1     442   0.2
+  327680  0.0113814  0.00000031  28.79  2637.5     440   0.1
+  328050  0.0167224  0.00000034  19.62  1797.3     299   0.1
+  328125  0.0237337  0.00000025  13.83  1266.7     211   0.1
+  329280  0.0215517  0.00000024  15.28  1400.2     232   0.1
+  330750  0.0147493  0.00000032  22.42  2055.8     339   0.1
+  331776  0.0117925  0.00000032  28.13  2579.9     424   0.2
+  333396  0.0153846  0.00000034  21.67  1988.0     325   0.1
+  336000  0.0138122  0.00000032  24.33  2232.9     362   0.2
+  336140  0.0124883  0.00000035  26.92  2470.7     401   0.3
+  337500  0.0131785  0.00000032  25.61  2351.6     380   0.2
+  338688  0.0109649  0.00000034  30.89  2837.0     456   0.2
+  340200  0.0129870  0.00000031  26.20  2406.8     385   0.2
+  343000  0.0139106  0.00000032  24.66  2267.0     360   0.1
+  344064  0.0114943  0.00000032  29.93  2752.7     435   0.1
+  345600  0.0107234  0.00000031  32.23  2964.8     467   0.3
+  345744  0.0125824  0.00000033  27.48  2527.9     398   0.1
+  349920  0.0120962  0.00000032  28.93  2663.8     414   0.2
+  350000  0.0137363  0.00000033  25.48  2346.3     364   0.1
+  351232  0.0128405  0.00000033  27.35  2519.5     390   0.1
+  352800  0.0120962  0.00000031  29.17  2687.5     414   0.2
+  352947  0.0293311  0.00000024  12.03  1108.8     171   0.2
+  354294  0.0180787  0.00000037  19.60  1806.3     277   0.1
+  354375  0.0214009  0.00000022  16.56  1526.3     234   0.1
+  357210  0.0180418  0.00000033  19.80  1826.1     278   0.1
+  358400  0.0108225  0.00000031  33.12  3055.2     462   0.2
+  360000  0.0122440  0.00000031  29.40  2713.5     409   0.3
+  360150  0.0158978  0.00000032  22.65  2090.8     315   0.1
+  362880  0.0152905  0.00000033  23.73  2191.6     327   0.2
+  364500  0.0154562  0.00000032  23.58  2178.5     324   0.2
+  367416  0.0156007  0.00000036  23.55  2177.0     321   0.1
+  367500  0.0146857  0.00000032  25.02  2313.2     341   0.1
+  368640  0.0131234  0.00000031  28.09  2597.2     381   0.2
+  370440  0.0143903  0.00000032  25.74  2381.0     348   0.1
+  373248  0.0145154  0.00000034  25.71  2379.8     345   0.2
+  375000  0.0151752  0.00000034  24.71  2287.8     330   0.1
+  376320  0.0137200  0.00000032  27.43  2540.1     365   0.1
+  378000  0.0130548  0.00000031  28.95  2682.4     383   0.2
+  381024  0.0135713  0.00000033  28.08  2602.6     369   0.2
+  382725  0.0257212  0.00000024  14.88  1379.8     195   0.1
+  384000  0.0141464  0.00000031  27.14  2517.8     354   0.2
+  384160  0.0149935  0.00000034  25.62  2376.6     334   0.6
+  385875  0.0262189  0.00000022  14.72  1365.6     191   0.1
+  387072  0.0139883  0.00000032  27.67  2568.2     358   0.2
+  388800  0.0130073  0.00000030  29.89  2775.2     385   0.3
+  388962  0.0199033  0.00000032  19.54  1814.5     252   0.1
+  390625  0.0273651  0.00000030  14.27  1325.8     183   0.1
+  392000  0.0155763  0.00000031  25.17  2338.0     321   0.2
+  393216  0.0109890  0.00000032  35.78  3325.1     455   0.1
+  393660  0.0191870  0.00000034  20.52  1906.7     261   0.1
+  393750  0.0171821  0.00000033  22.92  2129.7     291   0.1
+  395136  0.0148600  0.00000034  26.59  2471.9     337   0.1
+  396900  0.0170068  0.00000033  23.34  2170.2     294   0.2
+  400000  0.0149935  0.00000033  26.68  2482.4     334   0.2
+  401408  0.0116279  0.00000033  34.52  3213.0     430   0.1
+  403200  0.0146427  0.00000031  27.54  2563.7     342   0.3
+  403368  0.0161023  0.00000036  25.05  2332.4     311   0.4
+  405000  0.0160256  0.00000031  25.27  2353.8     312   0.2
+  408240  0.0147723  0.00000033  27.64  2575.5     339   0.2
+  409600  0.0115473  0.00000031  35.47  3306.6     433   0.2
+  411600  0.0192909  0.00000031  21.34  1989.7     260   0.1
+  413343  0.0309124  0.00000032  13.37  1247.4     162   0.1
+  414720  0.0151057  0.00000031  27.45  2561.7     331   0.3
+  416745  0.0298317  0.00000025  13.97  1304.0     168   0.1
+  419904  0.0154207  0.00000034  27.23  2543.2     325   0.2
+  420000  0.0191287  0.00000031  21.96  2050.7     262   0.2
+  420175  0.0373717  0.00000022  11.24  1050.1     134   0.2
+  421875  0.0264186  0.00000024  15.97  1492.0     190   0.1
+  423360  0.0146313  0.00000031  28.94  2704.2     342   0.2
+  425250  0.0219470  0.00000032  19.38  1811.5     228   0.1
+  428652  0.0207631  0.00000035  20.64  1931.3     241   0.1
+  428750  0.0233827  0.00000028  18.34  1715.3     214   0.1
+  430080  0.0149275  0.00000032  28.81  2695.9     336   0.2
+  432000  0.0168613  0.00000032  25.62  2398.2     297   0.3
+  432180  0.0289017  0.00000023  14.95  1399.7     173   0.1
+  435456  0.0174825  0.00000035  24.91  2332.9     286   0.3
+  437400  0.0175576  0.00000032  24.91  2334.1     285   0.2
+  437500  0.0216450  0.00000032  20.21  1893.8     231   0.1
+  439040  0.0163399  0.00000032  26.87  2518.2     306   0.1
+  441000  0.0178571  0.00000031  24.70  2315.3     280   0.2
+  442368  0.0156862  0.00000031  28.20  2644.5     319   0.2
+  444528  0.0162444  0.00000034  27.36  2567.1     309   0.2
+  448000  0.0142267  0.00000032  31.49  2955.8     352   0.2
+  450000  0.0161416  0.00000033  27.88  2617.7     310   0.2
+  451584  0.0166502  0.00000033  27.12  2547.4     301   0.2
+  453600  0.0157356  0.00000031  28.83  2708.4     318   0.3
+  453789  0.0401562  0.00000026  11.30  1061.8     125   0.3
+  455625  0.0288703  0.00000024  15.78  1483.3     174   0.2
+  458752  0.0160256  0.00000033  28.63  2691.9     312   0.1
+  459270  0.0217901  0.00000034  21.08  1982.2     230   0.1
+  459375  0.0306307  0.00000024  15.00  1410.4     164   0.1
+  460800  0.0165532  0.00000031  27.84  2618.6     303   0.3
+  460992  0.0318471  0.00000025  14.48  1361.7     157   0.2
+  463050  0.0229537  0.00000031  20.17  1898.4     218   0.1
+  466560  0.0207631  0.00000034  22.47  2115.8     241   0.3
+  468750  0.0252920  0.00000034  18.53  1745.7     198   0.1
+  470400  0.0197158  0.00000033  23.86  2247.9     254   0.2
+  470596  0.0204879  0.00000036  22.97  2164.2     245   0.2
+  472392  0.0218852  0.00000037  21.58  2034.3     229   0.2
+  472500  0.0209859  0.00000030  22.52  2122.0     239   0.2
+  476280  0.0193950  0.00000033  24.56  2315.9     258   0.2
+  480000  0.0183579  0.00000033  26.15  2467.3     273   0.2
+  480200  0.0221585  0.00000030  21.67  2045.0     226   0.1
+  483840  0.0182528  0.00000032  26.51  2502.9     275   0.3
+  486000  0.0169447  0.00000031  28.68  2709.1     296   0.3
+  489888  0.0183150  0.00000035  26.75  2528.0     273   0.2
+  490000  0.0238281  0.00000032  20.56  1943.5     210   0.2
+  491520  0.0177721  0.00000031  27.66  2614.5     282   0.2
+  492075  0.0307467  0.00000026  16.00  1513.1     163   0.1
+  493920  0.0179491  0.00000032  27.52  2602.3     279   0.2
+  496125  0.0345905  0.00000023  14.34  1356.9     145   0.2
+  497664  0.0183866  0.00000033  27.07  2561.2     273   0.3
+  500000  0.0241546  0.00000035  20.70  1959.4     207   0.2
+  500094  0.0266373  0.00000035  18.77  1777.2     188   0.1
+  501760  0.0185874  0.00000032  26.99  2555.9     269   0.2
+  504000  0.0176955  0.00000031  28.48  2697.7     283   0.3
+  504210  0.0262189  0.00000036  19.23  1821.5     191   0.4
+  506250  0.0245672  0.00000031  20.61  1952.4     204   0.2
+  508032  0.0225929  0.00000035  22.49  2131.1     222   0.2
+  510300  0.0240169  0.00000032  21.25  2014.4     209   0.2
+  512000  0.0161542  0.00000031  31.69  3005.6     310   0.2
+  514500  0.0384615  0.00000023  13.38  1269.0     130   0.2
+  516096  0.0184646  0.00000032  27.95  2652.1     271   0.2
+  518400  0.0194253  0.00000032  26.69  2533.1     258   0.4
+  518616  0.0212526  0.00000034  24.40  2316.3     236   0.1
+  524288  0.0213597  0.00000032  24.55  2331.8     235   0.1
+  524880  0.0200781  0.00000034  26.14  2483.7     250   0.2
+  525000  0.0277754  0.00000034  18.90  1795.8     181   0.2
+  526848  0.0172683  0.00000033  30.51  2899.5     290   0.1
+  529200  0.0187970  0.00000031  28.15  2676.5     266   0.2
+  531441  0.0398996  0.00000033  13.32  1266.7     126   0.2
+  535815  0.0384916  0.00000026  13.92  1324.6     130   0.2
+  537600  0.0173551  0.00000031  30.98  2948.4     289   0.2
+  537824  0.0252723  0.00000037  21.28  2025.6     198   0.4
+  540000  0.0190989  0.00000031  28.27  2692.0     262   0.3
+  540225  0.0390019  0.00000023  13.85  1318.9     129   0.2
+  544320  0.0189416  0.00000031  28.74  2737.8     265   0.3
+  546750  0.0274291  0.00000031  19.93  1899.7     183   0.2
+  546875  0.0399616  0.00000029  13.69  1304.2     126   0.2
+  548800  0.0265790  0.00000031  20.65  1968.4     189   0.2
+  551124  0.0279548  0.00000037  19.71  1880.0     179   0.2
+  551250  0.0279984  0.00000030  19.69  1877.5     179   0.2
+  552960  0.0172683  0.00000031  32.02  3054.4     290   0.3
+  555660  0.0266581  0.00000033  20.84  1988.9     188   0.2
+  559872  0.0213098  0.00000036  26.27  2508.4     235   0.3
+  560000  0.0216788  0.00000033  25.83  2466.3     231   0.2
+  562500  0.0293768  0.00000033  19.15  1828.8     171   0.2
+  564480  0.0186309  0.00000033  30.30  2894.5     269   0.2
+  567000  0.0213675  0.00000032  26.54  2535.9     234   0.2
+  571536  0.0222569  0.00000035  25.68  2455.5     225   0.2
+  573440  0.0178850  0.00000032  32.06  3066.7     280   0.2
+  576000  0.0191870  0.00000032  30.02  2872.3     261   0.3
+  576240  0.0255899  0.00000035  22.52  2154.6     196   1.1
+  580608  0.0190114  0.00000034  30.54  2923.8     263   0.3
+  583200  0.0202429  0.00000031  28.81  2759.1     247   0.4
+  583443  0.0449916  0.00000028  12.97  1241.9     112   0.2
+  588000  0.0284535  0.00000031  20.67  1980.3     176   0.2
+  588245  0.0574713  0.00000023  10.24   980.9      87   0.3
+  589824  0.0178214  0.00000032  33.10  3172.3     281   0.2
+  590490  0.0329975  0.00000035  17.89  1715.4     152   0.2
+  590625  0.0409836  0.00000024  14.41  1381.5     122   0.2
+  592704  0.0274505  0.00000034  21.59  2070.3     183   0.2
+  595350  0.0309124  0.00000033  19.26  1847.3     162   0.2
+  600000  0.0289469  0.00000033  20.73  1989.3     173   0.2
+  600250  0.0336095  0.00000035  17.86  1714.1     149   0.3
+  602112  0.0196691  0.00000033  30.61  2938.7     255   0.2
+  604800  0.0226244  0.00000033  26.73  2567.1     221   0.4
+  605052  0.0295858  0.00000037  20.45  1964.0     169   0.5
+  607500  0.0293768  0.00000032  20.68  1986.5     171   0.2
+  612360  0.0291152  0.00000033  21.03  2021.6     172   0.2
+  612500  0.0304451  0.00000031  20.12  1933.8     165   0.2
+  614400  0.0186859  0.00000031  32.88  3161.3     268   0.3
+  614656  0.0220264  0.00000034  27.91  2683.0     227   0.2
+  617400  0.0339421  0.00000033  18.19  1749.5     148   0.2
+  622080  0.0213098  0.00000033  29.19  2809.3     235   0.4
+  625000  0.0341199  0.00000036  18.32  1763.4     147   0.2
+  627200  0.0211300  0.00000032  29.68  2858.3     237   0.2
+  629856  0.0315939  0.00000036  19.94  1920.3     159   0.2
+  630000  0.0307228  0.00000032  20.51  1975.2     163   0.3
+  635040  0.0284979  0.00000033  22.28  2147.8     176   0.2
+  637875  0.0453266  0.00000024  14.07  1356.8     111   0.2
+  640000  0.0217731  0.00000033  29.39  2834.7     230   0.2
+  642978  0.0378289  0.00000037  17.00  1639.7     133   0.2
+  643125  0.0468020  0.00000023  13.74  1325.7     107   0.2
+  645120  0.0209205  0.00000032  30.84  2975.6     239   0.3
+  648000  0.0270077  0.00000032  23.99  2316.0     186   0.4
+  648270  0.0388808  0.00000037  16.67  1609.5     129   0.8
+  653184  0.0281777  0.00000037  23.18  2238.9     178   0.3
+  655360  0.0204918  0.00000032  31.98  3089.7     244   0.2
+  656100  0.0315939  0.00000033  20.77  2006.4     159   0.2
+  656250  0.0360836  0.00000033  18.19  1757.2     139   0.2
+  658560  0.0255899  0.00000034  25.74  2487.2     196   0.2
+  661500  0.0315448  0.00000031  20.97  2027.3     159   0.2
+  663552  0.0212195  0.00000032  31.27  3023.9     236   0.4
+  666792  0.0323589  0.00000034  20.61  1993.3     155   0.2
+  672000  0.0225225  0.00000033  29.84  2887.9     222   0.3
+  672280  0.0332161  0.00000036  20.24  1959.1     151   0.5
+  675000  0.0346444  0.00000033  19.48  1886.5     145   0.2
+  677376  0.0244284  0.00000034  27.73  2685.5     205   0.3
+  680400  0.0357143  0.00000033  19.05  1845.7     140   0.3
+  686000  0.0298084  0.00000032  23.01  2230.9     168   0.2
+  688128  0.0216191  0.00000033  31.83  3086.3     232   0.2
+  688905  0.0501563  0.00000028  13.74  1331.9     100   0.2
+  691200  0.0231843  0.00000032  29.81  2891.7     216   0.5
+  691488  0.0319467  0.00000032  21.65  2099.5     157   0.2
+  694575  0.0544327  0.00000024  12.76  1238.1      92   0.2
+  699840  0.0338894  0.00000033  20.65  2004.8     148   0.4
+  700000  0.0307707  0.00000034  22.75  2208.6     163   0.2
+  702464  0.0231843  0.00000034  30.30  2942.4     216   0.2
+  703125  0.0520296  0.00000026  13.51  1312.4      97   0.2
+  705600  0.0331126  0.00000032  21.31  2070.0     151   0.3
+  705894  0.0453266  0.00000037  15.57  1512.9     111   0.3
+  708588  0.0379380  0.00000038  18.68  1815.0     132   0.2
+  708750  0.0356272  0.00000031  19.89  1933.1     141   0.2
+  714420  0.0351289  0.00000034  20.34  1977.4     143   0.2
+  716800  0.0239608  0.00000032  29.92  2909.5     209   0.2
+  720000  0.0277106  0.00000034  25.98  2527.8     181   0.4
+  720300  0.0577407  0.00000023  12.47  1213.7      87   0.2
+  725760  0.0255102  0.00000034  28.45  2769.5     196   0.4
+  729000  0.0354610  0.00000031  20.56  2001.9     141   0.3
+  734832  0.0368222  0.00000035  19.96  1944.4     136   0.3
+  735000  0.0396161  0.00000033  18.55  1807.8     127   0.2
+  737280  0.0229358  0.00000032  32.15  3132.9     218   0.4
+  740880  0.0538474  0.00000024  13.76  1341.4      93   0.2
+  746496  0.0266789  0.00000035  27.98  2729.5     188   0.4
+  750000  0.0378788  0.00000035  19.80  1932.1     132   0.2
+  750141  0.0622106  0.00000029  12.06  1176.7      81   0.2
+  752640  0.0260417  0.00000033  28.90  2821.0     192   0.2
+  756000  0.0393066  0.00000033  19.23  1878.0     128   0.3
+  756315  0.0744485  0.00000023  10.16   991.9      68   0.5
+  759375  0.0493643  0.00000023  15.38  1502.5     102   0.2
+  762048  0.0364963  0.00000035  20.88  2039.9     137   0.3
+  765450  0.0408410  0.00000033  18.74  1831.7     123   0.2
+  765625  0.0563553  0.00000026  13.59  1327.7      89   0.2
+  768000  0.0258940  0.00000032  29.66  2899.3     194   0.3
+  768320  0.0587754  0.00000025  13.07  1277.9      86   0.2
+  771750  0.0453266  0.00000030  17.03  1665.0     111   0.2
+  774144  0.0254600  0.00000033  30.41  2974.1     197   0.4
+  777600  0.0308186  0.00000034  25.23  2468.7     163   0.5
+  777924  0.0400000  0.00000035  19.45  1902.9     125   0.2
+  781250  0.0438596  0.00000035  17.81  1743.4     114   0.2
+  784000  0.0314957  0.00000033  24.89  2437.0     159   0.2
+  786432  0.0300337  0.00000033  26.18  2564.2     167   0.2
+  787320  0.0403226  0.00000034  19.53  1912.2     124   0.3
+  787500  0.0436821  0.00000032  18.03  1765.6     115   0.3
+  790272  0.0283810  0.00000035  27.85  2727.7     177   0.2
+  793800  0.0398065  0.00000032  19.94  1954.1     126   0.3
+  800000  0.0292060  0.00000035  27.39  2685.7     172   0.2
+  802816  0.0270693  0.00000034  29.66  2908.7     185   0.2
+  806400  0.0275155  0.00000032  29.31  2875.2     182   0.4
+  806736  0.0413869  0.00000036  19.49  1912.4     121   0.7
+  810000  0.0407139  0.00000032  19.89  1952.4     123   0.3
+  816480  0.0389414  0.00000034  20.97  2058.9     129   0.3
+  819200  0.0272164  0.00000032  30.10  2956.4     184   0.3
+  820125  0.0546026  0.00000024  15.02  1475.4      92   0.3
+  823200  0.0415806  0.00000032  19.80  1945.2     121   0.2
+  823543  0.0892857  0.00000024   9.22   906.3      56   0.3
+  826686  0.0486195  0.00000038  17.00  1671.2     103   0.2
+  826875  0.0644030  0.00000024  12.84  1261.9      78   0.3
+  829440  0.0276709  0.00000032  29.98  2946.8     181   0.4
+  833490  0.0473868  0.00000034  17.59  1729.8     106   0.2
+  839808  0.0391172  0.00000037  21.47  2112.5     128   0.3
+  840000  0.0424364  0.00000032  19.79  1947.8     118   0.3
+  840350  0.0500900  0.00000035  16.78  1650.9     100   0.4
+  843750  0.0458045  0.00000034  18.42  1813.2     110   0.2
+  846720  0.0341940  0.00000034  24.76  2438.0     147   0.3
+  850500  0.0430086  0.00000032  19.78  1947.6     117   0.3
+  857304  0.0444602  0.00000036  19.28  1900.2     113   0.3
+  857500  0.0456000  0.00000030  18.80  1853.2     110   0.2
+  860160  0.0290752  0.00000032  29.58  2916.1     173   0.3
+  864000  0.0300330  0.00000032  28.77  2836.7     167   0.4
+  864360  0.0412459  0.00000036  20.96  2066.4     122   1.3
+  870912  0.0327255  0.00000036  26.61  2625.6     153   0.4
+  874800  0.0491714  0.00000034  17.79  1755.8     102   0.4
+  875000  0.0500444  0.00000035  17.48  1725.6     101   0.2
+  878080  0.0314497  0.00000033  27.92  2756.3     159   0.2
+  882000  0.0452523  0.00000032  19.49  1924.8     111   0.3
+  884736  0.0292205  0.00000032  30.28  2990.7     172   0.3
+  885735  0.0672935  0.00000029  13.16  1300.2      75   0.3
+  889056  0.0489224  0.00000035  18.17  1795.6     103   0.3
+  893025  0.0674002  0.00000025  13.25  1309.6      75   0.3
+  896000  0.0315064  0.00000033  28.44  2811.6     159   0.3
+  900000  0.0460826  0.00000034  19.53  1931.5     109   0.4
+  900375  0.0914726  0.00000023   9.84   973.5      55   0.5
+  903168  0.0306766  0.00000033  29.44  2912.5     164   0.3
+  907200  0.0446429  0.00000032  20.32  2010.9     112   0.5
+  907578  0.0609877  0.00000039  14.88  1472.6      83   0.5
+  911250  0.0501500  0.00000033  18.17  1798.7     100   0.3
+  917504  0.0288708  0.00000034  31.78  3147.4     174   0.3
+  918540  0.0487868  0.00000035  18.83  1864.8     103   0.3
+  918750  0.0512549  0.00000032  17.93  1775.4      98   0.2
+  921600  0.0307272  0.00000032  29.99  2971.4     163   0.5
+  921984  0.0382753  0.00000035  24.09  2386.5     131   0.2
+  926100  0.0465280  0.00000032  19.90  1972.6     108   0.3
+  933120  0.0357253  0.00000035  26.12  2590.0     140   0.5
+  937500  0.0476904  0.00000034  19.66  1949.9     105   0.3
+  940800  0.0330953  0.00000033  28.43  2820.5     152   0.3
+  941192  0.0480544  0.00000037  19.59  1943.3     105   0.4
+  944784  0.0509693  0.00000036  18.54  1839.7      99   0.3
+  945000  0.0526370  0.00000033  17.95  1781.8      95   0.4
+  952560  0.0429445  0.00000033  22.18  2202.8     117   0.3
+  960000  0.0322533  0.00000033  29.76  2957.5     156   0.4
+  960400  0.0463657  0.00000033  20.71  2058.2     108   0.3
+  964467  0.0705210  0.00000031  13.68  1359.4      71   0.3
+  967680  0.0327388  0.00000033  29.56  2938.6     153   0.4
+  972000  0.0442629  0.00000032  21.96  2184.0     114   0.5
+  972405  0.0756713  0.00000026  12.85  1278.0      67   0.3
+  979776  0.0452567  0.00000036  21.65  2154.3     111   0.4
+  980000  0.0452664  0.00000033  21.65  2154.4     111   0.3
+  983040  0.0324984  0.00000033  30.25  3010.8     154   0.3
+  984150  0.0556390  0.00000034  17.69  1760.7      90   0.3
+  984375  0.0738754  0.00000025  13.32  1326.4      68   0.3
+  987840  0.0429187  0.00000033  23.02  2291.7     117   0.3
+  992250  0.0567078  0.00000032  17.50  1742.8      89   0.3
+  995328  0.0354978  0.00000034  28.04  2793.4     141   0.5
+ 1000000  0.0483748  0.00000035  20.67  2060.1     104   0.3
+ 1000188  0.0535947  0.00000036  18.66  1859.8      94   0.3
+ 1003520  0.0349308  0.00000033  28.73  2863.8     144   0.3
+ 1008000  0.0402524  0.00000034  25.04  2497.1     125   0.5
+ 1008420  0.0520833  0.00000037  19.36  1930.7      96   0.8
+ 1012500  0.0549508  0.00000034  18.43  1837.9      91   0.4
+ 1016064  0.0389466  0.00000036  26.09  2602.9     129   0.4
+ 1020600  0.0529580  0.00000032  19.27  1923.4      95   0.5
+ 1024000  0.0348110  0.00000032  29.42  2936.6     144   0.3
+ 1029000  0.0584004  0.00000033  17.62  1759.6      86   0.3
+ 1032192  0.0361868  0.00000033  28.52  2849.2     139   0.4
+ 1036800  0.0360867  0.00000032  28.73  2870.7     139   0.7
+ 1037232  0.0837087  0.00000026  12.39  1238.1      60   0.3
+ 1048576  0.0403831  0.00000034  25.97  2596.6     124   0.3
+ 1049760  0.0540099  0.00000035  19.44  1943.8      93   0.5
+ 1050000  0.0552033  0.00000034  19.02  1902.2      91   0.3
+ 1053696  0.0498854  0.00000033  21.12  2113.0     101   0.3
+ 1058400  0.0588239  0.00000033  17.99  1800.5      85   0.4
+ 1058841  0.1140130  0.00000026   9.29   929.4      44   0.5
+ 1062882  0.0642051  0.00000039  16.55  1657.1      78   0.3
+ 1063125  0.0825971  0.00000023  12.87  1288.4      61   0.4
+ 1071630  0.0653369  0.00000035  16.40  1642.7      77   0.4
+ 1071875  0.0827552  0.00000024  12.95  1297.3      61   0.3
+ 1075200  0.0503101  0.00000032  21.37  2141.0     100   0.4
+ 1075648  0.0565275  0.00000038  19.03  1906.4      89   0.7
+ 1080000  0.0554729  0.00000033  19.47  1951.0      91   0.5
+ 1080450  0.0602454  0.00000031  17.93  1797.3      83   0.3
+ 1088640  0.0552911  0.00000033  19.69  1974.2      91   0.4
+ 1093500  0.0503897  0.00000032  21.70  2176.7     100   0.4
+ 1093750  0.0703057  0.00000034  15.56  1560.4      72   0.3
+ 1097600  0.0512493  0.00000033  21.42  2148.7      98   0.3
+ 1102248  0.0552086  0.00000037  19.97  2003.7      91   0.3
+ 1102500  0.0634804  0.00000032  17.37  1743.0      79   0.4
+ 1105920  0.0513421  0.00000031  21.54  2162.3      98   0.4
+ 1111320  0.0524057  0.00000034  21.21  2129.5      96   0.3
+ 1119744  0.0566122  0.00000035  19.78  1987.3      89   0.5
+ 1120000  0.0600164  0.00000033  18.66  1875.0      84   0.4
+ 1125000  0.0641984  0.00000035  17.52  1761.3      78   0.4
+ 1128960  0.0509092  0.00000033  22.18  2229.4      99   0.3
+ 1134000  0.0615607  0.00000033  18.42  1852.5      82   0.5
+ 1143072  0.0649038  0.00000036  17.61  1772.1      78   0.4
+ 1146880  0.0445222  0.00000032  25.76  2592.6     113   0.3
+ 1148175  0.0867499  0.00000027  13.24  1332.2      58   0.4
+ 1152000  0.0554669  0.00000033  20.77  2091.0      91   0.5
+ 1152480  0.0581566  0.00000037  19.82  1995.2      86   1.7
+ 1157625  0.0952079  0.00000024  12.16  1224.6      53   0.4
+ 1161216  0.0575632  0.00000034  20.17  2032.1      87   0.4
+ 1166400  0.0529734  0.00000033  22.02  2218.8      95   0.6
+ 1166886  0.0695623  0.00000036  16.77  1690.4      72   0.3
+ 1171875  0.0871466  0.00000029  13.45  1355.5      58   0.4
+ 1176000  0.0631813  0.00000032  18.61  1876.7      80   0.4
+ 1176490  0.0736470  0.00000036  15.97  1610.7      68   0.5
+ 1179648  0.0453288  0.00000032  26.02  2624.5     111   0.4
+ 1180980  0.0671932  0.00000036  17.58  1772.7      75   0.4
+ 1181250  0.0656429  0.00000033  18.00  1815.0      77   0.4
+ 1185408  0.0531967  0.00000034  22.28  2248.1      94   0.3
+ 1190700  0.0648076  0.00000033  18.37  1854.1      78   0.4
+ 1200000  0.0645063  0.00000033  18.60  1878.4      78   0.4
+ 1200500  0.1039491  0.00000024  11.55  1166.2      49   0.4
+ 1204224  0.0486847  0.00000032  24.74  2498.2     103   0.3
+ 1209600  0.0538284  0.00000032  22.47  2270.3      93   0.6
+ 1210104  0.0651364  0.00000038  18.58  1877.0      77   0.9
+ 1215000  0.0711971  0.00000033  17.07  1724.7      71   0.5
+ 1224720  0.0660858  0.00000034  18.53  1874.0      76   0.5
+ 1225000  0.0698683  0.00000034  17.53  1773.0      72   0.3
+ 1228800  0.0590117  0.00000032  20.82  2106.1      85   0.4
+ 1229312  0.0658088  0.00000032  18.68  1889.4      76   0.3
+ 1234800  0.0687122  0.00000033  17.97  1818.3      73   0.4
+ 1240029  0.0955281  0.00000033  12.98  1313.8      53   0.4
+ 1244160  0.0615487  0.00000033  20.21  2046.4      82   0.6
+ 1250000  0.0706546  0.00000038  17.69  1791.6      71   0.4
+ 1250235  0.1051356  0.00000026  11.89  1204.3      48   0.4
+ 1254400  0.0525881  0.00000033  23.85  2416.2      96   0.4
+ 1259712  0.0667603  0.00000037  18.87  1911.9      75   0.5
+ 1260000  0.0672998  0.00000032  18.72  1897.0      75   0.5
+ 1260525  0.1389193  0.00000023   9.07   919.4      37   0.7
+ 1265625  0.0944721  0.00000025  13.40  1357.9      53   0.4
+ 1270080  0.0607050  0.00000034  20.92  2121.1      83   0.4
+ 1275750  0.0753283  0.00000033  16.94  1717.5      67   0.4
+ 1280000  0.0535324  0.00000034  23.91  2425.5      94   0.4
+ 1285956  0.0729184  0.00000038  17.64  1789.5      69   0.4
+ 1286250  0.0742152  0.00000031  17.33  1758.7      68   0.4
+ 1290240  0.0518711  0.00000032  24.87  2524.6      97   0.5
+ 1296000  0.0624005  0.00000032  20.77  2108.6      81   0.6
+ 1296540  0.0698963  0.00000037  18.55  1883.4      72   1.5
+ 1306368  0.0638799  0.00000035  20.45  2077.5      79   0.5
+ 1310720  0.0511039  0.00000032  25.65  2606.1      98   0.4
+ 1312200  0.0630798  0.00000033  20.80  2113.9      80   0.5
+ 1312500  0.0685642  0.00000033  19.14  1945.3      73   0.4
+ 1317120  0.0982056  0.00000026  13.41  1363.2      51   0.4
+ 1323000  0.0797875  0.00000034  16.58  1686.0      63   0.4
+ 1327104  0.0658363  0.00000032  20.16  2050.0      77   0.5
+ 1333584  0.0783997  0.00000035  17.01  1730.5      64   0.4
+ 1344000  0.0723214  0.00000034  18.58  1891.6      70   0.5
+ 1344560  0.0717564  0.00000036  18.74  1907.4      70   0.8
+ 1350000  0.0733634  0.00000034  18.40  1873.7      69   0.5
+ 1354752  0.0691286  0.00000034  19.60  1996.0      73   0.4
+ 1360800  0.0764530  0.00000033  17.80  1813.4      66   0.6
+ 1361367  0.1546261  0.00000027   8.80   897.0      33   0.7
+ 1366875  0.1105771  0.00000024  12.36  1259.8      46   0.4
+ 1372000  0.0776367  0.00000033  17.67  1801.5      65   0.4
+ 1376256  0.0557217  0.00000033  24.70  2518.3      90   0.4
+ 1377810  0.0895636  0.00000035  15.38  1568.7      56   0.4
+ 1378125  0.1041896  0.00000024  13.23  1348.8      48   0.4
+ 1382400  0.0625000  0.00000032  22.12  2255.9      80   0.6
+ 1382976  0.0697784  0.00000035  19.82  2021.5      72   0.4
+ 1389150  0.0919201  0.00000033  15.11  1541.9      55   0.4
+ 1399680  0.0684979  0.00000034  20.43  2086.0      74   0.5
+ 1400000  0.0765751  0.00000034  18.28  1866.4      66   0.5
+ 1404928  0.0702150  0.00000034  20.01  2043.1      72   0.4
+ 1406250  0.0804744  0.00000034  17.47  1784.4      63   0.4
+ 1411200  0.0705274  0.00000033  20.01  2043.8      71   0.5
+ 1411788  0.0749712  0.00000038  18.83  1923.5      67   0.6
+ 1417176  0.0867583  0.00000037  16.33  1669.0      58   0.4
+ 1417500  0.0858134  0.00000031  16.52  1687.8      59   0.5
+ 1428840  0.0801256  0.00000034  17.83  1823.1      63   0.4
+ 1433600  0.0616396  0.00000032  23.26  2378.3      82   0.4
+ 1440000  0.0719788  0.00000033  20.01  2046.4      70   0.6
+ 1440600  0.0901293  0.00000033  15.98  1635.0      56   0.4
+ 1451520  0.0855609  0.00000034  16.96  1736.3      59   0.6
+ 1458000  0.0854068  0.00000033  17.07  1747.7      59   0.6
+ 1469664  0.0877289  0.00000037  16.75  1716.0      57   0.5
+ 1470000  0.0819062  0.00000033  17.95  1838.5      62   0.5
+ 1474560  0.0781250  0.00000032  18.87  1933.9      64   0.5
+ 1476225  0.1186538  0.00000028  12.44  1274.8      43   0.5
+ 1481760  0.0859313  0.00000034  17.24  1767.4      59   0.4
+ 1488375  0.1182790  0.00000024  12.58  1290.2      43   0.5
+ 1492992  0.0691453  0.00000035  21.59  2214.2      73   0.6
+ 1500000  0.0835958  0.00000035  17.94  1840.7      60   0.5
+ 1500282  0.0961621  0.00000036  15.60  1600.5      52   0.4
+ 1500625  0.1213190  0.00000024  12.37  1268.9      42   0.5
+ 1505280  0.0776461  0.00000033  19.39  1989.2      65   0.4
+ 1512000  0.0769400  0.00000033  19.65  2017.1      65   0.6
+ 1512630  0.1301457  0.00000038  11.62  1193.0      39   1.0
+ 1518750  0.0959588  0.00000032  15.83  1625.0      53   0.5
+ 1524096  0.0771597  0.00000035  19.75  2028.5      65   0.5
+ 1530900  0.0985107  0.00000034  15.54  1596.5      51   0.5
+ 1531250  0.1004468  0.00000032  15.24  1566.1      50   0.5
+ 1536000  0.0671875  0.00000033  22.86  2349.1      75   0.5
+ 1536640  0.0826096  0.00000037  18.60  1911.4      61   1.5
+ 1543500  0.0979990  0.00000032  15.75  1618.9      52   0.5
+ 1548288  0.0862237  0.00000033  17.96  1846.1      58   0.5
+ 1555200  0.0773982  0.00000032  20.09  2066.5      65   0.7
+ 1555848  0.0910645  0.00000033  17.09  1757.1      55   0.4
+ 1562500  0.0876696  0.00000037  17.82  1833.5      58   0.4
+ 1568000  0.0890685  0.00000032  17.60  1811.5      57   0.5
+ 1572864  0.0659935  0.00000032  23.83  2453.1      76   0.4
+ 1574640  0.0878585  0.00000034  17.92  1844.8      57   0.5
+ 1575000  0.0964402  0.00000035  16.33  1681.1      52   0.5
+ 1580544  0.0924627  0.00000035  17.09  1760.0      55   0.5
+ 1587600  0.0945008  0.00000034  16.80  1730.3      53   0.5
+ 1594323  0.1589394  0.00000035  10.03  1033.4      32   0.6
+ 1600000  0.0939015  0.00000035  17.04  1755.9      54   0.5
+ 1605632  0.0827257  0.00000033  19.41  2000.6      61   0.5
+ 1607445  0.1336477  0.00000028  12.03  1239.8      38   0.5
+ 1612800  0.0855403  0.00000033  18.85  1944.0      59   0.7
+ 1613472  0.0894383  0.00000037  18.04  1860.1      56   1.1
+ 1620000  0.0919079  0.00000034  17.63  1817.9      55   0.7
+ 1620675  0.1382958  0.00000025  11.72  1208.7      37   0.5
+ 1632960  0.0878628  0.00000035  18.59  1917.9      57   0.6
+ 1638400  0.0864658  0.00000032  18.95  1955.9      58   0.5
+ 1640250  0.1143494  0.00000033  14.34  1480.7      44   0.5
+ 1640625  0.1281128  0.00000028  12.81  1322.0      40   0.5
+ 1646400  0.0862237  0.00000032  19.09  1971.6      58   0.5
+ 1647086  0.1131972  0.00000037  14.55  1502.5      45   0.6
+ 1653372  0.1061350  0.00000038  15.58  1609.0      48   0.5
+ 1653750  0.1093803  0.00000033  15.12  1561.6      46   0.5
+ 1658880  0.0718558  0.00000032  23.09  2385.0      70   0.7
+ 1666980  0.1322246  0.00000026  12.61  1302.9      38   0.5
+ 1679616  0.0931758  0.00000036  18.03  1863.9      54   0.6
+ 1680000  0.0867246  0.00000032  19.37  2003.0      58   0.6
+ 1680700  0.0914617  0.00000037  18.38  1900.1      55   0.8
+ 1687500  0.1088549  0.00000034  15.50  1603.4      46   0.5
+ 1693440  0.0890728  0.00000033  19.01  1966.9      57   0.5
+ 1701000  0.1063934  0.00000032  15.99  1654.6      47   0.5
+ 1714608  0.0963088  0.00000036  17.80  1843.5      52   0.5
+ 1715000  0.0969215  0.00000031  17.69  1832.3      52   0.5
+ 1720320  0.0761201  0.00000033  22.60  2340.7      66   0.5
+ 1728000  0.0842468  0.00000033  20.51  2125.0      60   0.8
+ 1728720  0.1441860  0.00000025  11.99  1242.2      35   0.6
+ 1741824  0.0863521  0.00000036  20.17  2091.0      58   0.7
+ 1749600  0.1041819  0.00000034  16.79  1741.4      48   0.7
+ 1750000  0.0974990  0.00000034  17.95  1861.2      52   0.5
+ 1750329  0.1576843  0.00000030  11.10  1151.0      32   0.6
+ 1756160  0.0830078  0.00000033  21.16  2194.4      61   0.5
+ 1764000  0.1080530  0.00000033  16.33  1693.8      47   0.6
+ 1764735  0.1968431  0.00000024   8.97   930.2      26   0.9
+ 1769472  0.0964520  0.00000032  18.35  1903.8      52   0.6
+ 1771470  0.1374611  0.00000035  12.89  1337.5      37   0.6
+ 1771875  0.1534128  0.00000024  11.55  1198.7      33   0.6
+ 1778112  0.0967689  0.00000036  18.37  1907.5      52   0.5
+ 1786050  0.1154092  0.00000034  15.48  1607.0      44   0.5
+ 1792000  0.0860637  0.00000034  20.82  2162.7      59   0.6
+ 1800000  0.0994993  0.00000035  18.09  1879.6      51   0.7
+ 1800750  0.1328189  0.00000038  13.56  1408.7      38   1.0
+ 1806336  0.0868762  0.00000033  20.79  2160.8      58   0.6
+ 1814400  0.0986544  0.00000033  18.39  1911.9      51   0.8
+ 1815156  0.1054713  0.00000039  17.21  1789.1      48   1.0
+ 1822500  0.1170001  0.00000032  15.58  1619.8      43   0.6
+ 1835008  0.1006201  0.00000033  18.24  1897.3      50   0.5
+ 1837080  0.1252014  0.00000035  14.67  1526.7      40   0.6
+ 1837500  0.1203497  0.00000032  15.27  1588.6      42   0.5
+ 1843200  0.1044769  0.00000032  17.64  1836.0      48   0.8
+ 1843968  0.1413439  0.00000027  13.05  1357.7      36   0.6
+ 1852200  0.1049132  0.00000032  17.65  1837.9      49   0.5
+ 1866240  0.1236185  0.00000035  15.10  1572.5      41   0.8
+ 1875000  0.1073803  0.00000035  17.46  1819.3      47   0.5
+ 1881600  0.1161360  0.00000034  16.20  1688.5      44   0.6
+ 1882384  0.1016797  0.00000038  18.51  1929.4      50   0.7
+ 1889568  0.1314416  0.00000038  14.38  1498.6      39   0.6
+ 1890000  0.1058070  0.00000032  17.86  1862.2      48   0.6
+ 1905120  0.1190883  0.00000035  16.00  1668.7      42   0.6
+ 1913625  0.1572495  0.00000025  12.17  1269.7      32   0.6
+ 1920000  0.1125000  0.00000034  17.07  1781.1      45   0.7
+ 1920800  0.1164551  0.00000031  16.49  1721.4      43   0.6
+ 1928934  0.1398926  0.00000037  13.79  1439.5      36   0.6
+ 1929375  0.1604233  0.00000024  12.03  1255.6      32   0.6
+ 1935360  0.0949799  0.00000033  20.38  2127.7      53   0.7
+ 1944000  0.1061147  0.00000033  18.32  1913.6      48   0.8
+ 1944810  0.1417236  0.00000039  13.72  1433.4      36   1.4
+ 1953125  0.1660826  0.00000033  11.76  1228.8      31   0.6
+ 1959552  0.1171989  0.00000037  16.72  1747.4      43   0.7
+ 1960000  0.1107390  0.00000033  17.70  1849.8      46   0.6
+ 1966080  0.1124919  0.00000032  17.48  1827.0      45   0.6
+ 1968300  0.1189675  0.00000035  16.54  1729.6      43   0.6
+ 1968750  0.1186353  0.00000033  16.59  1734.9      43   0.6
+ 1975680  0.1152510  0.00000034  17.14  1792.6      44   0.6
+ 1984500  0.1143632  0.00000032  17.35  1815.1      44   0.6
+ 1990656  0.1181130  0.00000034  16.85  1763.3      43   0.7
+ 2000000  0.1285995  0.00000036  15.55  1627.7      39   0.6
+ 2000376  0.1404487  0.00000036  14.24  1490.6      36   0.6
+ 2007040  0.1196115  0.00000033  16.78  1756.5      42   0.6
+ 2016000  0.1148654  0.00000033  17.55  1837.9      44   0.8
+ 2016840  0.1112766  0.00000037  18.12  1898.0      45   1.4
+ 2025000  0.1195650  0.00000033  16.94  1774.0      42   0.6
+ 2032128  0.1337377  0.00000036  15.19  1592.0      38   0.7
+ 2041200  0.1338629  0.00000032  15.25  1598.1      38   0.7
+ 2048000  0.1070635  0.00000033  19.13  2005.3      47   0.6
+ 2058000  0.2154999  0.00000025   9.55  1001.4      24   0.8
+ 2064384  0.1214774  0.00000032  16.99  1782.4      42   0.7
+ 2066715  0.1999089  0.00000030  10.34  1084.4      26   0.7
+ 2073600  0.1092397  0.00000033  18.98  1991.6      46   1.0
+ 2074464  0.1368276  0.00000036  15.16  1590.7      37   0.6
+ 2083725  0.1851852  0.00000026  11.25  1181.0      27   0.7
+ 2097152  0.1031619  0.00000033  20.33  2134.5      49   0.5
+ 2099520  0.1297858  0.00000036  16.18  1698.7      39   0.7
+ 2100000  0.1310096  0.00000035  16.03  1683.2      39   0.7
+ 2100875  0.2577776  0.00000023   8.15   855.8      21   0.9
+ 2107392  0.1137945  0.00000034  18.52  1945.2      44   0.6
+ 2109375  0.1633064  0.00000026  12.92  1356.8      31   0.7
+ 2116800  0.1263733  0.00000033  16.75  1759.9      40   0.8
+ 2117682  0.1574860  0.00000039  13.45  1412.9      32   0.9
+ 2125764  0.1524695  0.00000039  13.94  1465.3      33   0.7
+ 2126250  0.1292005  0.00000033  16.46  1729.6      39   0.6
+ 2143260  0.1650706  0.00000034  12.98  1365.3      31   0.7
+ 2143750  0.1572189  0.00000032  13.64  1433.9      32   0.6
+ 2150400  0.1188624  0.00000033  18.09  1902.9      43   0.8
+ 2151296  0.1196434  0.00000038  17.98  1891.3      42   1.2
+ 2160000  0.1301739  0.00000033  16.59  1745.8      39   1.0
+ 2160900  0.1376656  0.00000033  15.70  1651.5      37   0.7
+ 2177280  0.1279480  0.00000033  17.02  1791.4      40   0.8
+ 2187000  0.1457275  0.00000032  15.01  1580.3      35   0.7
+ 2187500  0.1363888  0.00000036  16.04  1688.9      37   0.6
+ 2195200  0.1309752  0.00000032  16.76  1765.4      39   0.6
+ 2204496  0.1376788  0.00000038  16.01  1687.0      37   0.7
+ 2205000  0.1355475  0.00000033  16.27  1714.0      37   0.7
+ 2211840  0.1238508  0.00000032  17.86  1882.0      41   0.8
+ 2222640  0.1330085  0.00000034  16.71  1761.6      38   0.6
+ 2239488  0.1412625  0.00000037  15.85  1672.1      36   0.8
+ 2240000  0.1453299  0.00000034  15.41  1625.7      35   0.7
+ 2250000  0.1405029  0.00000034  16.01  1689.6      36   0.7
+ 2250423  0.2164612  0.00000031  10.40  1096.9      24   0.8
+ 2257920  0.1223412  0.00000034  18.46  1947.7      41   0.7
+ 2268000  0.1482328  0.00000034  15.30  1615.2      34   0.8
+ 2268945  0.2566284  0.00000025   8.84   933.4      20   1.2
+ 2278125  0.1924190  0.00000024  11.84  1250.2      27   0.8
+ 2286144  0.1457589  0.00000037  15.68  1656.6      35   0.8
+ 2293760  0.1214629  0.00000033  18.88  1995.1      42   0.7
+ 2296350  0.1653383  0.00000035  13.89  1467.4      31   0.7
+ 2296875  0.2280162  0.00000026  10.07  1064.3      22   0.8
+ 2304000  0.1283835  0.00000034  17.95  1896.5      39   0.9
+ 2304960  0.1232791  0.00000038  18.70  1975.9      41   2.6
+ 2315250  0.1548480  0.00000033  14.95  1580.6      33   0.7
+ 2322432  0.1376557  0.00000035  16.87  1783.9      37   0.8
+ 2332800  0.1397739  0.00000033  16.69  1765.3      36   1.0
+ 2333772  0.2109375  0.00000028  11.06  1170.2      24   0.8
+ 2343750  0.1767241  0.00000037  13.26  1403.2      29   0.7
+ 2352000  0.1616132  0.00000032  14.55  1540.1      31   0.8
+ 2352980  0.1308312  0.00000038  17.98  1903.3      39   0.9
+ 2359296  0.1292005  0.00000033  18.26  1932.9      39   0.8
+ 2361960  0.1614400  0.00000035  14.63  1548.8      31   1.3
+ 2362500  0.1412557  0.00000033  16.72  1770.5      36   0.7
+ 2370816  0.1527137  0.00000036  15.52  1643.8      33   0.7
+ 2381400  0.1459856  0.00000033  16.31  1727.8      35   0.7
+ 2400000  0.1455183  0.00000034  16.49  1747.8      35   0.8
+ 2401000  0.1353397  0.00000037  17.74  1880.1      37   1.2
+ 2408448  0.1410522  0.00000034  17.07  1809.9      36   0.7
+ 2419200  0.1548517  0.00000034  15.62  1656.5      33   0.9
+ 2420208  0.1342645  0.00000038  18.03  1911.3      38   1.6
+ 2430000  0.1669474  0.00000032  14.56  1543.8      30   0.8
+ 2449440  0.1687256  0.00000033  14.52  1540.6      30   0.8
+ 2450000  0.1572380  0.00000032  15.58  1653.5      32   0.7
+ 2457600  0.1427680  0.00000033  17.21  1827.2      36   0.8
+ 2458624  0.1524584  0.00000035  16.13  1711.8      33   0.7
+ 2460375  0.2226828  0.00000026  11.05  1172.9      23   0.9
+ 2469600  0.1877939  0.00000034  13.15  1396.3      27   0.8
+ 2470629  0.2856039  0.00000026   8.65   918.5      18   1.0
+ 2480058  0.1983173  0.00000039  12.51  1328.2      26   0.8
+ 2480625  0.2272312  0.00000024  10.92  1159.5      23   0.9
+ 2488320  0.1520071  0.00000034  16.37  1739.0      33   0.9
+ 2500000  0.1740386  0.00000037  14.36  1526.5      29   0.8
+ 2500470  0.1929087  0.00000034  12.96  1377.5      26   0.8
+ 2508800  0.1514139  0.00000034  16.57  1761.2      34   0.8
+ 2519424  0.1764632  0.00000038  14.28  1518.0      29   0.8
+ 2520000  0.1769935  0.00000033  14.24  1513.8      29   0.9
+ 2521050  0.1833147  0.00000038  13.75  1462.3      28   1.3
+ 2531250  0.1799491  0.00000034  14.07  1496.1      28   0.8
+ 2540160  0.1645508  0.00000035  15.44  1642.2      31   0.8
+ 2551500  0.1718669  0.00000033  14.85  1579.8      30   0.8
+ 2560000  0.1575165  0.00000035  16.25  1729.9      32   0.8
+ 2571912  0.1958196  0.00000037  13.13  1398.4      26   0.8
+ 2572500  0.1721517  0.00000032  14.94  1591.1      30   0.8
+ 2580480  0.1579666  0.00000033  16.34  1739.7      32   0.9
+ 2592000  0.1737439  0.00000033  14.92  1589.2      29   1.0
+ 2593080  0.1498090  0.00000038  17.31  1844.0      34   2.6
+ 2612736  0.1892632  0.00000037  13.80  1471.4      27   0.9
+ 2621440  0.1596756  0.00000033  16.42  1750.2      32   0.8
+ 2624400  0.1814837  0.00000033  14.46  1541.8      28   1.0
+ 2625000  0.2021582  0.00000034  12.98  1384.4      25   0.9
+ 2634240  0.1740386  0.00000035  15.14  1614.2      29   0.8
+ 2646000  0.1796352  0.00000032  14.73  1571.3      28   0.9
+ 2654208  0.1603241  0.00000033  16.56  1766.4      32   0.9
+ 2657205  0.2519531  0.00000032  10.55  1125.4      20   0.9
+ 2667168  0.1671631  0.00000035  15.96  1703.0      30   0.8
+ 2679075  0.2834473  0.00000027   9.45  1009.1      18   1.0
+ 2688000  0.1683187  0.00000034  15.97  1705.4      30   0.9
+ 2689120  0.1486673  0.00000037  18.09  1931.7      34   1.4
+ 2700000  0.2010352  0.00000034  13.43  1434.7      25   1.1
+ 2701125  0.2684647  0.00000024  10.06  1074.8      19   1.0
+ 2709504  0.1713298  0.00000035  15.81  1689.8      30   0.9
+ 2721600  0.2062695  0.00000034  13.19  1410.2      25   1.1
+ 2722734  0.2165324  0.00000041  12.57  1344.0      24   1.3
+ 2733750  0.2006445  0.00000033  13.62  1456.7      25   0.9
+ 2734375  0.2576904  0.00000031  10.61  1134.5      20   1.0
+ 2744000  0.1791382  0.00000033  15.32  1638.1      28   0.8
+ 2752512  0.1663543  0.00000033  16.55  1769.8      31   0.8
+ 2755620  0.2089844  0.00000035  13.19  1410.5      24   0.9
+ 2756250  0.1989183  0.00000033  13.86  1482.2      26   0.9
+ 2764800  0.1740302  0.00000033  15.89  1699.8      29   1.1
+ 2765952  0.1844046  0.00000034  15.00  1604.9      28   0.8
+ 2778300  0.1983643  0.00000034  14.01  1499.1      26   0.9
+ 2799360  0.1811175  0.00000035  15.46  1655.1      28   1.0
+ 2800000  0.1844221  0.00000035  15.18  1625.8      28   0.9
+ 2809856  0.1818935  0.00000035  15.45  1654.6      28   0.8
+ 2812500  0.1950120  0.00000036  14.42  1544.9      26   0.9
+ 2822400  0.1754024  0.00000034  16.09  1724.0      29   0.9
+ 2823576  0.1587067  0.00000039  17.79  1906.2      32   1.2
+ 2834352  0.1988995  0.00000039  14.25  1527.2      26   0.9
+ 2835000  0.1986178  0.00000032  14.27  1529.8      26   1.0
+ 2857680  0.1836112  0.00000034  15.56  1668.9      28   0.9
+ 2867200  0.1860532  0.00000033  15.41  1652.9      27   0.9
+ 2880000  0.2020898  0.00000035  14.25  1529.0      25   1.2
+ 2881200  0.3655134  0.00000025   7.88   845.7      14   1.1
+ 2893401  0.3088379  0.00000033   9.37  1005.5      17   1.1
+ 2903040  0.1929650  0.00000034  15.04  1614.9      26   1.0
+ 2916000  0.2375710  0.00000034  12.27  1318.0      22   1.2
+ 2917215  0.3295746  0.00000027   8.85   950.5      16   1.5
+ 2939328  0.1926551  0.00000036  15.26  1639.1      26   0.9
+ 2940000  0.2312012  0.00000034  12.72  1366.2      22   1.0
+ 2941225  0.3437337  0.00000024   8.56   919.3      15   1.2
+ 2949120  0.1889377  0.00000033  15.61  1677.3      27   1.0
+ 2952450  0.2504517  0.00000036  11.79  1266.9      20   1.0
+ 2953125  0.2775750  0.00000025  10.64  1143.4      19   1.0
+ 2963520  0.2643915  0.00000025  11.21  1204.9      19   1.0
+ 2976750  0.2329656  0.00000034  12.78  1373.9      22   1.0
+ 2985984  0.2062402  0.00000035  14.48  1557.1      25   1.1
+ 3000000  0.2259044  0.00000036  13.28  1428.7      23   1.1
+ 3000564  0.2343639  0.00000037  12.80  1377.4      22   0.9
+ 3001250  0.2315119  0.00000031  12.96  1394.7      22   0.9
+ 3010560  0.1953313  0.00000034  15.41  1658.5      26   0.9
+ 3024000  0.2177204  0.00000034  13.89  1495.1      23   1.1
+ 3025260  0.1677002  0.00000038  18.04  1941.8      30   1.8
+ 3037500  0.2257876  0.00000033  13.45  1448.5      23   1.0
+ 3048192  0.2287265  0.00000037  13.33  1435.3      22   1.0
+ 3061800  0.2241848  0.00000034  13.66  1471.3      23   1.1
+ 3062500  0.2507812  0.00000034  12.21  1315.6      20   1.0
+ 3072000  0.2065430  0.00000034  14.87  1602.7      25   1.0
+ 3073280  0.2713173  0.00000027  11.33  1220.6      19   1.0
+ 3087000  0.2280495  0.00000033  13.54  1459.1      22   1.0
+ 3096576  0.2034082  0.00000033  15.22  1641.3      25   1.0
+ 3110400  0.2266686  0.00000035  13.72  1479.9      23   1.3
+ 3111696  0.2086283  0.00000036  14.92  1608.5      24   0.9
+ 3125000  0.2605347  0.00000038  11.99  1293.9      20   1.0
+ 3136000  0.2462449  0.00000034  12.74  1374.2      21   1.0
+ 3145728  0.2086792  0.00000033  15.07  1626.9      24   1.0
+ 3149280  0.2080762  0.00000034  15.14  1633.6      25   1.0
+ 3150000  0.2360729  0.00000033  13.34  1440.2      22   1.2
+ 3161088  0.2201087  0.00000036  14.36  1550.5      23   1.0
+ 3175200  0.2685804  0.00000035  11.82  1276.7      19   1.2
+ 3176523  0.3822545  0.00000028   8.31   897.4      14   1.4
+ 3188646  0.2877468  0.00000040  11.08  1197.0      18   1.1
+ 3189375  0.2954963  0.00000025  10.79  1165.9      17   1.1
+ 3200000  0.2268809  0.00000037  14.10  1523.9      23   1.1
+ 3211264  0.2173665  0.00000034  14.77  1596.6      24   1.0
+ 3214890  0.2750694  0.00000036  11.69  1263.2      19   1.1
+ 3215625  0.3232727  0.00000025   9.95  1075.1      16   1.2
+ 3225600  0.2198539  0.00000033  14.67  1586.1      23   1.2
+ 3226944  0.1796962  0.00000039  17.96  1941.4      28   1.9
+ 3240000  0.2500000  0.00000033  12.96  1401.5      20   1.4
+ 3241350  0.2721140  0.00000034  11.91  1288.1      19   1.1
+ 3265920  0.2272838  0.00000036  14.37  1554.7      22   1.1
+ 3276800  0.2225820  0.00000033  14.72  1593.2      23   1.0
+ 3280500  0.2666787  0.00000034  12.30  1331.3      19   1.1
+ 3281250  0.2735531  0.00000036  11.99  1298.2      19   1.1
+ 3292800  0.2503174  0.00000033  13.15  1424.0      20   1.1
+ 3294172  0.1987868  0.00000040  16.57  1794.0      26   1.1
+ 3306744  0.2636590  0.00000039  12.54  1358.1      19   1.1
+ 3307500  0.2537476  0.00000033  13.03  1411.5      20   1.1
+ 3317760  0.2272838  0.00000033  14.60  1581.0      22   1.2
+ 3333960  0.2372048  0.00000035  14.06  1522.8      22   1.0
+ 3359232  0.2755320  0.00000038  12.19  1321.6      19   1.2
+ 3360000  0.2511841  0.00000033  13.38  1450.0      20   1.2
+ 3361400  0.1956036  0.00000037  17.18  1862.9      26   1.5
+ 3375000  0.2690173  0.00000034  12.55  1360.4      19   1.2
+ 3386880  0.2632478  0.00000035  12.87  1395.4      19   1.1
+ 3402000  0.2266368  0.00000033  15.01  1628.5      23   1.2
+ 3429216  0.2308017  0.00000036  14.86  1612.8      22   1.1
+ 3430000  0.2643915  0.00000032  12.97  1408.2      19   1.1
+ 3440640  0.2419434  0.00000033  14.22  1544.0      21   1.1
+ 3444525  0.3615723  0.00000028   9.53  1034.4      14   1.3
+ 3456000  0.2425595  0.00000034  14.25  1547.4      21   1.4
+ 3457440  0.2028223  0.00000037  17.05  1851.4      25   3.6
+ 3472875  0.3828125  0.00000025   9.07   985.6      14   1.3
+ 3483648  0.2639032  0.00000036  13.20  1434.4      19   1.2
+ 3499200  0.2959415  0.00000035  11.82  1285.2      17   1.4
+ 3500000  0.2987132  0.00000036  11.72  1273.6      17   1.2
+ 3500658  0.3416829  0.00000036  10.25  1113.6      15   1.2
+ 3512320  0.2462449  0.00000034  14.26  1550.7      21   1.1
+ 3515625  0.3535644  0.00000029   9.94  1081.1      15   1.3
+ 3528000  0.2701480  0.00000033  13.06  1420.2      19   1.2
+ 3529470  0.2606079  0.00000039  13.54  1472.9      20   1.5
+ 3538944  0.2425130  0.00000033  14.59  1587.3      21   1.2
+ 3542940  0.3396322  0.00000037  10.43  1134.8      15   1.2
+ 3543750  0.3079906  0.00000034  11.51  1251.7      17   1.2
+ 3556224  0.2740157  0.00000037  12.98  1412.1      19   1.7
+ 3572100  0.2945916  0.00000035  12.13  1319.8      17   1.2
+ 3584000  0.2597656  0.00000034  13.80  1502.0      20   1.2
+ 3600000  0.2829861  0.00000035  12.72  1385.3      18   1.3
+ 3601500  0.2096354  0.00000038  17.18  1870.9      24   2.0
+ 3612672  0.2601441  0.00000034  13.89  1512.6      20   1.2
+ 3628800  0.2575317  0.00000033  14.09  1535.3      20   1.4
+ 3630312  0.2217965  0.00000040  16.37  1783.4      23   1.9
+ 3645000  0.2868246  0.00000032  12.71  1385.0      18   1.3
+ 3670016  0.2754934  0.00000035  13.32  1452.5      19   1.1
+ 3674160  0.2534546  0.00000035  14.50  1580.8      20   1.2
+ 3675000  0.2945485  0.00000033  12.48  1360.5      17   1.2
+ 3686400  0.2617065  0.00000033  14.09  1536.3      20   1.4
+ 3687936  0.2908122  0.00000035  12.68  1383.2      18   1.2
+ 3704400  0.2872314  0.00000032  12.90  1407.1      18   1.2
+ 3720087  0.4375000  0.00000035   8.50   928.0      12   1.5
+ 3732480  0.2869737  0.00000035  13.01  1419.8      18   1.4
+ 3750000  0.3023897  0.00000035  12.40  1354.1      17   1.2
+ 3750705  0.4237671  0.00000028   8.85   966.5      12   1.4
+ 3763200  0.2795139  0.00000034  13.46  1470.4      18   1.2
+ 3764768  0.2208093  0.00000040  17.05  1862.2      23   1.4
+ 3779136  0.2656635  0.00000037  14.23  1554.1      19   1.2
+ 3780000  0.3183441  0.00000034  11.87  1297.2      16   1.3
+ 3781575  0.4368286  0.00000024   8.66   945.8      12   1.9
+ 3796875  0.3924467  0.00000025   9.67  1057.3      13   1.4
+ 3810240  0.2616821  0.00000034  14.56  1591.6      20   1.2
+ 3827250  0.3526530  0.00000034  10.85  1186.6      15   1.3
+ 3828125  0.4538371  0.00000028   8.44   922.3      12   1.5
+ 3840000  0.2798530  0.00000035  13.72  1500.6      18   1.3
+ 3841600  0.3203278  0.00000034  11.99  1311.6      16   1.2
+ 3857868  0.3405762  0.00000039  11.33  1239.2      15   1.3
+ 3858750  0.3671352  0.00000034  10.51  1149.8      14   1.4
+ 3870720  0.2790799  0.00000034  13.87  1517.6      18   1.3
+ 3888000  0.2877468  0.00000033  13.51  1478.9      18   1.4
+ 3889620  0.3911884  0.00000027   9.94  1088.3      13   1.4
+ 3906250  0.3755406  0.00000039  10.40  1138.8      14   1.4
+ 3919104  0.2894830  0.00000038  13.54  1482.6      18   1.3
+ 3920000  0.3145142  0.00000034  12.46  1364.9      16   1.3
+ 3932160  0.2882080  0.00000033  13.64  1494.4      18   2.1
+ 3936600  0.2991728  0.00000035  13.16  1441.4      17   1.4
+ 3937500  0.3526042  0.00000033  11.17  1223.3      15   1.4
+ 3951360  0.2826335  0.00000035  13.98  1531.8      18   1.2
+ 3969000  0.2964154  0.00000033  13.39  1467.6      17   1.2
+ 3981312  0.2968750  0.00000034  13.41  1470.1      17   1.5
+ 4000000  0.2972915  0.00000036  13.45  1475.4      17   1.3
+ 4000752  0.2781847  0.00000037  14.38  1577.1      18   1.2
+ 4014080  0.2934028  0.00000034  13.68  1500.6      18   1.3
+ 4032000  0.3149567  0.00000035  12.80  1404.5      16   1.5
+ 4033680  0.2308461  0.00000038  17.47  1917.2      22   2.4
+ 4050000  0.2907986  0.00000034  13.93  1528.5      18   1.3
+ 4064256  0.3203125  0.00000037  12.69  1392.8      16   1.4
+ 4082400  0.2810194  0.00000033  14.53  1595.1      18   1.4
+ 4084101  0.4914995  0.00000029   8.31   912.4      11   1.8
+ 4096000  0.3106618  0.00000034  13.18  1448.1      17   1.4
+ 4100625  0.4686834  0.00000026   8.75   961.0      11   1.6
+ 4116000  0.3627930  0.00000034  11.35  1246.4      14   1.4
+ 4117715  0.4922097  0.00000025   8.37   919.1      11   1.7
+ 4128768  0.3092687  0.00000033  13.35  1467.0      17   1.4
+ 4133430  0.4134052  0.00000037  10.00  1098.8      13   1.5
+ 4134375  0.5046387  0.00000025   8.19   900.4      10   1.6
+ 4147200  0.3069853  0.00000033  13.51  1484.9      17   1.6
+ 4148928  0.4472860  0.00000028   9.28  1019.6      12   1.5
+ 4167450  0.4008414  0.00000033  10.40  1143.2      13   1.5
+ 4194304  0.3064970  0.00000034  13.68  1505.3      17   1.2
+ 4199040  0.3320312  0.00000036  12.65  1391.2      16   1.5
+ 4200000  0.3484375  0.00000035  12.05  1326.0      15   1.5
+ 4201750  0.2942437  0.00000038  14.28  1571.0      18   1.5
+ 4214784  0.3065114  0.00000035  13.75  1513.1      17   1.3
+ 4218750  0.4020621  0.00000035  10.49  1154.6      13   1.5
+ 4233600  0.3246613  0.00000035  13.04  1435.3      16   2.0
+ 4235364  0.2593262  0.00000040  16.33  1797.7      20   1.7
+ 4251528  0.3484701  0.00000039  12.20  1343.3      15   1.4
+ 4252500  0.4014423  0.00000033  10.59  1166.3      13   1.5
+ 4286520  0.3241577  0.00000036  13.22  1456.7      16   1.4
+ 4287500  0.3960712  0.00000034  10.83  1192.5      13   1.5
+ 4300800  0.3106761  0.00000033  13.84  1525.3      17   1.4
+ 4302592  0.2451521  0.00000039  17.55  1933.8      21   2.0
+ 4320000  0.3116096  0.00000034  13.86  1527.9      17   1.5
+ 4321800  0.4147010  0.00000031  10.42  1148.6      13   1.5
+ 4354560  0.3102022  0.00000035  14.04  1548.0      17   1.5
+ 4374000  0.3006089  0.00000033  14.55  1605.0      17   1.4
+ 4375000  0.3766218  0.00000036  11.62  1281.3      14   1.5
+ 4390400  0.3705532  0.00000033  11.85  1307.2      14   1.5
+ 4408992  0.3188171  0.00000038  13.83  1526.2      16   1.4
+ 4410000  0.3672049  0.00000033  12.01  1325.4      14   1.5
+ 4423680  0.3178406  0.00000033  13.92  1536.3      16   1.5
+ 4428675  0.5685764  0.00000030   7.79   859.9       9   1.8
+ 4445280  0.3144531  0.00000034  14.14  1560.9      16   1.4
+ 4465125  0.5274414  0.00000026   8.47   935.0      10   2.8
+ 4478976  0.3739014  0.00000037  11.98  1323.4      14   1.7
+ 4480000  0.3744245  0.00000034  11.97  1321.8      14   1.6
+ 4500000  0.4080717  0.00000036  11.03  1218.6      13   1.6
+ 4500846  0.4651101  0.00000038   9.68  1069.4      11   1.6
+ 4501875  0.5311035  0.00000024   8.48   936.7      10   1.8
+ 4515840  0.3526367  0.00000035  12.81  1415.5      15   1.5
+ 4536000  0.3852351  0.00000034  11.77  1301.9      13   1.7
+ 4537890  0.3541829  0.00000040  12.81  1416.6      15   2.2
+ 4556250  0.4524333  0.00000034  10.07  1113.8      12   1.6
+ 4572288  0.3505859  0.00000038  13.04  1442.7      15   1.5
+ 4587520  0.3329620  0.00000033  13.78  1524.5      16   1.5
+ 4592700  0.4602273  0.00000034   9.98  1104.2      11   1.8
+ 4593750  0.4289754  0.00000035  10.71  1185.0      12   1.6
+ 4608000  0.3500488  0.00000034  13.16  1457.0      15   1.8
+ 4609920  0.2782796  0.00000038  16.57  1833.5      18   3.9
+ 4630500  0.5133057  0.00000024   9.02   998.7      10   1.8
+ 4644864  0.3525879  0.00000036  13.17  1458.8      15   1.6
+ 4665600  0.3417643  0.00000034  13.65  1512.2      15   1.8
+ 4667544  0.3582938  0.00000037  13.03  1443.0      14   1.4
+ 4687500  0.4375000  0.00000037  10.71  1187.2      12   1.6
+ 4704000  0.4031889  0.00000033  11.67  1293.0      13   1.6
+ 4705960  0.2899170  0.00000038  16.23  1799.0      18   1.7
+ 4718592  0.3380696  0.00000034  13.96  1547.2      15   1.5
+ 4723920  0.3515625  0.00000037  13.44  1489.6      15   1.5
+ 4725000  0.4461263  0.00000032  10.59  1174.1      12   1.7
+ 4741632  0.3207703  0.00000036  14.78  1639.1      16   1.4
+ 4762800  0.3280945  0.00000034  14.52  1610.1      16   1.5
+ 4782969  0.6436462  0.00000036   7.43   824.5       8   2.0
+ 4800000  0.4166870  0.00000035  11.52  1278.3      12   1.8
+ 4802000  0.6336670  0.00000026   7.58   841.0       8   2.0
+ 4816896  0.3552246  0.00000034  13.56  1505.2      15   1.5
+ 4822335  0.6206597  0.00000030   7.77   862.5       9   2.0
+ 4838400  0.3257294  0.00000033  14.85  1649.3      16   1.7
+ 4840416  0.2833523  0.00000039  17.08  1896.7      18   2.8
+ 4860000  0.4558549  0.00000034  10.66  1184.1      11   1.9
+ 4862025  0.6757812  0.00000027   7.19   799.1       8   2.1
+ 4898880  0.3467611  0.00000034  14.13  1569.9      15   1.6
+ 4900000  0.4232992  0.00000034  11.58  1286.3      12   1.6
+ 4915200  0.3953764  0.00000033  12.43  1381.7      13   1.7
+ 4917248  0.3906062  0.00000034  12.59  1399.2      13   1.6
+ 4920750  0.5693088  0.00000034   8.64   960.7       9   1.9
+ 4921875  0.5886230  0.00000027   8.36   929.4       9   2.0
+ 4939200  0.4440104  0.00000034  11.12  1236.8      12   1.7
+ 4941258  0.3936298  0.00000040  12.55  1395.7      13   1.8
+ 4960116  0.5281982  0.00000040   9.39  1044.3      10   1.8
+ 4961250  0.5170898  0.00000034   9.59  1067.0      10   2.0
+ 4976640  0.4167074  0.00000035  11.94  1328.4      12   1.9
+ 5000000  0.4538574  0.00000039  11.02  1225.8      12   1.8
+ 5000940  0.5226074  0.00000036   9.57  1064.8      10   1.9
+ 5017600  0.4068322  0.00000034  12.33  1372.6      13   1.7
+ 5038848  0.3708147  0.00000039  13.59  1512.7      14   1.7
+ 5040000  0.4371745  0.00000033  11.53  1283.4      12   1.9
+ 5042100  0.2916667  0.00000038  17.29  1924.5      18   4.0
+ 5062500  0.4620028  0.00000033  10.96  1220.2      11   1.8
+ 5080320  0.3532552  0.00000035  14.38  1601.8      15   1.5
+ 5103000  0.3804409  0.00000034  13.41  1494.4      14   1.6
+ 5120000  0.3856671  0.00000035  13.28  1479.4      13   1.7
+ 5143824  0.3731864  0.00000038  13.78  1536.5      14   1.6
+ 5145000  0.4572088  0.00000032  11.25  1254.4      11   1.7
+ 5160960  0.3812779  0.00000033  13.54  1509.2      14   1.7
+ 5184000  0.3506511  0.00000033  14.78  1648.8      15   1.8
+ 5186160  0.3037684  0.00000038  17.07  1904.1      17  12.5
+ 5225472  0.3576823  0.00000037  14.61  1630.2      15   1.7
+ 5242880  0.3871695  0.00000033  13.54  1511.4      13   1.6
+ 5248800  0.3611886  0.00000033  14.53  1622.0      14   1.8
+ 5250000  0.4671520  0.00000034  11.24  1254.4      11   1.8
+ 5250987  0.7173549  0.00000031   7.32   817.1       7   2.2
+ 5268480  0.5859375  0.00000027   8.99  1003.9       9   2.0
+ 5292000  0.4975142  0.00000035  10.64  1187.9      11   1.9
+ 5294205  0.6298828  0.00000025   8.41   938.7       8   2.5
+ 5308416  0.3870192  0.00000034  13.72  1532.1      13   1.8
+ 5314410  0.6052517  0.00000038   8.78   980.8       9   2.0
+ 5315625  0.6139323  0.00000025   8.66   967.2       9   2.0
+ 5334336  0.5419922  0.00000036   9.84  1099.7      10   1.9
+ 5358150  0.5933160  0.00000035   9.03  1009.3       9   2.0
+ 5359375  0.6520996  0.00000026   8.22   918.6       8   2.1
+ 5376000  0.4327799  0.00000035  12.42  1388.7      12   1.8
+ 5378240  0.3154297  0.00000039  17.05  1906.1      16   4.3
+ 5400000  0.4744318  0.00000035  11.38  1272.8      11   2.0
+ 5402250  0.3984375  0.00000039  13.56  1516.2      13   4.7
+ 5419008  0.4187826  0.00000036  12.94  1447.3      12   1.7
+ 5443200  0.3973858  0.00000035  13.70  1532.5      13   1.9
+ 5445468  0.3501302  0.00000042  15.55  1740.1      15   3.8
+ 5467500  0.5831163  0.00000033   9.38  1049.3       9   2.1
+ 5468750  0.5281250  0.00000038  10.36  1158.9      10   1.9
+ 5488000  0.4884588  0.00000034  11.24  1257.7      11   1.8
+ 5505024  0.4050481  0.00000035  13.59  1521.7      13   1.7
+ 5511240  0.6464844  0.00000036   8.52   954.5       8   2.1
+ 5512500  0.5351562  0.00000033  10.30  1153.4      10   2.0
+ 5529600  0.4566761  0.00000033  12.11  1356.1      11   2.8
+ 5531904  0.3931791  0.00000037  14.07  1575.8      13   1.8
+ 5556600  0.5690104  0.00000034   9.77  1094.0       9   2.1
+ 5598720  0.3843471  0.00000036  14.57  1632.7      14   1.9
+ 5600000  0.5000000  0.00000035  11.20  1255.4      10   2.0
+ 5619712  0.4290365  0.00000035  13.10  1468.5      12   1.8
+ 5625000  0.5109375  0.00000036  11.01  1234.3      10   2.0
+ 5644800  0.3811384  0.00000034  14.81  1660.9      14   1.7
+ 5647152  0.3442708  0.00000039  16.40  1839.5      15   3.2
+ 5668704  0.6660156  0.00000039   8.51   954.7       8   2.3
+ 5670000  0.5039062  0.00000032  11.25  1262.2      10   2.0
+ 5715360  0.6464844  0.00000036   8.84   992.2       8   2.2
+ 5734400  0.4329427  0.00000033  13.25  1486.9      12   1.8
+ 5740875  0.7912946  0.00000027   7.26   814.5       7   2.5
+ 5760000  0.3930289  0.00000034  14.66  1645.6      13   1.9
+ 5762400  0.5616319  0.00000034  10.26  1152.1       9   2.0
+ 5764801  0.6962891  0.00000026   8.28   929.7       8   2.3
+ 5786802  0.6953125  0.00000040   8.32   934.8       8   2.2
+ 5788125  0.7021484  0.00000025   8.24   925.9       8   2.3
+ 5806080  0.4744318  0.00000036  12.24  1374.9      11   2.0
+ 5832000  0.5523437  0.00000034  10.56  1186.6      10   2.3
+ 5834430  0.4687500  0.00000041  12.45  1398.8      11   5.5
+ 5859375  0.6767578  0.00000032   8.66   973.3       8   2.2
+ 5878656  0.4552557  0.00000039  12.91  1451.9      11   2.0
+ 5880000  0.5304688  0.00000034  11.08  1246.3      10   2.0
+ 5882450  0.4199219  0.00000038  14.01  1575.1      12   2.2
+ 5898240  0.4420573  0.00000034  13.34  1500.5      12   1.9
+ 5904900  0.6835938  0.00000035   8.64   971.5       8   2.3
+ 5906250  0.5746528  0.00000035  10.28  1156.0       9   2.1
+ 5927040  0.4322917  0.00000036  13.71  1542.4      12   1.8
+ 5953500  0.6748047  0.00000033   8.82   992.8       8   2.3
+ 5971968  0.4786932  0.00000036  12.48  1404.1      11   2.1
+ 6000000  0.5382813  0.00000036  11.15  1254.9      10   2.1
+ 6001128  0.7060547  0.00000037   8.50   956.9       8   2.3
+ 6002500  0.5677083  0.00000033  10.57  1190.4       9   2.0
+ 6021120  0.4566761  0.00000034  13.18  1484.7      11   1.9
+ 6048000  0.4086539  0.00000034  14.80  1667.1      13   1.9
+ 6050520  0.3526042  0.00000039  17.16  1932.9      15   6.9
+ 6075000  0.5651042  0.00000033  10.75  1211.3       9   2.2
+ 6096384  0.4270833  0.00000037  14.27  1608.7      12   5.3
+ 6123600  0.5668403  0.00000035  10.80  1217.8       9   3.0
+ 6125000  0.5653212  0.00000035  10.83  1221.4       9   3.2
+ 6144000  0.4687500  0.00000034  13.11  1477.9      11   2.8
+ 6146560  0.3744420  0.00000038  16.42  1850.9      14   6.7
+ 6174000  0.5531250  0.00000033  11.16  1259.0      10   2.1
+ 6193152  0.4687500  0.00000035  13.21  1490.5      11   2.0
+ 6200145  0.9101562  0.00000032   6.81   768.5       6   2.7
+ 6220800  0.4251302  0.00000034  14.63  1651.2      12   2.2
+ 6223392  0.7455357  0.00000035   8.35   942.0       7   2.4
+ 6250000  0.5850694  0.00000038  10.68  1205.8       9   2.1
+ 6251175  0.9153646  0.00000028   6.83   770.9       6   2.7
+ 6272000  0.5720486  0.00000033  10.96  1237.9       9   2.2
+ 6291456  0.4744318  0.00000034  13.26  1497.5      11   2.0
+ 6298560  0.7466518  0.00000036   8.44   952.7       7   2.6
+ 6300000  0.6145833  0.00000036  10.25  1157.7       9   2.3
+ 6302625  0.7555804  0.00000024   8.34   942.1       7   3.0
+ 6322176  0.5234375  0.00000036  12.08  1364.4      10   2.0
+ 6328125  0.7321429  0.00000026   8.64   976.4       7   2.4
+ 6350400  0.6041667  0.00000035  10.51  1187.7       9   2.3
+ 6353046  0.5335938  0.00000041  11.91  1345.3      10   2.8
+ 6377292  0.8046875  0.00000041   7.93   895.7       7   2.6
+ 6378750  0.6582031  0.00000035   9.69  1095.3       8   2.3
+ 6400000  0.5296875  0.00000035  12.08  1365.9      10   2.1
+ 6422528  0.4794034  0.00000035  13.40  1514.8      11   2.0
+ 6429780  0.7700893  0.00000036   8.35   944.2       7   2.5
+ 6431250  0.6318359  0.00000034  10.18  1151.0       8   2.2
+ 6451200  0.5023438  0.00000034  12.84  1452.5      10   2.2
+ 6453888  0.3870192  0.00000040  16.68  1886.2      13   5.9
+ 6480000  0.4794034  0.00000035  13.52  1529.3      11   2.3
+ 6482700  0.7868304  0.00000025   8.24   932.2       7   2.5
+ 6531840  0.4545455  0.00000036  14.37  1626.6      11   2.1
+ 6553600  0.4886364  0.00000033  13.41  1518.5      11   2.1
+ 6561000  0.6494141  0.00000034  10.10  1143.9       8   2.4
+ 6562500  0.6171875  0.00000036  10.63  1204.0       9   2.2
+ 6585600  0.5946181  0.00000034  11.08  1254.3       9   2.8
+ 6588344  0.4238281  0.00000040  15.54  1760.6      12   6.4
+ 6613488  0.8802083  0.00000039   7.51   851.2       6   2.9
+ 6615000  0.6718750  0.00000033   9.85  1115.4       8   2.5
+ 6635520  0.5007812  0.00000034  13.25  1501.4      10   2.4
+ 6667920  0.8024554  0.00000026   8.31   941.8       7   2.8
+ 6718464  0.4801136  0.00000038  13.99  1586.8      11   2.3
+ 6720000  0.6076389  0.00000033  11.06  1254.1       9   2.3
+ 6722800  0.4375000  0.00000038  15.37  1742.6      12   4.1
+ 6750000  0.6076389  0.00000034  11.11  1260.1       9   2.5
+ 6751269  1.0437500  0.00000033   6.47   733.7       5   3.1
+ 6773760  0.4723011  0.00000035  14.34  1627.2      11   2.0
+ 6804000  0.8554688  0.00000035   7.95   902.6       6   2.9
+ 6806835  0.8125000  0.00000027   8.38   950.8       7   3.6
+ 6834375  0.9713542  0.00000025   7.04   798.7       6   3.0
+ 6858432  0.8314732  0.00000038   8.25   936.6       7   2.8
+ 6860000  0.6562500  0.00000033  10.45  1187.0       8   2.3
+ 6881280  0.5351562  0.00000034  12.86  1460.3      10   2.7
+ 6889050  0.9075521  0.00000036   7.59   862.2       6   2.9
+ 6890625  0.8346354  0.00000026   8.26   937.7       6   2.7
+ 6912000  0.5616319  0.00000034  12.31  1398.1       9   2.5
+ 6914880  0.7667411  0.00000027   9.02  1024.6       7   2.6
+ 6945750  0.9036458  0.00000032   7.69   873.5       6   2.8
+ 6967296  0.5737847  0.00000038  12.14  1380.1       9   2.4
+ 6998400  0.5335938  0.00000036  13.12  1491.2      10   2.5
+ 7000000  0.6953125  0.00000035  10.07  1144.6       8   2.5
+ 7001316  0.9270833  0.00000038   7.55   858.6       6   2.9
+ 7024640  0.5500000  0.00000035  12.77  1452.4      10   2.2
+ 7031250  0.7119141  0.00000038   9.88  1123.2       8   2.5
+ 7056000  0.5460938  0.00000034  12.92  1469.8      10   2.2
+ 7058940  0.4270833  0.00000039  16.53  1880.2      12   3.7
+ 7077888  0.5382813  0.00000034  13.15  1496.0      10   2.3
+ 7085880  0.8984375  0.00000037   7.89   897.4       6   2.9
+ 7087500  0.6845703  0.00000033  10.35  1178.0       8   2.5
+ 7112448  0.5156250  0.00000038  13.79  1569.9      10   3.4
+ 7144200  0.8984375  0.00000034   7.95   905.2       6   3.0
+ 7168000  0.5598958  0.00000034  12.80  1457.8       9   2.4
+ 7200000  0.5296875  0.00000036  13.59  1548.2      10   2.5
+ 7203000  0.4231771  0.00000038  17.02  1938.7      12   8.2
+ 7225344  0.5590278  0.00000035  12.92  1472.4       9   2.3
+ 7257600  0.5085937  0.00000034  14.27  1626.1      10   2.3
+ 7260624  0.4459635  0.00000040  16.28  1855.3      12   6.7
+ 7290000  0.6767578  0.00000032  10.77  1227.9       8   2.7
+ 7340032  0.5824653  0.00000035  12.60  1437.1       9   2.3
+ 7348320  0.9609375  0.00000036   7.65   872.1       6   3.2
+ 7350000  0.6992188  0.00000033  10.51  1198.8       8   2.6
+ 7372800  0.5616319  0.00000033  13.13  1497.4       9   2.5
+ 7375872  0.9804688  0.00000028   7.52   858.1       6   3.1
+ 7381125  1.1250000  0.00000028   6.56   748.5       5   3.3
+ 7408800  0.6796875  0.00000033  10.90  1243.8       8   2.5
+ 7411887  0.9257812  0.00000028   8.01   913.6       6   3.1
+ 7440174  1.0562500  0.00000041   7.04   804.0       5   3.2
+ 7441875  1.1843750  0.00000026   6.28   717.2       5   3.4
+ 7464960  0.6474609  0.00000036  11.53  1316.2       8   2.7
+ 7500000  0.7165179  0.00000036  10.47  1195.3       7   2.6
+ 7501410  1.0218750  0.00000037   7.34   838.3       5   3.2
+ 7503125  0.9713542  0.00000025   7.72   882.1       6   3.1
+ 7526400  0.6250000  0.00000035  12.04  1375.4       8   2.4
+ 7529536  0.4433594  0.00000041  16.98  1939.8      12   3.2
+ 7558272  0.6197917  0.00000040  12.19  1393.2       9   2.5
+ 7560000  0.6835938  0.00000032  11.06  1263.5       8   2.7
+ 7563150  0.5572917  0.00000039  13.57  1550.6       9   4.7
+ 7593750  0.7845982  0.00000035   9.68  1106.1       7   2.8
+ 7620480  0.5772569  0.00000037  13.20  1509.0       9   2.4
+ 7654500  0.9895833  0.00000034   7.74   884.4       6   3.2
+ 7656250  0.7935268  0.00000036   9.65  1103.2       7   3.6
+ 7680000  0.5972222  0.00000035  12.86  1470.7       9   2.7
+ 7683200  0.7466518  0.00000033  10.29  1176.9       7   3.9
+ 7715736  1.0359375  0.00000039   7.45   852.0       5   3.4
+ 7717500  0.7555804  0.00000034  10.21  1168.5       7   2.8
+ 7741440  0.6059028  0.00000035  12.78  1461.9       9   2.6
+ 7776000  0.5555556  0.00000034  14.00  1602.0       9   2.5
+ 7779240  0.4943182  0.00000040  15.74  1801.2      11  12.5
+ 7812500  0.7712054  0.00000041  10.13  1159.8       7   2.7
+ 7838208  0.5946181  0.00000039  13.18  1509.5       9   2.6
+ 7840000  0.7343750  0.00000034  10.68  1222.5       7   2.7
+ 7864320  0.5972222  0.00000034  13.17  1508.2       9   2.5
+ 7873200  0.7801339  0.00000036  10.09  1156.0       7   2.9
+ 7875000  0.7566964  0.00000034  10.41  1192.1       7   2.8
+ 7902720  0.5694444  0.00000036  13.88  1590.0       9   2.3
+ 7938000  0.7299107  0.00000033  10.88  1246.3       7   2.7
+ 7962624  0.6357422  0.00000036  12.52  1435.7       8   2.7
+ 7971615  1.2929688  0.00000033   6.17   706.7       4   3.7
+ 8000000  0.7433036  0.00000036  10.76  1234.0       7   2.8
+ 8001504  1.0921875  0.00000038   7.33   840.0       5   3.4
+ 8028160  0.6269531  0.00000034  12.81  1468.5       8   2.5
+ 8037225  1.2812500  0.00000028   6.27   719.5       4   3.8
+ 8064000  0.5781250  0.00000034  13.95  1600.1       9   2.5
+ 8067360  0.4928977  0.00000040  16.37  1877.6      11   8.6
+ 8100000  0.7500000  0.00000033  10.80  1239.3       7   3.0
+ 8103375  0.9414062  0.00000024   8.61   987.7       6   4.7
+ 8128512  0.7332589  0.00000037  11.09  1272.3       7   2.8
+ 8164800  1.0859375  0.00000034   7.52   863.2       5   3.6
+ 8168202  0.7801339  0.00000043  10.47  1202.1       7   7.6
+ 8192000  0.6484375  0.00000034  12.63  1450.7       8   2.7
+ 8201250  1.1531250  0.00000035   7.11   816.7       5   3.7
+ 8203125  1.0515625  0.00000030   7.80   895.8       5   3.5
+ 8232000  1.3671875  0.00000026   6.02   691.6       4   4.1
+ 8235430  0.5920139  0.00000039  13.91  1597.9       9   2.9
+ 8257536  0.6367188  0.00000034  12.97  1489.9       8   2.7
+ 8266860  1.1296875  0.00000038   7.32   840.8       5   3.5
+ 8268750  0.8593750  0.00000035   9.62  1105.5       6   3.0
+ 8294400  0.6660156  0.00000034  12.45  1431.2       8   3.0
+ 8297856  0.6572266  0.00000038  12.63  1450.9       8   2.5
+ 8334900  1.1359375  0.00000034   7.34   843.5       5   3.5
+ 8388608  0.6611328  0.00000035  12.69  1459.1       8   2.5
diff --git a/lib/astro.f90 b/lib/astro.f90
new file mode 100644
index 0000000..56711f3
--- /dev/null
+++ b/lib/astro.f90
@@ -0,0 +1,108 @@
+subroutine astro(nyear,month,nday,uth,nfreq,Mygrid,                    &
+          NStation,MoonDX,AzSun,ElSun,AzMoon0,ElMoon0,                 &
+          ntsky,doppler00,doppler,dbMoon,RAMoon,DecMoon,HA,Dgrd,sd,    &
+          poloffset,xnr,day,lon,lat,LST,techo)
+
+! Computes astronomical quantities for display and tracking.
+! NB: may want to smooth the Tsky map to 10 degrees or so.
+
+  character*6 MyGrid,HisGrid
+  real LST
+  real lat,lon
+  integer*2 nt144(180)
+
+!      common/echo/xdop(2),techo,AzMoon,ElMoon,mjd
+  real xdop(2)
+
+  data rad/57.2957795/
+  data nt144/                                             &
+       234, 246, 257, 267, 275, 280, 283, 286, 291, 298,  &
+       305, 313, 322, 331, 341, 351, 361, 369, 376, 381,  &
+       383, 382, 379, 374, 370, 366, 363, 361, 363, 368,  &
+       376, 388, 401, 415, 428, 440, 453, 467, 487, 512,  &
+       544, 579, 607, 618, 609, 588, 563, 539, 512, 482,  &
+       450, 422, 398, 379, 363, 349, 334, 319, 302, 282,  &
+       262, 242, 226, 213, 205, 200, 198, 197, 196, 197,  &
+       200, 202, 204, 205, 204, 203, 202, 201, 203, 206,  &
+       212, 218, 223, 227, 231, 236, 240, 243, 247, 257,  &
+       276, 301, 324, 339, 346, 344, 339, 331, 323, 316,  &
+       312, 310, 312, 317, 327, 341, 358, 375, 392, 407,  &
+       422, 437, 451, 466, 480, 494, 511, 530, 552, 579,  &
+       612, 653, 702, 768, 863,1008,1232,1557,1966,2385,  &
+      2719,2924,3018,3038,2986,2836,2570,2213,1823,1461,  &
+      1163, 939, 783, 677, 602, 543, 494, 452, 419, 392,  &
+       373, 360, 353, 350, 350, 350, 350, 350, 350, 348,  &
+       344, 337, 329, 319, 307, 295, 284, 276, 272, 272,  &
+       273, 274, 274, 271, 266, 260, 252, 245, 238, 231/
+  save
+
+  call grid2deg(MyGrid,elon,lat)
+  lon=-elon
+  call sun(nyear,month,nday,uth,lon,lat,RASun,DecSun,LST,      &
+       AzSun,ElSun,mjd,day)
+
+  freq=nfreq*1.e6
+  if(nfreq.eq.2) freq=1.8e6
+  if(nfreq.eq.4) freq=3.5e6
+
+  call MoonDop(nyear,month,nday,uth,lon,lat,RAMoon,DecMoon,    &
+       LST,HA,AzMoon,ElMoon,vr,dist)
+
+! Compute spatial polarization offset
+  xx=sin(lat/rad)*cos(ElMoon/rad) - cos(lat/rad)*              &
+       cos(AzMoon/rad)*sin(ElMoon/rad)
+  yy=cos(lat/rad)*sin(AzMoon/rad)
+  if(NStation.eq.1) poloffset1=rad*atan2(yy,xx)
+  if(NStation.eq.2) poloffset2=rad*atan2(yy,xx)
+
+  techo=2.0 * dist/2.99792458e5                 !Echo delay time
+  doppler=-freq*vr/2.99792458e5                 !One-way Doppler
+
+  call coord(0.,0.,-1.570796,1.161639,RAMoon/rad,DecMoon/rad,el,eb)
+  longecl_half=nint(rad*el/2.0)
+  if(longecl_half.lt.1 .or. longecl_half.gt.180) longecl_half=180
+  t144=nt144(longecl_half)
+  tsky=(t144-2.7)*(144.0/nfreq)**2.6 + 2.7      !Tsky for obs freq
+
+  xdop(NStation)=doppler
+  if(NStation.eq.2) then
+     HisGrid=MyGrid
+     go to 900
+  endif
+
+  doppler00=2.0*xdop(1)
+  doppler=xdop(1)+xdop(2)
+!      if(mode.eq.3) doppler=2.0*xdop(1)
+  dBMoon=-40.0*log10(dist/356903.)
+  sd=16.23*370152.0/dist
+
+!      if(NStation.eq.1 .and. MoonDX.ne.0 .and. 
+!     +    (mode.eq.2 .or. mode.eq.5)) then
+  if(NStation.eq.1 .and. MoonDX.ne.0) then
+     poloffset=mod(poloffset2-poloffset1+720.0,180.0)
+     if(poloffset.gt.90.0) poloffset=poloffset-180.0
+     x1=abs(cos(2*poloffset/rad))
+     if(x1.lt.0.056234) x1=0.056234
+     xnr=-20.0*log10(x1)
+     if(HisGrid(1:1).lt.'A' .or. HisGrid(1:1).gt.'R') xnr=0
+  endif
+
+  tr=80.0                              !Good preamp
+  tskymin=13.0*(408.0/nfreq)**2.6      !Cold sky temperature
+  tsysmin=tskymin+tr
+  tsys=tsky+tr
+  dgrd=-10.0*log10(tsys/tsysmin) + dbMoon
+900 AzMoon0=Azmoon
+  ElMoon0=Elmoon
+  ntsky=nint(tsky)
+
+!      auxHA = 15.0*(LST-auxra)                       !HA in degrees
+!      pi=3.14159265
+!      pio2=0.5*pi
+!      call coord(pi,pio2-lat/rad,0.0,lat/rad,auxha*pi/180.0,
+!     +  auxdec/rad,azaux,elaux)
+!      AzAux=azaux*rad
+!      ElAux=ElAux*rad
+
+  return
+end subroutine astro
diff --git a/lib/astro0.f90 b/lib/astro0.f90
new file mode 100644
index 0000000..fe047d4
--- /dev/null
+++ b/lib/astro0.f90
@@ -0,0 +1,82 @@
+subroutine astro0(nyear,month,nday,uth8,nfreq,mygrid,hisgrid,              &
+     AzSun8,ElSun8,AzMoon8,ElMoon8,AzMoonB8,ElMoonB8,ntsky,ndop,ndop00,    &
+     dbMoon8,RAMoon8,DecMoon8,HA8,Dgrd8,sd8,poloffset8,xnr8,dfdt,dfdt0,    &
+     width1,width2,w501,w502,xlst8,techo8)
+
+  parameter (DEGS=57.2957795130823d0)
+  character*6 mygrid,hisgrid
+  real*8 AzSun8,ElSun8,AzMoon8,ElMoon8,AzMoonB8,ElMoonB8
+  real*8 dbMoon8,RAMoon8,DecMoon8,HA8,Dgrd8,xnr8,dfdt,dfdt0,dt
+  real*8 sd8,poloffset8,day8,width1,width2,w501,w502,xlst8
+  real*8 uth8,techo8
+  data uth8z/0.d0/
+  save
+
+  uth=uth8
+  call astro(nyear,month,nday,uth,nfreq,hisgrid,2,1,                 &
+       AzSun,ElSun,AzMoon,ElMoon,ntsky,doppler00,doppler,            &
+       dbMoon,RAMoon,DecMoon,HA,Dgrd,sd,poloffset,xnr,               &
+       day,xlon2,xlat2,xlst,techo)
+  AzMoonB8=AzMoon
+  ElMoonB8=ElMoon
+  call astro(nyear,month,nday,uth,nfreq,mygrid,1,1,                  &
+       AzSun,ElSun,AzMoon,ElMoon,ntsky,doppler00,doppler,            &
+       dbMoon,RAMoon,DecMoon,HA,Dgrd,sd,poloffset,xnr,               &
+       day,xlon1,xlat1,xlst,techo)
+
+  day8=day
+  xlst8=xlst
+  techo8=techo
+  call tm2(day8,xlat1,xlon1,xl1,b1)
+  call tm2(day8,xlat2,xlon2,xl2,b2)
+  call tm2(day8+1.d0/1440.0,xlat1,xlon1,xl1a,b1a)
+  call tm2(day8+1.d0/1440.0,xlat2,xlon2,xl2a,b2a)
+  fghz=0.001*nfreq
+  dldt1=DEGS*(xl1a-xl1)
+  dbdt1=DEGS*(b1a-b1)
+  dldt2=DEGS*(xl2a-xl2)
+  dbdt2=DEGS*(b2a-b2)
+  rate1=2.0*sqrt(dldt1**2 + dbdt1**2)
+  width1=0.5*6741*fghz*rate1
+  rate2=sqrt((dldt1+dldt2)**2 + (dbdt1+dbdt2)**2)
+  width2=0.5*6741*fghz*rate2
+
+  fbend=0.7
+  a2=0.0045*log(fghz/fbend)/log(1.05)
+  if(fghz.lt.fbend) a2=0.0
+  f50=0.19 * (fghz/fbend)**a2
+  if(f50.gt.1.0) f50=1.0
+  w501=f50*width1
+  w502=f50*width2
+
+  AzSun8=AzSun
+  ElSun8=ElSun
+  AzMoon8=AzMoon
+  ElMoon8=ElMoon
+  dbMoon8=dbMoon
+  RAMoon8=RAMoon/15.0
+  DecMoon8=DecMoon
+  HA8=HA
+  Dgrd8=Dgrd
+  sd8=sd
+  poloffset8=poloffset
+  xnr8=xnr
+  ndop=nint(doppler)
+  ndop00=nint(doppler00)
+
+  if(uth8z.eq.0.d0) then
+     uth8z=uth8-1.d0/3600.d0
+     dopplerz=doppler
+     doppler00z=doppler00
+  endif
+     
+  dt=60.0*(uth8-uth8z)
+  if(dt.le.0) dt=1.d0/60.d0
+  dfdt=(doppler-dopplerz)/dt
+  dfdt0=(doppler00-doppler00z)/dt
+  uth8z=uth8
+  dopplerz=doppler
+  doppler00z=doppler00
+
+  return
+end subroutine astro0
diff --git a/lib/astrosub.f90 b/lib/astrosub.f90
new file mode 100644
index 0000000..9dccd29
--- /dev/null
+++ b/lib/astrosub.f90
@@ -0,0 +1,14 @@
+subroutine astrosub(nyear,month,nday,uth8,nfreq,mygrid,hisgrid,          &
+     AzSun8,ElSun8,AzMoon8,ElMoon8,AzMoonB8,ElMoonB8,ntsky,ndop,ndop00,  &
+     RAMoon8,DecMoon8,Dgrd8,poloffset8,xnr8,techo8)
+
+  implicit real*8 (a-h,o-z)
+  character*6 mygrid,hisgrid
+
+  call astro0(nyear,month,nday,uth8,nfreq,mygrid,hisgrid,                &
+     AzSun8,ElSun8,AzMoon8,ElMoon8,AzMoonB8,ElMoonB8,ntsky,ndop,ndop00,  &
+     dbMoon8,RAMoon8,DecMoon8,HA8,Dgrd8,sd8,poloffset8,xnr8,dfdt,dfdt0,  &
+     width1,width2,w501,w502,xlst8,techo8)
+
+  return  
+end subroutine astrosub
diff --git a/lib/baddata.f90 b/lib/baddata.f90
new file mode 100644
index 0000000..edacc1d
--- /dev/null
+++ b/lib/baddata.f90
@@ -0,0 +1,27 @@
+logical function baddata(id2,nz)
+
+  integer*2 id2(nz)
+
+  nadd=1200
+  j=0
+  smin=1.e30
+  smax=-smin
+  iz=49*12000/nadd
+  do i=1,iz
+     sq=0.
+     do n=1,nadd
+        j=j+1
+        x=id2(j)
+        sq=sq + x*x
+     enddo
+     rms=sqrt(sq/nadd)
+     smin=min(smin,rms)
+     smax=max(smax,rms)
+  enddo
+
+  sratio=smax/(smin+1.e-30)
+  baddata=.false.
+  if(sratio.gt.1.e30) baddata=.true.
+
+  return
+end function baddata
diff --git a/lib/chkfft.f90 b/lib/chkfft.f90
new file mode 100644
index 0000000..84208a9
--- /dev/null
+++ b/lib/chkfft.f90
@@ -0,0 +1,162 @@
+program chkfft
+
+! Tests and times one-dimensional FFTs computed by four2a().
+! An all-Fortran version of four2a() is available, but the preferred
+! version uses calls to the FFTW library.
+
+  parameter (NMAX=8*1024*1024)            !Maximum FFT length
+  complex a(NMAX),b(NMAX)
+  real ar(NMAX),br(NMAX)
+  real mflops
+  character infile*12,arg*8
+  logical list
+  common/patience/npatience
+  equivalence (a,ar),(b,br)
+
+  nargs=iargc()
+  if(nargs.ne.5) then
+     print*,'Usage: chkfft <nfft | infile> nr nw nc np'
+     print*,'       nfft:   length of FFT'
+     print*,'       nfft=0: do lengths 2^n, n=2^4 to 2^23'
+     print*,'       infile: name of file with nfft values, one per line'
+     print*,'       nr:     0/1 to not read (or read) wisdom'
+     print*,'       nw:     0/1 to not write (or write) wisdom'
+     print*,'       nc:     0/1 for real or complex data'
+     print*,'       np:     0-4 patience for finding best algorithm'
+     go to 999
+  endif
+
+  list=.false.
+  nfft=-1
+  call getarg(1,infile)
+  open(10,file=infile,status='old',err=1)
+  list=.true.                          !A valid file name was provided
+  go to 2
+1 read(infile,*) nfft                  !Takje first argument to be nfft
+2  call getarg(2,arg)
+  read(arg,*) nr
+  call getarg(3,arg)
+  read(arg,*) nw
+  call getarg(4,arg)
+  read(arg,*) ncomplex
+  call getarg(5,arg)
+  read(arg,*) npatience
+
+  if(list) write(*,1000) infile,nr,nw,ncomplex,npatience
+1000 format(/'infile: ',a12,'   nr:',i2,'   nw',i2,'   nc:',i2,'   np:',i2/)
+  if(.not.list) write(*,1002) nfft,nr,nw,ncomplex,npatience
+1002 format(/'nfft: ',i10,'   nr:',i2,'   nw',i2,'   nc:',i2,'   np:',i2/)
+
+  open(12,file='chkfft.out',status='unknown')
+  open(13,file='fftwf_wisdom.dat',status='unknown')
+
+  if(nr.ne.0) then
+     call import_wisdom_from_file(isuccess,13)
+     if(isuccess.eq.0) then
+        write(*,1010) 
+1010    format('Failed to import FFTW wisdom.')
+        go to 999
+     endif
+  endif
+
+  idum=-1                               !Set random seed
+  ndim=1				!One-dimensional transforms
+  do i=1,NMAX                           !Set random data
+     x=gran()
+     y=gran()
+     b(i)=cmplx(x,y)                    !Generate random data
+  enddo
+
+  iters=1000000
+  if(list .or. (nfft.gt.0)) then
+     n1=1
+     n2=1
+     if(nfft.eq.-1) n2=999999
+     write(*,1020) 
+1020 format('    NFFT     Time        rms      MHz   MFlops  iters',    &
+          '  tplan'/61('-'))
+  else
+     n1=4
+     n2=23
+     write(*,1030) 
+1030 format(' n   N=2^n     Time        rms      MHz   MFlops  iters',  &
+          '  tplan'/63('-'))
+  endif
+
+  do ii=n1,n2                           !Test one or more FFT lengths
+     if(list) then
+        read(10,*,end=900) nfft         !Read nfft from file
+     else if(n2.gt.n1) then
+        nfft=2**ii                      !Do powers of 2
+     endif
+
+     iformf=1
+     iformb=1
+     if(ncomplex.eq.0) then
+        iformf=0                        !Real-to-complex transform
+        iformb=-1                       !Complex-to-real (inverse) transform
+     endif
+
+     if(nfft.gt.NMAX) go to 900
+     a(1:nfft)=b(1:nfft)                !Copy test data into a()
+     t0=second()
+     call four2a(a,nfft,ndim,-1,iformf) !Get planning time for forward FFT
+     call four2a(a,nfft,ndim,+1,iformb) !Get planning time for backward FFT
+     t2=second()
+     tplan=t2-t0                        !Total planning time for this length
+     
+     total=0.
+     do iter=1,iters                    !Now do many iterations
+        a(1:nfft)=b(1:nfft)             !Copy test data into a()
+
+        t0=second()
+        call four2a(a,nfft,ndim,-1,iformf) !Forward FFT
+        call four2a(a,nfft,ndim,+1,iformb) !Backward FFT on same data
+        t1=second()
+        total=total+t1-t0
+        if(total.ge.1.0) go to 40       !Cut iterations short if t>1 s
+     enddo
+     iter=iters
+
+40   time=0.5*total/iter                !Time for one FFT of current length
+     tplan=0.5*tplan-time               !Planning time for one FFT
+     if(tplan.lt.0) tplan=0.
+     a(1:nfft)=a(1:nfft)/nfft
+
+! Compute RMS difference between original array and back-transformed array.
+     sq=0.
+     if(ncomplex.eq.1) then
+        do i=1,nfft
+           sq=sq + real(a(i)-b(i))**2 + imag(a(i)-b(i))**2
+        enddo
+     else
+        do i=1,nfft
+           sq=sq + (ar(i)-br(i))**2
+        enddo
+     endif
+     rms=sqrt(sq/nfft)
+
+     freq=1.e-6*nfft/time
+     mflops=5.0/(1.e6*time/(nfft*log(float(nfft))/log(2.0)))
+     if(n2.eq.1 .or. n2.eq.999999) then
+        write(*,1050) nfft,time,rms,freq,mflops,iter,tplan
+        write(12,1050) nfft,time,rms,freq,mflops,iter,tplan
+1050    format(i8,f11.7,f12.8,f7.2,f8.1,i8,f6.1)
+     else
+        write(*,1060) ii,nfft,time,rms,freq,mflops,iter,tplan
+        write(12,1060) ii,nfft,time,rms,freq,mflops,iter,tplan
+1060    format(i2,i8,f11.7,f12.8,f7.2,f8.1,i8,f6.1)
+     endif
+     if(mod(ii,50).eq.0) call four2a(0,-1,0,0,0)
+  enddo
+
+900  continue 
+  if(nw.eq.1) then
+     rewind 13
+     call export_wisdom_to_file(13)
+!     write(*,1070) 
+!1070 format(/'Exported FFTW wisdom')
+  endif
+
+999 call four2a(0,-1,0,0,0)
+end program chkfft
diff --git a/lib/chkfft.txt b/lib/chkfft.txt
new file mode 100644
index 0000000..970d7a7
--- /dev/null
+++ b/lib/chkfft.txt
@@ -0,0 +1,124 @@
+		Brief Description of chkfft, by K1JT
+		------------------------------------
+
+Discrete Fourier transforms (DFTs) are found at the root of most
+digital signal processing tasks. In WSJT and its sister programs the
+transforms are done using the FFTW library, and subroutine four2
+provides a convenient interface to the library.  Program chkfft is a
+command-line utility offering a convenient way to test FFT execution
+times under a variety of circumstances.
+
+To compile chkfft in Linux:
+
+$ gfortran -o chkfft chkfft.f90 four2a.f90 f77_wisdom.f90 gran.c -lfftw3f
+
+To compile chkfft in Windows (you may need to customize the hard-coded
+path shown here for libfftw3f-3.dll):
+
+> gfortran -o chkfft chkfft.f90 four2a.f90 f77_wisdom.f90 gran.c \
+  /JTSDK-QT/appsupport/runtime/libfftw3f-3.dll
+
+To see a brief usage message, type chkfft at the command prompt:
+ 
+$ chkfft
+ Usage: chkfft <nfft | infile> nr nw nc np
+        nfft:   length of FFT
+        nfft=0: do lengths 2^n, n=2^4 to 2^23
+        infile: name of file with nfft values, one per line
+        nr:     0/1 to not read (or read) wisdom
+        nw:     0/1 to not write (or write) wisdom
+        nc:     0/1 for real or complex data
+        np:     0-4 patience for finding best algorithm
+
+As an example, to measure the speed of a complex DFT of length 131072:
+
+#######################################################################
+$ chkfft 131072 0 1 1 2
+
+nfft:     131072   nr: 0   nw 1   nc: 1   np: 2
+
+    NFFT     Time        rms      MHz   MFlops  iters  tplan
+-------------------------------------------------------------
+  131072  0.0021948  0.00000032  59.72  5076.1     231   2.9
+#######################################################################
+
+Program output shows that on the test machine the average time for one
+forward (or inverse) transform of length N=131072 is about 2.2 ms,
+corresponding to slightly over 5 GFlops computing speed.  The planning
+time in FFTW was 2.9 s.
+
+Running the command again with parameter nr=1 will use the 
+"wisdom" already accumulated for complex N=131072 FFTs.  The execution
+speed will be essentially the same, but no planning time is required:  
+
+#######################################################################
+$ chkfft 131072 1 1 1 2
+
+nfft:     131072   nr: 1   nw 1   nc: 1   np: 2
+
+    NFFT     Time        rms      MHz   MFlops  iters  tplan
+-------------------------------------------------------------
+  131072  0.0021575  0.00000032  60.75  5164.0     235   0.0
+#######################################################################
+
+Optimized algorithms can compute DFTs much faster for lengths that are
+the product of small integers.  Length N=131072 = 2^17 is a good
+example, and FFTs should be very efficient.  For comparison, look at
+the speed for N=131071, a prime number.  The average time is now about
+7 times larger:
+
+#######################################################################
+C:\JTSDK-QT\src\wsjtx\lib>chkfft 131071 1 1 1 2
+
+nfft:     131071   nr: 1   nw 1   nc: 1   np: 2
+
+    NFFT     Time        rms      MHz   MFlops  iters  tplan
+-------------------------------------------------------------
+  131071  0.0153637  0.00000065   8.53   725.2      33   5.6
+#######################################################################
+
+Here's an example that measures execution times for all integral
+power-of-2 lengths from 2^4 to 2^23:
+
+#######################################################################
+$ chkfft 0 1 1 1 2
+
+nfft:          0   nr: 1   nw 1   nc: 1   np: 2
+
+  n   N=2^n    Time        rms      MHz   MFlops  iters  tplan
+---------------------------------------------------------------
+ 4      16  0.0000003  0.00000014  58.61  1172.2 1000000   0.0
+ 5      32  0.0000004  0.00000016  89.19  2229.6 1000000   0.0
+ 6      64  0.0000006  0.00000016 109.44  3283.2  866975   0.0
+ 7     128  0.0000009  0.00000021 135.92  4757.1  538369   0.0
+ 8     256  0.0000016  0.00000020 158.40  6335.8  313701   0.0
+ 9     512  0.0000032  0.00000021 162.53  7313.8  160943   0.1
+10    1024  0.0000067  0.00000023 152.53  7626.5   75521   0.1
+11    2048  0.0000136  0.00000025 150.42  8273.3   37239   0.2
+12    4096  0.0000316  0.00000027 129.75  7784.8   16060   0.3
+13    8192  0.0000720  0.00000026 113.75  7393.8    7040   0.5
+14   16384  0.0001620  0.00000028 101.11  7078.0    3129   0.9
+15   32768  0.0003227  0.00000030 101.53  7615.1    1571   1.7
+16   65536  0.0010020  0.00000030  65.41  5232.5     506   4.1
+17  131072  0.0021575  0.00000032  60.75  5164.0     235   0.0
+18  262144  0.0053937  0.00000032  48.60  4374.2      94   3.6
+19  524288  0.0190668  0.00000034  27.50  2612.2      27   6.8
+20 1048576  0.0468001  0.00000035  22.41  2240.5      11   2.4
+21 2097152  0.0936012  0.00000036  22.41  2352.5       6  31.6
+22 4194304  0.1949997  0.00000037  21.51  2366.0       3   9.8
+23 8388608  0.4212036  0.00000038  19.92  2290.3       2 112.9
+#######################################################################
+
+Test data for all transforms is gaussian random noise of zero mean and
+standard deviation 1.  Tabulated values of "rms" are the
+root-mean-square differences between the original data and the
+back-transfmred data.
+
+File nfft.dat contains all numbers between 2^3 and 2^23 with no factor
+greater than 7, followed by their factors.  These numbers are good
+choices for FFT lengths.  File all_fft.out gives the result on one
+machine of running the command 
+
+$ chkfft nfft.dat 0 1 1 2
+
+Take note: this task may take as much as 24 hours, or even more!
diff --git a/lib/chkfft2.f90 b/lib/chkfft2.f90
new file mode 100644
index 0000000..9effd4c
--- /dev/null
+++ b/lib/chkfft2.f90
@@ -0,0 +1,187 @@
+program chkfft
+
+! Tests and times one-dimensional FFTs computed by FFTW3
+  use FFTW3
+  parameter (NMAX=8*1024*1024)           !Maximum FFT length
+  complex a(NMAX),b(NMAX),c(NMAX)
+  real ar(NMAX),br(NMAX),cr(NMAX)
+  real mflops
+  integer*8 plan1,plan2                  !Pointers to stored plans
+  character infile*12,arg*8
+  logical list
+  common/patience/npatience
+  equivalence (a,ar),(b,br),(c,cr)
+!  include 'fftw3.f90'                    !FFTW definitions
+
+  nargs=iargc()
+  if(nargs.ne.6) then
+     print*,'Usage: chkfft <nfft | infile> nr nw nc np inplace'
+     print*,'       nfft:    length of FFT'
+     print*,'       nfft=0:  do lengths 2^n, n=2^4 to 2^23'
+     print*,'       infile:  name of file with nfft values, one per line'
+     print*,'       nr:      0/1 to not read (or read) wisdom'
+     print*,'       nw:      0/1 to not write (or write) wisdom'
+     print*,'       nc:      0/1 for real or complex data'
+     print*,'       np:      0-4 patience for finding best algorithm'
+     print*,'       inplace: 1 for inplace, 0 otherwise'
+     go to 999
+  endif
+
+  list=.false.
+  nfft=-1
+  call getarg(1,infile)
+  open(10,file=infile,status='old',err=1)
+  list=.true.                          !A valid file name was provided
+  go to 2
+1 read(infile,*) nfft                  !Take first argument to be nfft
+2  call getarg(2,arg)
+  read(arg,*) nr
+  call getarg(3,arg)
+  read(arg,*) nw
+  call getarg(4,arg)
+  read(arg,*) ncomplex
+  call getarg(5,arg)
+  read(arg,*) npatience
+  call getarg(6,arg)
+  read(arg,*) inplace
+
+  if(list) write(*,1000) infile,nr,nw,ncomplex,npatience
+1000 format(/'infile: ',a12,'   nr:',i2,'   nw',i2,'   nc:',i2,'   np:',i2/)
+  if(.not.list) write(*,1002) nfft,nr,nw,ncomplex,npatience
+1002 format(/'nfft: ',i10,'   nr:',i2,'   nw',i2,'   nc:',i2,'   np:',i2/)
+
+  nflags=FFTW_ESTIMATE
+  if(npatience.eq.1) nflags=FFTW_ESTIMATE_PATIENT
+  if(npatience.eq.2) nflags=FFTW_MEASURE
+  if(npatience.eq.3) nflags=FFTW_PATIENT
+  if(npatience.eq.4) nflags=FFTW_EXHAUSTIVE
+
+  open(12,file='chkfft.out',status='unknown')
+  open(13,file='fftwf_wisdom.dat',status='unknown')
+
+  if(nr.ne.0) then
+     call import_wisdom_from_file(isuccess,13)
+     if(isuccess.eq.0) then
+        write(*,1010) 
+1010    format('Failed to import FFTW wisdom.')
+        go to 999
+     endif
+  endif
+
+  idum=-1                               !Set random seed
+  ndim=1				!One-dimensional transforms
+  do i=1,NMAX                           !Set random data
+     x=gran()
+     y=gran()
+     b(i)=cmplx(x,y)                    !Generate random data
+  enddo
+
+  iters=1000000
+  if(list .or. (nfft.gt.0)) then
+     n1=1
+     n2=1
+     if(nfft.eq.-1) n2=999999
+     write(*,1020) 
+1020 format('    NFFT     Time        rms      MHz   MFlops  iters',    &
+          '  tplan'/61('-'))
+  else
+     n1=4
+     n2=23
+     write(*,1030) 
+1030 format(' n   N=2^n     Time        rms      MHz   MFlops  iters',  &
+          '  tplan'/63('-'))
+  endif
+
+  do ii=n1,n2                           !Test one or more FFT lengths
+     if(list) then
+        read(10,*,end=900) nfft         !Read nfft from file
+     else if(n2.gt.n1) then
+        nfft=2**ii                      !Do powers of 2
+     endif
+
+     iformf=1
+     iformb=1
+     if(ncomplex.eq.0) then
+        iformf=0                        !Real-to-complex transform
+        iformb=-1                       !Complex-to-real (inverse) transform
+     endif
+
+     if(nfft.gt.NMAX) go to 900
+     a(1:nfft)=b(1:nfft)                !Copy test data into a()
+     t0=second()
+     if(inplace.ne.0) then
+        if(ncomplex.ne.0) then
+           call sfftw_plan_dft_1d(plan1,nfft,a,a,FFTW_FORWARD,nflags)
+           call sfftw_plan_dft_1d(plan2,nfft,a,a,FFTW_BACKWARD,nflags)
+        else
+           call sfftw_plan_dft_r2c_1d(plan1,nfft,a,a,nflags)
+           call sfftw_plan_dft_c2r_1d(plan2,nfft,a,a,nflags)
+        endif
+     else
+        if(ncomplex.ne.0) then
+           call sfftw_plan_dft_1d(plan1,nfft,a,c,FFTW_FORWARD,nflags)
+           call sfftw_plan_dft_1d(plan2,nfft,c,a,FFTW_BACKWARD,nflags)
+        else
+           call sfftw_plan_dft_r2c_1d(plan1,nfft,a,c,nflags)
+           call sfftw_plan_dft_c2r_1d(plan2,nfft,c,a,nflags)
+        endif
+     endif
+
+     t2=second()
+     tplan=t2-t0                        !Total planning time for this length
+     
+     total=0.
+     do iter=1,iters                    !Now do many iterations
+        a(1:nfft)=b(1:nfft)             !Copy test data into a()
+        t0=second()
+        call sfftw_execute(plan1)
+        call sfftw_execute(plan2)
+        t1=second()
+        total=total+t1-t0
+        if(total.ge.1.0) go to 40       !Cut iterations short if t>1 s
+     enddo
+     iter=iters
+
+40   time=0.5*total/iter                !Time for one FFT of current length
+     tplan=0.5*tplan-time               !Planning time for one FFT
+     if(tplan.lt.0) tplan=0.
+     a(1:nfft)=a(1:nfft)/nfft
+
+! Compute RMS difference between original array and back-transformed array.
+     sq=0.
+     if(ncomplex.eq.1) then
+        do i=1,nfft
+           sq=sq + real(a(i)-b(i))**2 + imag(a(i)-b(i))**2
+        enddo
+     else
+        do i=1,nfft
+           sq=sq + (ar(i)-br(i))**2
+        enddo
+     endif
+     rms=sqrt(sq/nfft)
+
+     freq=1.e-6*nfft/time
+     mflops=5.0/(1.e6*time/(nfft*log(float(nfft))/log(2.0)))
+     if(n2.eq.1 .or. n2.eq.999999) then
+        write(*,1050) nfft,time,rms,freq,mflops,iter,tplan
+        write(12,1050) nfft,time,rms,freq,mflops,iter,tplan
+1050    format(i8,f11.7,f12.8,f7.2,f8.1,i8,f6.1)
+     else
+        write(*,1060) ii,nfft,time,rms,freq,mflops,iter,tplan
+        write(12,1060) ii,nfft,time,rms,freq,mflops,iter,tplan
+1060    format(i2,i8,f11.7,f12.8,f7.2,f8.1,i8,f6.1)
+     endif
+  enddo
+
+900  continue 
+  if(nw.eq.1) then
+     rewind 13
+     call export_wisdom_to_file(13)
+!     write(*,1070) 
+!1070 format(/'Exported FFTW wisdom')
+  endif
+
+  call sfftw_destroy_plan(plan1)
+  call sfftw_destroy_plan(plan2)
+
+999 end program chkfft
diff --git a/lib/chkfft3.f90 b/lib/chkfft3.f90
new file mode 100644
index 0000000..d42203a
--- /dev/null
+++ b/lib/chkfft3.f90
@@ -0,0 +1,176 @@
+program chkfft
+
+! Tests and times one-dimensional FFTs computed by FFTW3
+  use, intrinsic :: iso_c_binding
+  use FFTW3
+  parameter (NMAX=8*1024*1024)           !Maximum FFT length
+  complex a(NMAX),b(NMAX),c(NMAX)
+  real ar(NMAX),br(NMAX),cr(NMAX)
+  real mflops
+!  integer*8 plan1,plan2                  !Pointers to stored plans
+  type(C_PTR) :: plan1,plan2              !Pointers to FFTW plans
+  character infile*12,arg*8
+  logical list
+  common/patience/npatience
+  equivalence (a,ar),(b,br),(c,cr)
+!  include 'fftw3.f90'                    !FFTW definitions
+
+  nargs=iargc()
+  if(nargs.ne.5) then
+     print*,'Usage: chkfft3 <nfft | infile> nr nw nc np'
+     print*,'       nfft:    length of FFT'
+     print*,'       nfft=0:  do lengths 2^n, n=2^4 to 2^23'
+     print*,'       infile:  name of file with nfft values, one per line'
+     print*,'       nr:      0/1 to not read (or read) wisdom'
+     print*,'       nw:      0/1 to not write (or write) wisdom'
+     print*,'       nc:      0/1 for real or complex data'
+     print*,'       np:      0-4 patience for finding best algorithm'
+     go to 999
+  endif
+
+  list=.false.
+  nfft=-1
+  call getarg(1,infile)
+  open(10,file=infile,status='old',err=1)
+  list=.true.                          !A valid file name was provided
+  go to 2
+1 read(infile,*) nfft                  !Take first argument to be nfft
+2  call getarg(2,arg)
+  read(arg,*) nr
+  call getarg(3,arg)
+  read(arg,*) nw
+  call getarg(4,arg)
+  read(arg,*) ncomplex
+  call getarg(5,arg)
+  read(arg,*) npatience
+
+  if(list) write(*,1000) infile,nr,nw,ncomplex,npatience
+1000 format(/'infile: ',a12,'   nr:',i2,'   nw',i2,'   nc:',i2,'   np:',i2/)
+  if(.not.list) write(*,1002) nfft,nr,nw,ncomplex,npatience
+1002 format(/'nfft: ',i10,'   nr:',i2,'   nw',i2,'   nc:',i2,'   np:',i2/)
+
+  nflags=FFTW_ESTIMATE
+  if(npatience.eq.1) nflags=FFTW_ESTIMATE_PATIENT
+  if(npatience.eq.2) nflags=FFTW_MEASURE
+  if(npatience.eq.3) nflags=FFTW_PATIENT
+  if(npatience.eq.4) nflags=FFTW_EXHAUSTIVE
+
+  open(12,file='chkfft.out',status='unknown')
+  open(13,file='fftwf_wisdom.dat',status='unknown')
+
+  if(nr.ne.0) then
+     call import_wisdom_from_file(isuccess,13)
+     if(isuccess.eq.0) then
+        write(*,1010) 
+1010    format('Failed to import FFTW wisdom.')
+        go to 999
+     endif
+  endif
+
+  idum=-1                               !Set random seed
+  ndim=1				!One-dimensional transforms
+  do i=1,NMAX                           !Set random data
+     x=gran()
+     y=gran()
+     b(i)=cmplx(x,y)                    !Generate random data
+  enddo
+
+  iters=1000000
+  if(list .or. (nfft.gt.0)) then
+     n1=1
+     n2=1
+     if(nfft.eq.-1) n2=999999
+     write(*,1020) 
+1020 format('    NFFT     Time        rms      MHz   MFlops  iters',    &
+          '  tplan'/61('-'))
+  else
+     n1=4
+     n2=23
+     write(*,1030) 
+1030 format(' n   N=2^n     Time        rms      MHz   MFlops  iters',  &
+          '  tplan'/63('-'))
+  endif
+
+  do ii=n1,n2                           !Test one or more FFT lengths
+     if(list) then
+        read(10,*,end=900) nfft         !Read nfft from file
+     else if(n2.gt.n1) then
+        nfft=2**ii                      !Do powers of 2
+     endif
+
+     iformf=1
+     iformb=1
+     if(ncomplex.eq.0) then
+        iformf=0                        !Real-to-complex transform
+        iformb=-1                       !Complex-to-real (inverse) transform
+     endif
+
+     if(nfft.gt.NMAX) go to 900
+     a(1:nfft)=b(1:nfft)                !Copy test data into a()
+     t0=second()
+     if(ncomplex.ne.0) then
+        plan1=fftwf_plan_dft_1d(nfft,a,c,-1,nflags)
+        plan2=fftwf_plan_dft_1d(nfft,a,c,+1,nflags)
+     else
+        plan1=fftwf_plan_dft_r2c_1d(nfft,ar,c,nflags)
+        plan2=fftwf_plan_dft_c2r_1d(nfft,c,ar,nflags)
+     endif
+
+     t2=second()
+     tplan=t2-t0                        !Total planning time for this length
+     
+     total=0.
+     do iter=1,iters                    !Now do many iterations
+        a(1:nfft)=b(1:nfft)             !Copy test data into a()
+        t0=second()
+        call fftwf_execute_dft(plan1,a,c)
+        call fftwf_execute_dft(plan2,c,a)
+        t1=second()
+        total=total+t1-t0
+        if(total.ge.1.0) go to 40       !Cut iterations short if t>1 s
+     enddo
+     iter=iters
+
+40   time=0.5*total/iter                !Time for one FFT of current length
+     tplan=0.5*tplan-time               !Planning time for one FFT
+     if(tplan.lt.0) tplan=0.
+     a(1:nfft)=a(1:nfft)/nfft
+
+! Compute RMS difference between original array and back-transformed array.
+     sq=0.
+     if(ncomplex.eq.1) then
+        do i=1,nfft
+           sq=sq + real(a(i)-b(i))**2 + imag(a(i)-b(i))**2
+        enddo
+     else
+        do i=1,nfft
+           sq=sq + (ar(i)-br(i))**2
+        enddo
+     endif
+     rms=sqrt(sq/nfft)
+
+     freq=1.e-6*nfft/time
+     mflops=5.0/(1.e6*time/(nfft*log(float(nfft))/log(2.0)))
+     if(n2.eq.1 .or. n2.eq.999999) then
+        write(*,1050) nfft,time,rms,freq,mflops,iter,tplan
+        write(12,1050) nfft,time,rms,freq,mflops,iter,tplan
+1050    format(i8,f11.7,f12.8,f7.2,f8.1,i8,f6.1)
+     else
+        write(*,1060) ii,nfft,time,rms,freq,mflops,iter,tplan
+        write(12,1060) ii,nfft,time,rms,freq,mflops,iter,tplan
+1060    format(i2,i8,f11.7,f12.8,f7.2,f8.1,i8,f6.1)
+     endif
+  enddo
+
+900  continue 
+  if(nw.eq.1) then
+     rewind 13
+     call export_wisdom_to_file(13)
+!     write(*,1070) 
+!1070 format(/'Exported FFTW wisdom')
+  endif
+
+  call fftwf_destroy_plan(plan1)
+  call fftwf_destroy_plan(plan2)
+
+999 end program chkfft
diff --git a/lib/chkmsg.f90 b/lib/chkmsg.f90
index ade13bc..72e0ccc 100644
--- a/lib/chkmsg.f90
+++ b/lib/chkmsg.f90
@@ -23,9 +23,9 @@ subroutine chkmsg(message,cok,nspecial,flip)
      endif
   endif
 
-  if(message(1:2).eq.'RO')  nspecial=2
-  if(message(1:3).eq.'RRR') nspecial=3
-  if(message(1:2).eq.'73')  nspecial=4
+  if(message(1:3).eq.'RO ')  nspecial=2
+  if(message(1:4).eq.'RRR ') nspecial=3
+  if(message(1:3).eq.'73 ')  nspecial=4
 
   return
 end subroutine chkmsg
diff --git a/lib/chkss2.f90 b/lib/chkss2.f90
index 12b2a2e..ad52c66 100644
--- a/lib/chkss2.f90
+++ b/lib/chkss2.f90
@@ -2,22 +2,18 @@ subroutine chkss2(ss2,freq,drift,schk)
 
   real ss2(0:8,85)
   real s(0:8,85)
-  real s1(0:5)
   include 'jt9sync.f90'
 
   ave=sum(ss2)/(9*85)
   if(freq+drift.eq.-999999.0) ave=0.      !To silence compiler warning
   s=ss2/ave-1.0
 
-!  call zplot9(s,freq,drift)
   s1=0.
-  do lag=0,5
-     do i=1,16
-        j=ii(i)+lag
-        if(j.le.85) s1(lag)=s1(lag) + s(0,j)
-     enddo
+  do i=1,16
+     j=ii(i)
+     if(j.le.85) s1=s1 + s(0,j)
   enddo
-  schk=s1(0)/16.0
+  schk=s1/16.0
 
   return
 end subroutine chkss2
diff --git a/lib/coord.f90 b/lib/coord.f90
new file mode 100644
index 0000000..b60f71e
--- /dev/null
+++ b/lib/coord.f90
@@ -0,0 +1,41 @@
+SUBROUTINE COORD(A0,B0,AP,BP,A1,B1,A2,B2)
+
+! Examples:
+! 1. From ha,dec to az,el:
+!      call coord(pi,pio2-lat,0.,lat,ha,dec,az,el)
+! 2. From az,el to ha,dec:
+!      call coord(pi,pio2-lat,0.,lat,az,el,ha,dec)
+! 3. From ra,dec to l,b
+!      call coord(4.635594495,-0.504691042,3.355395488,0.478220215,
+!        ra,dec,l,b)
+! 4. From l,b to ra,dec
+!      call coord(1.705981071d0,-1.050357016d0,2.146800277d0,
+!        0.478220215d0,l,b,ra,dec)
+! 5. From ra,dec to ecliptic latitude (eb) and longitude (el):
+!      call coord(0.d0,0.d0,-pio2,pio2-23.443*pi/180,ra,dec,el,eb)
+! 6. From ecliptic latitude (eb) and longitude (el) to ra,dec:
+!      call coord(0.d0,0.d0,-pio2,pio2-23.443*pi/180,el,eb,ra,dec)
+
+  SB0=sin(B0)
+  CB0=cos(B0)
+  SBP=sin(BP)
+  CBP=cos(BP)
+  SB1=sin(B1)
+  CB1=cos(B1)
+  SB2=SBP*SB1 + CBP*CB1*cos(AP-A1)
+  CB2=SQRT(1.e0-SB2**2)
+  B2=atan(SB2/CB2)
+  SAA=sin(AP-A1)*CB1/CB2
+  CAA=(SB1-SB2*SBP)/(CB2*CBP)
+  CBB=SB0/CBP
+  SBB=sin(AP-A0)*CB0
+  SA2=SAA*CBB-CAA*SBB
+  CA2=CAA*CBB+SAA*SBB
+  TA2O2=0.0 !Shut up compiler warnings. -db
+  IF(CA2.LE.0.e0) TA2O2=(1.e0-CA2)/SA2 
+  IF(CA2.GT.0.e0) TA2O2=SA2/(1.e0+CA2)
+  A2=2.e0*atan(TA2O2)
+  IF(A2.LT.0.e0) A2=A2+6.2831853
+
+  RETURN
+END SUBROUTINE COORD
diff --git a/lib/cutil.c b/lib/cutil.c
deleted file mode 100644
index 69a526b..0000000
--- a/lib/cutil.c
+++ /dev/null
@@ -1,93 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-// #include <sys/times.h>
-// #include <time.h>
-// #include <sys/time.h>
-#include "sleep.h"
-#include "timeval.h"
-
-/*  FORTRAN:  fd = close(filedes)      */
-int close_(int *filedes)
-{
-return(close(*filedes));
-}
-/*  FORTRAN:  fd = open(filnam,mode)  */
-int open_(char filnam[], int *mode)
-{
-  return(open(filnam,*mode));
-}
-/* FORTRAN:  fd = creat(filnam,mode) */
-int creat_(char filnam[],int *mode)
-{
-  return(creat(filnam,*mode));
-}
-/* FORTRAN:  nread = read(fd,buf,n) */
-int read_(int *fd, char buf[], int *n)
-{
-  return(read(*fd,buf,*n));
-}
-/* FORTRAN:  nwrt = write(fd,buf,n) */
-int write_(int *fd, char buf[], int *n)
-{
-  return(write(*fd,buf,*n));
-}
-/* FORTRAN: ns = lseek(fd,offset,origin) */
-int lseek_(int *fd,int *offset, int *origin)
-{
-  return(lseek(*fd,*offset,*origin));
-}
-/* times(2) */
-//int times_(struct tms *buf)
-//{
-//  return (times(buf));
-//}
-/* ioperm(2) */
-//ioperm_(from,num,turn_on)
-//unsigned long *from,*num,*turn_on;
-//{
-//  return (ioperm(*from,*num,*turn_on));
-//   return (i386_get_ioperm(*from,*num,*turn_on));
-//}
-
-/* usleep(3) */
-void usleep_(unsigned long *microsec)
-{
-  usleep(*microsec);
-}
-
-/* returns random numbers between 0 and 32767 to FORTRAN program */
-int iran_(int *arg)
-{
-  return (rand());
-}
-
-int exit_(int *n)
-{
-  printf("\n\n");
-  exit(*n);
-}
-
-/*
-struct tm *
-gmtime_r_(const time_t *clock, struct tm *result)
-{
-  gmtime_r(clock, result);
-}
-*/
-
-time_t time_(void)
-{
-     return time(0);
-}
-
-/* hrtime() */
-double hrtime_(void)
-{
-  struct timeval tv;
-  gettimeofday(&tv,NULL);
-  return(tv.tv_sec+1.e-6*tv.tv_usec);
-}
diff --git a/lib/dcoord.f90 b/lib/dcoord.f90
new file mode 100644
index 0000000..683be0a
--- /dev/null
+++ b/lib/dcoord.f90
@@ -0,0 +1,40 @@
+SUBROUTINE DCOORD(A0,B0,AP,BP,A1,B1,A2,B2)
+
+  implicit real*8 (a-h,o-z)
+! Examples:
+! 1. From ha,dec to az,el:
+!      call coord(pi,pio2-lat,0.,lat,ha,dec,az,el)
+! 2. From az,el to ha,dec:
+!      call coord(pi,pio2-lat,0.,lat,az,el,ha,dec)
+! 3. From ra,dec to l,b
+!      call coord(4.635594495,-0.504691042,3.355395488,0.478220215,
+!        ra,dec,l,b)
+! 4. From l,b to ra,dec
+!      call coord(1.705981071d0,-1.050357016d0,2.146800277d0,
+!        0.478220215d0,l,b,ra,dec)
+! 5. From ecliptic latitude (eb) and longitude (el) to ra, dec:
+!      call coord(0.d0,0.d0,-pio2,pio2-23.443*pi/180,ra,dec,el,eb)
+
+  SB0=sin(B0)
+  CB0=cos(B0)
+  SBP=sin(BP)
+  CBP=cos(BP)
+  SB1=sin(B1)
+  CB1=cos(B1)
+  SB2=SBP*SB1 + CBP*CB1*cos(AP-A1)
+  CB2=SQRT(1.D0-SB2**2)
+  B2=atan(SB2/CB2)
+  SAA=sin(AP-A1)*CB1/CB2
+  CAA=(SB1-SB2*SBP)/(CB2*CBP)
+  CBB=SB0/CBP
+  SBB=sin(AP-A0)*CB0
+  SA2=SAA*CBB-CAA*SBB
+  CA2=CAA*CBB+SAA*SBB
+  TA2O2=0.0 !Shut up compiler warnings. -db
+  IF(CA2.LE.0.D0) TA2O2=(1.D0-CA2)/SA2 
+  IF(CA2.GT.0.D0) TA2O2=SA2/(1.D0+CA2)
+  A2=2.D0*atan(TA2O2)
+  IF(A2.LT.0.D0) A2=A2+6.2831853071795864D0
+  
+  RETURN
+END SUBROUTINE DCOORD
diff --git a/lib/decoder.f90 b/lib/decjt9.f90
similarity index 59%
copy from lib/decoder.f90
copy to lib/decjt9.f90
index 83e63a2..0f54980 100644
--- a/lib/decoder.f90
+++ b/lib/decjt9.f90
@@ -1,173 +1,146 @@
-subroutine decoder(ss,id2)
-
-! Decoder for JT9.
-
-  include 'constants.f90'
-  real ss(184,NSMAX)
-  character*22 msg
-  character*20 datetime
-  real*4 ccfred(NSMAX)
-  real*4 red2(NSMAX)
-  logical ccfok(NSMAX)
-  logical done(NSMAX)
-  logical done65
-  integer*2 id2(NTMAX*12000)
-  real*4 dd(NTMAX*12000)
-  integer*1 i1SoftSymbols(207)
-  common/npar/nutc,ndiskdat,ntrperiod,nfqso,newdat,npts8,nfa,nfb,ntol,  &
-       kin,nzhsym,nsave,nagain,ndepth,ntxmode,nmode,datetime
-  common/tracer/limtrace,lu
-  save
-
-  call system_clock(iclock0,iclock_rate,iclock_max)           !###
-  nfreqs0=0
-  nfreqs1=0
-  ndecodes0=0
-  ndecodes1=0
-
-  open(13,file='decoded.txt',status='unknown')
-  open(22,file='kvasd.dat',access='direct',recl=1024,status='unknown')
-
-  npts65=52*12000
-  ntol65=20
-  done65=.false.
-  if(nmode.ge.65 .and. ntxmode.eq.65) then
-     if(newdat.ne.0) dd(1:npts65)=id2(1:npts65)
-     call jt65a(dd,npts65,newdat,nutc,nfa,nfqso,ntol65,nagain,ndecoded)
-     done65=.true.
-  endif
-
-  if(nmode.eq.65) go to 800
-
-  nsynced=0
-  ndecoded=0
-  nsps=0
-
-  nsps=6912                                   !Params for JT9-1
-  df3=1500.0/2048.0
-
-  tstep=0.5*nsps/12000.0                      !Half-symbol step (seconds)
-  done=.false.
-
-  nf0=0
-  ia=max(1,nint((nfa-nf0)/df3))
-  ib=min(NSMAX,nint((nfb-nf0)/df3))
-  lag1=-(2.5/tstep + 0.9999)
-  lag2=5.0/tstep + 0.9999
-  if(newdat.ne.0) then
-     call timer('sync9   ',0)
-     call sync9(ss,nzhsym,lag1,lag2,ia,ib,ccfred,red2,ipk)
-     call timer('sync9   ',1)
-  endif
-
-  nsps8=nsps/8
-  df8=1500.0/nsps8
-  dblim=db(864.0/nsps8) - 26.2
-
-  do nqd=1,0,-1
-     limit=1000
-     ccflim=4.0
-     red2lim=1.6
-     schklim=2.2
-     if(ndepth.eq.2) then
-        limit=10000
-        ccflim=3.5
-     endif
-     if(ndepth.ge.3 .or. nqd.eq.1) then
-        limit=100000
-        ccflim=2.5
-     endif
-     ccfok=.false.
-
-     if(nqd.eq.1) then
-        nfa1=nfqso-ntol
-        nfb1=nfqso+ntol
-        ia=max(1,nint((nfa1-nf0)/df3))
-        ib=min(NSMAX,nint((nfb1-nf0)/df3))
-        ccfok(ia:ib)=(ccfred(ia:ib).gt.(ccflim-2.0)) .and.               &
-                     (red2(ia:ib).gt.(red2lim-1.0))
-        ia1=ia
-        ib1=ib
-     else
-        nfa1=nfa
-        nfb1=nfb
-        ia=max(1,nint((nfa1-nf0)/df3))
-        ib=min(NSMAX,nint((nfb1-nf0)/df3))
-        do i=ia,ib
-           ccfok(i)=ccfred(i).gt.ccflim .and. red2(i).gt.red2lim
-        enddo
-        ccfok(ia1:ib1)=.false.
-     endif
-
-     fgood=0.
-     do i=ia,ib
-        if(done(i) .or. (.not.ccfok(i))) cycle
-        f=(i-1)*df3
-        if(nqd.eq.1 .or.                                                   &
-           (ccfred(i).ge.ccflim .and. abs(f-fgood).gt.10.0*df8)) then
-
-           if(nqd.eq.0) nfreqs0=nfreqs0+1
-           if(nqd.eq.1) nfreqs1=nfreqs1+1
-
-           call timer('softsym ',0)
-           fpk=nf0 + df3*(i-1)
-
-           call softsym(id2,npts8,nsps8,newdat,fpk,syncpk,snrdb,xdt,    &
-                freq,drift,schk,i1SoftSymbols)
-           call timer('softsym ',1)
-
-!           write(71,3001) nqd,i,f,fpk,ccfred(i),red2(i),schk
-!3001       format(2i6,2f8.1,3f6.1)
-!           call flush(71)
-
-           if(schk.lt.schklim) cycle
-
-           call timer('decode9 ',0)
-           call decode9(i1SoftSymbols,limit,nlim,msg)
-           call timer('decode9 ',1)
-
-           sync=(syncpk+1)/4.0
-           if(sync.lt.0.0 .or. snrdb.lt.dblim-2.0) sync=0.0
-           nsync=sync
-           if(nsync.gt.10) nsync=10
-           nsnr=nint(snrdb)
-           ndrift=nint(drift/df3)
-              
-           if(msg.ne.'                      ') then
-              if(nqd.eq.0) ndecodes0=ndecodes0+1
-              if(nqd.eq.1) ndecodes1=ndecodes1+1
-                 
-              write(*,1000) nutc,nsnr,xdt,nint(freq),msg
-1000          format(i4.4,i4,f5.1,i5,1x,'@',1x,a22)
-              write(13,1002) nutc,nsync,nsnr,xdt,freq,ndrift,msg
-1002          format(i4.4,i4,i5,f6.1,f8.0,i4,3x,a22,' JT9')
-
-              iaa=max(1,i-1)
-              ibb=min(NSMAX,i+22)
-              fgood=f
-              nsynced=1
-              ndecoded=1
-              ccfok(iaa:ibb)=.false.
-              done(iaa:ibb)=.true.              
-              call flush(6)
-           endif
-        endif
-     enddo
-     call flush(6)
-     if(nagain.ne.0) exit
-  enddo
-
-  if(nmode.ge.65 .and. (.not.done65)) then
-     if(newdat.ne.0) dd(1:npts65)=id2(1:npts65)
-     call jt65a(dd,npts65,newdat,nutc,nfa,nfqso,ntol65,nagain,ndecoded)
-  endif
-
-!### JT65 is not yet producing info for nsynced, ndecoded.
-800 write(*,1010) nsynced,ndecoded
-1010 format('<DecodeFinished>',2i4)
-  call flush(6)
-  close(13)
-  close(22)
-
-  return
-end subroutine decoder
+subroutine decjt9(ss,id2,nutc,nfqso,newdat,npts8,nfa,nfsplit,nfb,ntol,  &
+     nzhsym,nagain,ndepth,nmode)
+
+  include 'constants.f90'
+  real ss(184,NSMAX)
+  character*22 msg
+  character*500 infile
+  real*4 ccfred(NSMAX)
+  real*4 red2(NSMAX)
+  logical ccfok(NSMAX)
+  logical done(NSMAX)
+  integer*2 id2(NTMAX*12000)
+  integer*1 i1SoftSymbols(207)
+  common/decstats/num65,numbm,numkv,num9,numfano,infile
+  save ccfred,red2
+
+  nsynced=0
+  ndecoded=0
+  nsps=6912                                   !Params for JT9-1
+  df3=1500.0/2048.0
+
+  tstep=0.5*nsps/12000.0                      !Half-symbol step (seconds)
+  done=.false.
+
+  nf0=0
+  nf1=nfa
+  if(nmode.eq.65+9) nf1=nfsplit
+  ia=max(1,nint((nf1-nf0)/df3))
+  ib=min(NSMAX,nint((nfb-nf0)/df3))
+  lag1=-int(2.5/tstep + 0.9999)
+  lag2=int(5.0/tstep + 0.9999)
+  if(newdat.ne.0) then
+     call timer('sync9   ',0)
+     call sync9(ss,nzhsym,lag1,lag2,ia,ib,ccfred,red2,ipk)
+     call timer('sync9   ',1)
+  endif
+
+  nsps8=nsps/8
+  df8=1500.0/nsps8
+  dblim=db(864.0/nsps8) - 26.2
+
+  do nqd=1,0,-1
+     limit=5000
+     ccflim=3.0
+     red2lim=1.6
+     schklim=2.2
+     if(ndepth.eq.2) then
+        limit=10000
+        ccflim=2.7
+     endif
+     if(ndepth.ge.3 .or. nqd.eq.1) then
+        limit=30000
+        ccflim=2.5
+        schklim=2.0
+     endif
+     if(nagain.ne.0) then
+        limit=100000
+        ccflim=2.4
+        schklim=1.8
+     endif
+     ccfok=.false.
+
+     if(nqd.eq.1) then
+        nfa1=nfqso-ntol
+        nfb1=nfqso+ntol
+        ia=max(1,nint((nfa1-nf0)/df3))
+        ib=min(NSMAX,nint((nfb1-nf0)/df3))
+        ccfok(ia:ib)=(ccfred(ia:ib).gt.(ccflim-2.0)) .and.               &
+                     (red2(ia:ib).gt.(red2lim-1.0))
+        ia1=ia
+        ib1=ib
+     else
+        nfa1=nf1
+        nfb1=nfb
+        ia=max(1,nint((nfa1-nf0)/df3))
+        ib=min(NSMAX,nint((nfb1-nf0)/df3))
+        do i=ia,ib
+           ccfok(i)=ccfred(i).gt.ccflim .and. red2(i).gt.red2lim
+        enddo
+        ccfok(ia1:ib1)=.false.
+     endif
+
+     fgood=0.
+     do i=ia,ib
+        if(done(i) .or. (.not.ccfok(i))) cycle
+        f=(i-1)*df3
+        if(nqd.eq.1 .or.                                                   &
+           (ccfred(i).ge.ccflim .and. abs(f-fgood).gt.10.0*df8)) then
+
+           if(nqd.eq.0) nfreqs0=nfreqs0+1
+           if(nqd.eq.1) nfreqs1=nfreqs1+1
+
+           call timer('softsym ',0)
+           fpk=nf0 + df3*(i-1)
+           call softsym(id2,npts8,nsps8,newdat,fpk,syncpk,snrdb,xdt,    &
+                freq,drift,a3,schk,i1SoftSymbols)
+           call timer('softsym ',1)
+
+           sync=(syncpk+1)/4.0
+           if(nqd.eq.1 .and. ((sync.lt.0.5) .or. (schk.lt.1.0))) cycle
+           if(nqd.ne.1 .and. ((sync.lt.1.0) .or. (schk.lt.1.5))) cycle
+
+           call timer('jt9fano ',0)
+           call jt9fano(i1SoftSymbols,limit,nlim,msg)
+           call timer('jt9fano ',1)
+
+           if(sync.lt.0.0 .or. snrdb.lt.dblim-2.0) sync=0.0
+           nsync=int(sync)
+           if(nsync.gt.10) nsync=10
+           nsnr=nint(snrdb)
+           ndrift=nint(drift/df3)
+           num9=num9+1
+
+           if(msg.ne.'                      ') then
+              numfano=numfano+1
+              if(nqd.eq.0) ndecodes0=ndecodes0+1
+              if(nqd.eq.1) ndecodes1=ndecodes1+1
+
+!$omp critical(decode_results) ! serialize writes - see also jt65a.f90
+              write(*,1000) nutc,nsnr,xdt,nint(freq),msg
+1000          format(i4.4,i4,f5.1,i5,1x,'@',1x,a22)
+!              i1=index(infile,'.wav')
+!              write(*,1000) infile(i1-11:i1-1),nsnr,xdt,nint(freq),msg,   &
+!                   schk,drift,a3,nlim
+!1000          format(a11,i4,f5.1,i5,1x,'@',1x,a22,3f6.1,i6)
+              write(13,1002) nutc,nsync,nsnr,xdt,freq,ndrift,msg
+1002          format(i4.4,i4,i5,f6.1,f8.0,i4,3x,a22,' JT9')
+              call flush(6)
+              call flush(13)
+!$omp end critical(decode_results)
+
+              iaa=max(1,i-1)
+              ibb=min(NSMAX,i+22)
+              fgood=f
+              nsynced=1
+              ndecoded=1
+              ccfok(iaa:ibb)=.false.
+              done(iaa:ibb)=.true.
+           endif
+        endif
+     enddo
+     if(nagain.ne.0) exit
+  enddo
+
+  return
+end subroutine decjt9
diff --git a/lib/decode65a.f90 b/lib/decode65a.f90
index ea61d35..031c48f 100644
--- a/lib/decode65a.f90
+++ b/lib/decode65a.f90
@@ -1,4 +1,4 @@
-subroutine decode65a(dd,npts,newdat,f0,nflip,mode65,sync2,a,dt,    &
+subroutine decode65a(dd,npts,newdat,nqd,f0,nflip,mode65,sync2,a,dt,    &
      nbmkv,nhist,decoded)
 
 ! Apply AFC corrections to a candidate JT65 signal, then decode it.
@@ -87,7 +87,7 @@ subroutine decode65a(dd,npts,newdat,f0,nflip,mode65,sync2,a,dt,    &
   call timer('sh_ffts ',1)
 
   call timer('dec65b  ',0)
-  call decode65b(s2,nflip,mode65,nbmkv,nhist,decoded)
+  call decode65b(s2,nflip,mode65,nqd,nbmkv,nhist,decoded)
   dt=dt00 + dtbest + 1.7
   call timer('dec65b  ',1)
 
diff --git a/lib/decode65b.f90 b/lib/decode65b.f90
index 729a218..f404049 100644
--- a/lib/decode65b.f90
+++ b/lib/decode65b.f90
@@ -1,4 +1,4 @@
-subroutine decode65b(s2,nflip,mode65,nbmkv,nhist,decoded)
+subroutine decode65b(s2,nflip,mode65,nqd,nbmkv,nhist,decoded)
 
   real s2(66,126)
   real s3(64,63)
@@ -22,7 +22,7 @@ subroutine decode65b(s2,nflip,mode65,nbmkv,nhist,decoded)
   enddo
 
   nadd=mode65
-  call extract(s3,nadd,ncount,nhist,decoded,ltext,nbmkv)   !Extract the message
+  call extract(s3,nadd,nqd,ncount,nhist,decoded,ltext,nbmkv)   !Extract message
 ! Suppress "birdie messages" and other garbage decodes:
   if(decoded(1:7).eq.'000AAA ') ncount=-1
   if(decoded(1:7).eq.'0L6MWK ') ncount=-1
diff --git a/lib/decoder.f90 b/lib/decoder.f90
index 83e63a2..7dfe64a 100644
--- a/lib/decoder.f90
+++ b/lib/decoder.f90
@@ -1,173 +1,96 @@
-subroutine decoder(ss,id2)
-
-! Decoder for JT9.
-
-  include 'constants.f90'
-  real ss(184,NSMAX)
-  character*22 msg
-  character*20 datetime
-  real*4 ccfred(NSMAX)
-  real*4 red2(NSMAX)
-  logical ccfok(NSMAX)
-  logical done(NSMAX)
-  logical done65
-  integer*2 id2(NTMAX*12000)
-  real*4 dd(NTMAX*12000)
-  integer*1 i1SoftSymbols(207)
-  common/npar/nutc,ndiskdat,ntrperiod,nfqso,newdat,npts8,nfa,nfb,ntol,  &
-       kin,nzhsym,nsave,nagain,ndepth,ntxmode,nmode,datetime
-  common/tracer/limtrace,lu
-  save
-
-  call system_clock(iclock0,iclock_rate,iclock_max)           !###
-  nfreqs0=0
-  nfreqs1=0
-  ndecodes0=0
-  ndecodes1=0
-
-  open(13,file='decoded.txt',status='unknown')
-  open(22,file='kvasd.dat',access='direct',recl=1024,status='unknown')
-
-  npts65=52*12000
-  ntol65=20
-  done65=.false.
-  if(nmode.ge.65 .and. ntxmode.eq.65) then
-     if(newdat.ne.0) dd(1:npts65)=id2(1:npts65)
-     call jt65a(dd,npts65,newdat,nutc,nfa,nfqso,ntol65,nagain,ndecoded)
-     done65=.true.
-  endif
-
-  if(nmode.eq.65) go to 800
-
-  nsynced=0
-  ndecoded=0
-  nsps=0
-
-  nsps=6912                                   !Params for JT9-1
-  df3=1500.0/2048.0
-
-  tstep=0.5*nsps/12000.0                      !Half-symbol step (seconds)
-  done=.false.
-
-  nf0=0
-  ia=max(1,nint((nfa-nf0)/df3))
-  ib=min(NSMAX,nint((nfb-nf0)/df3))
-  lag1=-(2.5/tstep + 0.9999)
-  lag2=5.0/tstep + 0.9999
-  if(newdat.ne.0) then
-     call timer('sync9   ',0)
-     call sync9(ss,nzhsym,lag1,lag2,ia,ib,ccfred,red2,ipk)
-     call timer('sync9   ',1)
-  endif
-
-  nsps8=nsps/8
-  df8=1500.0/nsps8
-  dblim=db(864.0/nsps8) - 26.2
-
-  do nqd=1,0,-1
-     limit=1000
-     ccflim=4.0
-     red2lim=1.6
-     schklim=2.2
-     if(ndepth.eq.2) then
-        limit=10000
-        ccflim=3.5
-     endif
-     if(ndepth.ge.3 .or. nqd.eq.1) then
-        limit=100000
-        ccflim=2.5
-     endif
-     ccfok=.false.
-
-     if(nqd.eq.1) then
-        nfa1=nfqso-ntol
-        nfb1=nfqso+ntol
-        ia=max(1,nint((nfa1-nf0)/df3))
-        ib=min(NSMAX,nint((nfb1-nf0)/df3))
-        ccfok(ia:ib)=(ccfred(ia:ib).gt.(ccflim-2.0)) .and.               &
-                     (red2(ia:ib).gt.(red2lim-1.0))
-        ia1=ia
-        ib1=ib
-     else
-        nfa1=nfa
-        nfb1=nfb
-        ia=max(1,nint((nfa1-nf0)/df3))
-        ib=min(NSMAX,nint((nfb1-nf0)/df3))
-        do i=ia,ib
-           ccfok(i)=ccfred(i).gt.ccflim .and. red2(i).gt.red2lim
-        enddo
-        ccfok(ia1:ib1)=.false.
-     endif
-
-     fgood=0.
-     do i=ia,ib
-        if(done(i) .or. (.not.ccfok(i))) cycle
-        f=(i-1)*df3
-        if(nqd.eq.1 .or.                                                   &
-           (ccfred(i).ge.ccflim .and. abs(f-fgood).gt.10.0*df8)) then
-
-           if(nqd.eq.0) nfreqs0=nfreqs0+1
-           if(nqd.eq.1) nfreqs1=nfreqs1+1
-
-           call timer('softsym ',0)
-           fpk=nf0 + df3*(i-1)
-
-           call softsym(id2,npts8,nsps8,newdat,fpk,syncpk,snrdb,xdt,    &
-                freq,drift,schk,i1SoftSymbols)
-           call timer('softsym ',1)
-
-!           write(71,3001) nqd,i,f,fpk,ccfred(i),red2(i),schk
-!3001       format(2i6,2f8.1,3f6.1)
-!           call flush(71)
-
-           if(schk.lt.schklim) cycle
-
-           call timer('decode9 ',0)
-           call decode9(i1SoftSymbols,limit,nlim,msg)
-           call timer('decode9 ',1)
-
-           sync=(syncpk+1)/4.0
-           if(sync.lt.0.0 .or. snrdb.lt.dblim-2.0) sync=0.0
-           nsync=sync
-           if(nsync.gt.10) nsync=10
-           nsnr=nint(snrdb)
-           ndrift=nint(drift/df3)
-              
-           if(msg.ne.'                      ') then
-              if(nqd.eq.0) ndecodes0=ndecodes0+1
-              if(nqd.eq.1) ndecodes1=ndecodes1+1
-                 
-              write(*,1000) nutc,nsnr,xdt,nint(freq),msg
-1000          format(i4.4,i4,f5.1,i5,1x,'@',1x,a22)
-              write(13,1002) nutc,nsync,nsnr,xdt,freq,ndrift,msg
-1002          format(i4.4,i4,i5,f6.1,f8.0,i4,3x,a22,' JT9')
-
-              iaa=max(1,i-1)
-              ibb=min(NSMAX,i+22)
-              fgood=f
-              nsynced=1
-              ndecoded=1
-              ccfok(iaa:ibb)=.false.
-              done(iaa:ibb)=.true.              
-              call flush(6)
-           endif
-        endif
-     enddo
-     call flush(6)
-     if(nagain.ne.0) exit
-  enddo
-
-  if(nmode.ge.65 .and. (.not.done65)) then
-     if(newdat.ne.0) dd(1:npts65)=id2(1:npts65)
-     call jt65a(dd,npts65,newdat,nutc,nfa,nfqso,ntol65,nagain,ndecoded)
-  endif
-
-!### JT65 is not yet producing info for nsynced, ndecoded.
-800 write(*,1010) nsynced,ndecoded
-1010 format('<DecodeFinished>',2i4)
-  call flush(6)
-  close(13)
-  close(22)
-
-  return
-end subroutine decoder
+subroutine decoder(ss,id2)
+
+  use prog_args
+  !$ use omp_lib
+
+  include 'constants.f90'
+  real ss(184,NSMAX)
+  character*20 datetime
+  logical baddata
+  integer*2 id2(NTMAX*12000)
+  real*4 dd(NTMAX*12000)
+  common/npar/nutc,ndiskdat,ntrperiod,nfqso,newdat,npts8,nfa,nfsplit,nfb,    &
+       ntol,kin,nzhsym,nsave,nagain,ndepth,ntxmode,nmode,datetime
+  common/tracer/limtrace,lu
+  integer onlevel(0:10)
+  common/tracer_priv/level,onlevel
+  !$omp threadprivate(/tracer_priv/)
+  save
+
+  rms=sqrt(dot_product(float(id2(300000:310000)),                            &
+                       float(id2(300000:310000)))/10000.0)
+  if(rms.lt.2.0) go to 800 
+
+  nfreqs0=0
+  nfreqs1=0
+  ndecodes0=0
+  ndecodes1=0
+
+  if (nagain .eq. 0) then
+     open(13,file=trim(temp_dir)//'/decoded.txt',status='unknown')
+  else
+     open(13,file=trim(temp_dir)//'/decoded.txt',status='unknown',      &
+          position='append')
+  end if
+  open(22,file=trim(temp_dir)//'/kvasd.dat',access='direct',recl=1024,  &
+       status='unknown')
+
+  npts65=52*12000
+  if(baddata(id2,npts65)) then
+     nsynced=0
+     ndecoded=0
+     go to 800
+  endif
+
+  ntol65=20
+  newdat65=newdat
+  newdat9=newdat
+
+  !$ call omp_set_dynamic(.true.)
+  !$omp parallel sections num_threads(2) copyin(/tracer_priv/) shared(ndecoded) if(.true.) !iif() needed on Mac
+
+  !$omp section
+  if(nmode.eq.65 .or. (nmode.gt.65 .and. ntxmode.eq.65)) then
+! We're decoding JT65 or should do this mode first
+     if(newdat65.ne.0) dd(1:npts65)=id2(1:npts65)
+     nf1=nfa
+     nf2=nfb
+     call timer('jt65a   ',0)
+     call jt65a(dd,npts65,newdat65,nutc,nf1,nf2,nfqso,ntol65,nagain,ndecoded)
+     call timer('jt65a   ',1)
+  else
+! We're decoding JT9 or should do this mode first
+     call timer('decjt9  ',0)
+     call decjt9(ss,id2,nutc,nfqso,newdat9,npts8,nfa,nfsplit,nfb,ntol,nzhsym,  &
+          nagain,ndepth,nmode)
+     call timer('decjt9  ',1)
+  endif
+
+  !$omp section
+  if(nmode.gt.65) then          ! do the other mode in dual mode
+     if (ntxmode.eq.9) then
+        if(newdat65.ne.0) dd(1:npts65)=id2(1:npts65)
+        nf1=nfa
+        nf2=nfb
+        call timer('jt65a   ',0)
+        call jt65a(dd,npts65,newdat65,nutc,nf1,nf2,nfqso,ntol65,nagain,ndecoded)
+        call timer('jt65a   ',1)
+     else
+        call timer('decjt9  ',0)
+        call decjt9(ss,id2,nutc,nfqso,newdat9,npts8,nfa,nfsplit,nfb,ntol,   &
+             nzhsym,nagain,ndepth,nmode)
+        call timer('decjt9  ',1)
+     end if
+  endif
+
+  !$omp end parallel sections
+
+! JT65 is not yet producing info for nsynced, ndecoded.
+800 write(*,1010) nsynced,ndecoded
+1010 format('<DecodeFinished>',2i4)
+  call flush(6)
+  close(13)
+  close(22)
+
+  return
+end subroutine decoder
diff --git a/lib/demod64a.f90 b/lib/demod64a.f90
index 9d1a379..452140a 100644
--- a/lib/demod64a.f90
+++ b/lib/demod64a.f90
@@ -1,4 +1,4 @@
-subroutine demod64a(s3,nadd,mrsym,mrprob,mr2sym,mr2prob,ntest,nlow)
+subroutine demod64a(s3,nadd,afac1,mrsym,mrprob,mr2sym,mr2prob,ntest,nlow)
 
 ! Demodulate the 64-bin spectra for each of 63 symbols in a frame.
 
@@ -10,23 +10,16 @@ subroutine demod64a(s3,nadd,mrsym,mrprob,mr2sym,mr2prob,ntest,nlow)
 !    mr2prob  probability that mr2sym was the transmitted value
 
   implicit real*8 (a-h,o-z)
-  real*4 s3(64,63)
+  real*4 s3(64,63),afac1
   real*8 fs(64)
   integer mrsym(63),mrprob(63),mr2sym(63),mr2prob(63)
-!  common/mrscom/ mrs(63),mrs2(63)
 
   if(nadd.eq.-999) return
-  afac=1.1 * float(nadd)**0.64
+  afac=afac1 * float(nadd)**0.64
   scale=255.999
 
 ! Compute average spectral value
-  sum=0.
-  do j=1,63
-     do i=1,64
-        sum=sum+s3(i,j)
-     enddo
-  enddo
-  ave=sum/(64.*63.)
+  ave=sum(s3)/(64.*63.)
   i1=1                                      !Silence warning
   i2=1
 
@@ -57,17 +50,13 @@ subroutine demod64a(s3,nadd,mrsym,mrprob,mr2sym,mr2prob,ntest,nlow)
      mr2sym(j)=i2-1
      mrprob(j)=scale*p1
      mr2prob(j)=scale*p2
-!     mrs(j)=i1
-!     mrs2(j)=i2
   enddo
 
-  sum=0.
   nlow=0
   do j=1,63
-     sum=sum+mrprob(j)
      if(mrprob(j).le.5) nlow=nlow+1
   enddo
-  ntest=sum/63
+  ntest=sum(mrprob)/63.0
 
   return
 end subroutine demod64a
diff --git a/lib/determ.f90 b/lib/determ.f90
new file mode 100644
index 0000000..6ae471b
--- /dev/null
+++ b/lib/determ.f90
@@ -0,0 +1,32 @@
+real*8 function determ(array,norder)
+  implicit real*8 (a-h,o-z)
+  real*8 array(10,10)
+
+  determ=1.
+  do k=1,norder
+     if (array(k,k).ne.0) go to 41
+     do j=k,norder
+        if(array(k,j).ne.0) go to 31
+     enddo
+     determ=0.
+     go to 60
+
+31   do i=k,norder
+        s8=array(i,j)
+        array(i,j)=array(i,k)
+        array(i,k)=s8
+     enddo
+     determ=-1.*determ
+41   determ=determ*array(k,k)
+     if(k.lt.norder) then
+        k1=k+1
+        do i=k1,norder
+           do j=k1,norder
+              array(i,j)=array(i,j)-array(i,k)*array(k,j)/array(k,k)
+           enddo
+        enddo
+     end if
+  enddo
+
+60 return
+end function determ
diff --git a/lib/dot.f90 b/lib/dot.f90
new file mode 100644
index 0000000..a68c5bd
--- /dev/null
+++ b/lib/dot.f90
@@ -0,0 +1,11 @@
+real*8 function dot(x,y)
+
+  real*8 x(3),y(3)
+
+  dot=0.d0
+  do i=1,3
+     dot=dot+x(i)*y(i)
+  enddo
+
+  return
+end function dot
diff --git a/lib/downsam9.f90 b/lib/downsam9.f90
index 851d497..520ffa5 100644
--- a/lib/downsam9.f90
+++ b/lib/downsam9.f90
@@ -1,66 +1,87 @@
-subroutine downsam9(id2,npts8,nsps8,newdat,nspsd,fpk,c2,nz2)
-
-!Downsample from id2() into C2() so as to yield nspsd samples per symbol, 
-!mixing from fpk down to zero frequency.
-
-  include 'constants.f90'
-  parameter (NMAX1=1024*1920)
-  integer*2 id2(0:8*npts8-1)
-  real*4 x1(0:NMAX1-1)
-  complex c1(0:NMAX1/2)
-  complex c2(0:4096-1)
-  real s(5000)
-  equivalence (c1,x1)
-  save
-
-  nfft1=1024*nsps8                          !Forward FFT length
-  df1=12000.0/nfft1
-  npts=8*npts8
-
-  if(newdat.eq.1) then
-     fac=6.963e-6                             !Why this weird constant?
-     do i=0,npts-1
-        x1(i)=fac*id2(i)
-     enddo
-     x1(npts:nfft1-1)=0.                      !Zero the rest of x1
-     call timer('fft_forw',0)
-     call four2a(c1,nfft1,1,-1,0)             !Forward FFT, r2c
-     call timer('fft_forw',1)
-
-     nadd=1.0/df1
-     s=0.
-     do i=1,5000
-        j=(i-1)/df1
-        do n=1,nadd
-           j=j+1
-           s(i)=s(i)+real(c1(j))**2 + aimag(c1(j))**2
-        enddo
-     enddo
-  endif
-
-  ndown=8*nsps8/nspsd                      !Downsample factor
-  nfft2=nfft1/ndown                        !Backward FFT length
-  nh2=nfft2/2
-  nf=nint(fpk)
-  i0=fpk/df1
-
-  nw=100
-  ia=max(1,nf-nw)
-  ib=min(5000,nf+nw)
-  call timer('pctile_1',0)
-  call pctile(s(ia),ib-ia+1,40,avenoise)
-  call timer('pctile_1',1)
-
-  fac=sqrt(1.0/avenoise)
-  do i=0,nfft2-1
-     j=i0+i
-     if(i.gt.nh2) j=j-nfft2
-     c2(i)=fac*c1(j)
-  enddo
-  call timer('fft_back',0)
-  call four2a(c2,nfft2,1,1,1)              !FFT back to time domain
-  call timer('fft_back',1)
-  nz2=8*npts8/ndown
-
-  return
-end subroutine downsam9
+subroutine downsam9(id2,npts8,nsps8,newdat,nspsd,fpk,c2,nz2)
+
+!Downsample from id2() into c2() so as to yield nspsd samples per symbol, 
+!mixing from fpk down to zero frequency.  The downsample factor is 432.
+
+  use, intrinsic :: iso_c_binding
+  use FFTW3
+
+  include 'constants.f90'
+  integer(C_SIZE_T) NMAX1
+  parameter (NMAX1=604800)
+  type(C_PTR) :: plan                        !Pointers plan for big FFT
+  integer*2 id2(0:8*npts8-1)
+  real*4, pointer :: x1(:)
+  complex c1(0:NMAX1/2)
+  complex c2(0:1440-1)
+  real s(5000)
+  logical first
+  common/patience/npatience,nthreads
+  data first/.true./
+  save plan,first,c1,s,x1
+
+  nfft1=NMAX1                                !Forward FFT length
+  df1=12000.0/nfft1
+  npts=8*npts8
+
+  if(first) then
+     nflags=FFTW_ESTIMATE
+     if(npatience.eq.1) nflags=FFTW_ESTIMATE_PATIENT
+     if(npatience.eq.2) nflags=FFTW_MEASURE
+     if(npatience.eq.3) nflags=FFTW_PATIENT
+     if(npatience.eq.4) nflags=FFTW_EXHAUSTIVE
+! Plan the FFTs just once
+
+     !$omp critical(fftw) ! serialize non thread-safe FFTW3 calls
+     plan=fftwf_alloc_real(NMAX1)
+     call c_f_pointer(plan,x1,[NMAX1])
+     x1(0:NMAX1-1) => x1        !remap bounds
+     call fftwf_plan_with_nthreads(nthreads)
+     plan=fftwf_plan_dft_r2c_1d(nfft1,x1,c1,nflags)
+     call fftwf_plan_with_nthreads(1)
+     !$omp end critical(fftw)
+
+     first=.false.
+  endif
+
+  if(newdat.eq.1) then
+     x1(0:npts-1)=id2(0:npts-1)
+     x1(npts:nfft1-1)=0.                      !Zero the rest of x1
+     call timer('FFTbig9 ',0)
+     call fftwf_execute_dft_r2c(plan,x1,c1)
+     call timer('FFTbig9 ',1)
+
+     nadd=int(1.0/df1)
+     s=0.
+     do i=1,5000
+        j=int((i-1)/df1)
+        do n=1,nadd
+           j=j+1
+           s(i)=s(i)+real(c1(j))**2 + aimag(c1(j))**2
+        enddo
+     enddo
+     newdat=0
+  endif
+
+  ndown=8*nsps8/nspsd                      !Downsample factor
+  nfft2=nfft1/ndown                        !Backward FFT length
+  nh2=nfft2/2
+  nf=nint(fpk)
+  i0=int(fpk/df1)
+
+  nw=100
+  ia=max(1,nf-nw)
+  ib=min(5000,nf+nw)
+  call pctile(s(ia),ib-ia+1,40,avenoise)
+
+  fac=sqrt(1.0/avenoise)
+  do i=0,nfft2-1
+     j=i0+i
+     if(i.gt.nh2) j=j-nfft2
+     c2(i)=fac*c1(j)
+  enddo
+  call four2a(c2,nfft2,1,1,1)              !FFT back to time domain
+  nz2=8*npts8/ndown
+
+  return
+end subroutine downsam9
diff --git a/lib/encode4.f90 b/lib/encode4.f90
deleted file mode 100644
index 64b9dfc..0000000
--- a/lib/encode4.f90
+++ /dev/null
@@ -1,20 +0,0 @@
-subroutine encode4(message,ncode)
-
-  parameter (MAXCALLS=7000,MAXRPT=63)
-  integer ncode(206)
-  character*22 message          !Message to be generated
-  character*3 cok               !'   ' or 'OOO'
-  integer dgen(13)
-  integer*1 data0(13),symbol(216)
-  logical text
-
-  call chkmsg(message,cok,nspecial,flip)
-  call packmsg(message,dgen,text)  !Pack 72-bit message into 12 six-bit symbols
-  call entail(dgen,data0)
-  call encode232(data0,206,symbol)       !Convolutional encoding
-  call interleave24(symbol,1)            !Apply JT4 interleaving
-  do i=1,206
-     ncode(i)=symbol(i)
-  enddo
-
-end subroutine encode4
diff --git a/lib/extract.F90 b/lib/extract.F90
index 2b580f6..4760aa3 100644
--- a/lib/extract.F90
+++ b/lib/extract.F90
@@ -1,103 +1,120 @@
-subroutine extract(s3,nadd,ncount,nhist,decoded,ltext,nbmkv)
-
-  real s3(64,63)
-  character decoded*22
-  integer era(51),dat4(12),indx(64)
-  integer mrsym(63),mr2sym(63),mrprob(63),mr2prob(63)
-  logical nokv,ltext
-  data nokv/.false./,nsec1/0/
-  save
-
-  nbmkv=0
-  nfail=0
-1 continue
-  call demod64a(s3,nadd,mrsym,mrprob,mr2sym,mr2prob,ntest,nlow)
-  if(ntest.lt.50 .or. nlow.gt.20) then
-     ncount=-999                         !Flag bad data
-     go to 900
-  endif
-  call chkhist(mrsym,nhist,ipk)
-
-  if(nhist.ge.20) then
-     nfail=nfail+1
-     call pctile(s3,4032,50,base)     ! ### or, use ave from demod64a
-     do j=1,63
-        s3(ipk,j)=base
-     enddo
-     if(nfail.gt.30) then
-        decoded='                      '
-        ncount=-1
-        go to 900
-     endif
-     go to 1
-  endif
-
-  call graycode65(mrsym,63,-1)
-  call interleave63(mrsym,-1)
-  call interleave63(mrprob,-1)
-
-! Decode using Berlekamp-Massey algorithm
-  nemax=30                                         !Max BM erasures
-  call indexx(63,mrprob,indx)
-  do i=1,nemax
-     j=indx(i)
-     if(mrprob(j).gt.120) then
-        ne2=i-1
-        go to 2
-     endif
-     era(i)=j-1
-  enddo
-  ne2=nemax
-2 decoded='                      '
-  do nerase=0,ne2,2
-     call rs_decode(mrsym,era,nerase,dat4,ncount)
-     if(ncount.ge.0) then
-        call unpackmsg(dat4,decoded)
-        if(iand(dat4(10),8).ne.0) ltext=.true.
-        nbmkv=1
-        go to 900
-     endif
-  enddo
-
-! Berlekamp-Massey algorithm failed, try Koetter-Vardy
-
-  if(nokv) go to 900
-
-  maxe=8                             !Max KV errors in 12 most reliable symbols
-!  xlambda=12.0
-  xlambda=7.99
-  call graycode65(mr2sym,63,-1)
-  call interleave63(mr2sym,-1)
-  call interleave63(mr2prob,-1)
-
-  nsec1=nsec1+1
-  write(22,rec=1) nsec1,xlambda,maxe,200,mrsym,mrprob,mr2sym,mr2prob
-  call flush(22)
-  call timer('kvasd   ',0)
-#ifdef UNIX
-  iret=system('./kvasd -q > dev_null')
-#else
-  iret=system('kvasd -q > dev_null')
-#endif
-  call timer('kvasd   ',1)
-  if(iret.ne.0) then
-     if(.not.nokv) write(*,1000) 
-1000 format('Error in KV decoder, or no KV decoder present.')
-     nokv=.true.
-     go to 900
-  endif
-
-  read(22,rec=2,err=900) nsec2,ncount,dat4
-  j=nsec2                !Silence compiler warning
-  decoded='                      '
-  ltext=.false.
-  if(ncount.ge.0) then
-     call unpackmsg(dat4,decoded)     !Unpack the user message
-     if(iand(dat4(10),8).ne.0) ltext=.true.
-     nbmkv=2
-  endif
-
-900 continue
-
-  return
-end subroutine extract
+subroutine extract(s3,nadd,nqd,ncount,nhist,decoded,ltext,nbmkv)
+
+! Input:
+!   s3       64-point spectra for each of 63 data symbols
+!   nadd     number of spectra summed into s3
+!   nqd      0/1 to indicate decode attempt at QSO frequency
+
+! Output:
+!   ncount   number of symbols requiring correction
+!   nhist    maximum number of identical symbol values
+!   decoded  decoded message (if ncount >=0)
+!   ltext    true if decoded message is free text
+!   nbmkv    0=no decode; 1=BM decode; 2=KV decode
+
+  use prog_args                       !shm_key, exe_dir, data_dir
+
+  real s3(64,63)
+  character decoded*22
+  integer dat4(12)
+  integer mrsym(63),mr2sym(63),mrprob(63),mr2prob(63)
+  logical nokv,ltext
+  common/decstats/num65,numbm,numkv,num9,numfano
+  data nokv/.false./,nsec1/0/
+  save
+
+  nbirdie=7
+  npct=40
+  afac1=10.1
+  xlambda=7.999
+  if(nqd.eq.1) xlambda=11.999               !Increase depth at QSO frequency
+  nbmkv=0
+  nfail=0
+  decoded='                      '
+  call pctile(s3,4032,npct,base)
+  s3=s3/base
+
+! Get most reliable and second-most-reliable symbol values, and their
+! probabilities
+1 call demod64a(s3,nadd,afac1,mrsym,mrprob,mr2sym,mr2prob,ntest,nlow)
+  if(ntest.lt.100) then
+     ncount=-999                      !Flag and reject bad data
+     go to 900
+  endif
+
+  call chkhist(mrsym,nhist,ipk)       !Test for birdies and QRM
+  if(nhist.ge.nbirdie) then
+     nfail=nfail+1
+     call pctile(s3,4032,npct,base)
+     s3(ipk,1:63)=base
+     if(nfail.gt.30) then
+        decoded='                      '
+        ncount=-1
+        go to 900
+     endif
+     go to 1
+  endif
+
+  call graycode65(mrsym,63,-1)        !Remove gray code and interleaving
+  call interleave63(mrsym,-1)         !from most reliable symbols
+  call interleave63(mrprob,-1)
+  num65=num65+1
+
+! Decode using Berlekamp-Massey algorithm
+  call timer('rs_decod',0)
+  call rs_decode(mrsym,0,0,dat4,ncount)
+  call timer('rs_decod',1)
+  if(ncount.ge.0) then
+     call unpackmsg(dat4,decoded)
+     if(iand(dat4(10),8).ne.0) ltext=.true.
+     nbmkv=1
+     go to 900
+  endif
+
+! Berlekamp-Massey algorithm failed, try Koetter-Vardy
+  if(nokv) go to 900
+
+  maxe=8                             !Max KV errors in 12 most reliable symbols
+  call graycode65(mr2sym,63,-1)      !Remove gray code and interleaving
+  call interleave63(mr2sym,-1)       !from second-most-reliable symbols
+  call interleave63(mr2prob,-1)
+
+  nsec1=nsec1+1
+  dat4=0
+  write(22,rec=1) nsec1,xlambda,maxe,200,mrsym,mrprob,mr2sym,mr2prob
+  write(22,rec=2) -1,-1,dat4
+  call flush(22)
+  call timer('kvasd   ',0)
+
+#ifdef WIN32
+  iret=system('""'//trim(exe_dir)//'/kvasd" "'//trim(temp_dir)//'/kvasd.dat" >"'//trim(temp_dir)//'/dev_null""')
+#else
+  iret=system('"'//trim(exe_dir)//'/kvasd" "'//trim(temp_dir)//'/kvasd.dat" >/dev/null')
+#endif
+
+  call timer('kvasd   ',1)
+  if(iret.ne.0) then
+     if(.not.nokv) write(*,1000) iret
+1000 format('Error in KV decoder, or no KV decoder present.',i12)
+!     nokv=.true.
+     go to 900
+  endif
+
+  read(22,rec=2,err=900) nsec2,ncount,dat4
+  j=nsec2                             !Silence compiler warning
+  decoded='                      '
+  ltext=.false.
+  if(ncount.ge.0) then
+     call unpackmsg(dat4,decoded)     !Unpack the user message
+     if(index(decoded,'...... ').gt.0) then
+        ncount=-1
+        go to 900
+     endif
+     if(iand(dat4(10),8).ne.0) ltext=.true.
+     nbmkv=2
+  endif
+
+900 continue
+
+  return
+end subroutine extract
diff --git a/lib/fano232.f90 b/lib/fano232.f90
index 1e12950..21906da 100644
--- a/lib/fano232.f90
+++ b/lib/fano232.f90
@@ -9,7 +9,7 @@ subroutine fano232(symbol,nbits,mettab,ndelta,maxcycles,dat,     &
   parameter (MAXBYTES=(MAXBITS+7)/8)
   integer*1 symbol(0:2*MAXBITS-1)  !Soft symbols (as unsigned i*1)
   integer*1 dat(MAXBYTES)          !Decoded user data, 8 bits per byte
-  integer mettab(0:255,0:1)        !Metric table
+  integer mettab(-128:127,0:1)        !Metric table
 
 ! These were the "node" structure in Karn's C code:
   integer nstate(0:MAXBITS-1)      !Encoder state of next node
@@ -31,8 +31,6 @@ subroutine fano232(symbol,nbits,mettab,ndelta,maxcycles,dat,     &
      j=2*np
      i4a=symbol(j)
      i4b=symbol(j+1)
-     if (i4a.lt.0) i4a=i4a+256
-     if (i4b.lt.0) i4b=i4b+256
      metrics(0,np) = mettab(i4a,0) + mettab(i4b,0)
      metrics(1,np) = mettab(i4a,0) + mettab(i4b,1)
      metrics(2,np) = mettab(i4a,1) + mettab(i4b,0)
diff --git a/lib/fchisq.f90 b/lib/fchisq.f90
index 1dece10..6eb8b6b 100644
--- a/lib/fchisq.f90
+++ b/lib/fchisq.f90
@@ -34,7 +34,7 @@ real function fchisq(c3,npts,fsample,a)
         sum0=sum0+pp
      endif
   enddo
-  sync=(sum1/16.0)/(sum0/69.0) - 1.0
+  sync=sum1/10000.0
   fchisq=-sync
 
   return
diff --git a/lib/fftw3.f03 b/lib/fftw3.f03
new file mode 100644
index 0000000..ff9c570
--- /dev/null
+++ b/lib/fftw3.f03
@@ -0,0 +1,1246 @@
+! Generated automatically.  DO NOT EDIT!
+
+  integer, parameter :: C_FFTW_R2R_KIND = C_INT32_T
+
+  integer(C_INT), parameter :: FFTW_R2HC = 0
+  integer(C_INT), parameter :: FFTW_HC2R = 1
+  integer(C_INT), parameter :: FFTW_DHT = 2
+  integer(C_INT), parameter :: FFTW_REDFT00 = 3
+  integer(C_INT), parameter :: FFTW_REDFT01 = 4
+  integer(C_INT), parameter :: FFTW_REDFT10 = 5
+  integer(C_INT), parameter :: FFTW_REDFT11 = 6
+  integer(C_INT), parameter :: FFTW_RODFT00 = 7
+  integer(C_INT), parameter :: FFTW_RODFT01 = 8
+  integer(C_INT), parameter :: FFTW_RODFT10 = 9
+  integer(C_INT), parameter :: FFTW_RODFT11 = 10
+  integer(C_INT), parameter :: FFTW_FORWARD = -1
+  integer(C_INT), parameter :: FFTW_BACKWARD = +1
+  integer(C_INT), parameter :: FFTW_MEASURE = 0
+  integer(C_INT), parameter :: FFTW_DESTROY_INPUT = 1
+  integer(C_INT), parameter :: FFTW_UNALIGNED = 2
+  integer(C_INT), parameter :: FFTW_CONSERVE_MEMORY = 4
+  integer(C_INT), parameter :: FFTW_EXHAUSTIVE = 8
+  integer(C_INT), parameter :: FFTW_PRESERVE_INPUT = 16
+  integer(C_INT), parameter :: FFTW_PATIENT = 32
+  integer(C_INT), parameter :: FFTW_ESTIMATE = 64
+  integer(C_INT), parameter :: FFTW_WISDOM_ONLY = 2097152
+  integer(C_INT), parameter :: FFTW_ESTIMATE_PATIENT = 128
+  integer(C_INT), parameter :: FFTW_BELIEVE_PCOST = 256
+  integer(C_INT), parameter :: FFTW_NO_DFT_R2HC = 512
+  integer(C_INT), parameter :: FFTW_NO_NONTHREADED = 1024
+  integer(C_INT), parameter :: FFTW_NO_BUFFERING = 2048
+  integer(C_INT), parameter :: FFTW_NO_INDIRECT_OP = 4096
+  integer(C_INT), parameter :: FFTW_ALLOW_LARGE_GENERIC = 8192
+  integer(C_INT), parameter :: FFTW_NO_RANK_SPLITS = 16384
+  integer(C_INT), parameter :: FFTW_NO_VRANK_SPLITS = 32768
+  integer(C_INT), parameter :: FFTW_NO_VRECURSE = 65536
+  integer(C_INT), parameter :: FFTW_NO_SIMD = 131072
+  integer(C_INT), parameter :: FFTW_NO_SLOW = 262144
+  integer(C_INT), parameter :: FFTW_NO_FIXED_RADIX_LARGE_N = 524288
+  integer(C_INT), parameter :: FFTW_ALLOW_PRUNING = 1048576
+
+  type, bind(C) :: fftw_iodim
+     integer(C_INT) n, is, os
+  end type fftw_iodim
+  type, bind(C) :: fftw_iodim64
+     integer(C_INTPTR_T) n, is, os
+  end type fftw_iodim64
+
+  interface
+    type(C_PTR) function fftw_plan_dft(rank,n,in,out,sign,flags) bind(C, name='fftw_plan_dft')
+      import
+      integer(C_INT), value :: rank
+      integer(C_INT), dimension(*), intent(in) :: n
+      complex(C_DOUBLE_COMPLEX), dimension(*), intent(out) :: in
+      complex(C_DOUBLE_COMPLEX), dimension(*), intent(out) :: out
+      integer(C_INT), value :: sign
+      integer(C_INT), value :: flags
+    end function fftw_plan_dft
+    
+    type(C_PTR) function fftw_plan_dft_1d(n,in,out,sign,flags) bind(C, name='fftw_plan_dft_1d')
+      import
+      integer(C_INT), value :: n
+      complex(C_DOUBLE_COMPLEX), dimension(*), intent(out) :: in
+      complex(C_DOUBLE_COMPLEX), dimension(*), intent(out) :: out
+      integer(C_INT), value :: sign
+      integer(C_INT), value :: flags
+    end function fftw_plan_dft_1d
+    
+    type(C_PTR) function fftw_plan_dft_2d(n0,n1,in,out,sign,flags) bind(C, name='fftw_plan_dft_2d')
+      import
+      integer(C_INT), value :: n0
+      integer(C_INT), value :: n1
+      complex(C_DOUBLE_COMPLEX), dimension(*), intent(out) :: in
+      complex(C_DOUBLE_COMPLEX), dimension(*), intent(out) :: out
+      integer(C_INT), value :: sign
+      integer(C_INT), value :: flags
+    end function fftw_plan_dft_2d
+    
+    type(C_PTR) function fftw_plan_dft_3d(n0,n1,n2,in,out,sign,flags) bind(C, name='fftw_plan_dft_3d')
+      import
+      integer(C_INT), value :: n0
+      integer(C_INT), value :: n1
+      integer(C_INT), value :: n2
+      complex(C_DOUBLE_COMPLEX), dimension(*), intent(out) :: in
+      complex(C_DOUBLE_COMPLEX), dimension(*), intent(out) :: out
+      integer(C_INT), value :: sign
+      integer(C_INT), value :: flags
+    end function fftw_plan_dft_3d
+    
+    type(C_PTR) function fftw_plan_many_dft(rank,n,howmany,in,inembed,istride,idist,out,onembed,ostride,odist,sign,flags) &
+                         bind(C, name='fftw_plan_many_dft')
+      import
+      integer(C_INT), value :: rank
+      integer(C_INT), dimension(*), intent(in) :: n
+      integer(C_INT), value :: howmany
+      complex(C_DOUBLE_COMPLEX), dimension(*), intent(out) :: in
+      integer(C_INT), dimension(*), intent(in) :: inembed
+      integer(C_INT), value :: istride
+      integer(C_INT), value :: idist
+      complex(C_DOUBLE_COMPLEX), dimension(*), intent(out) :: out
+      integer(C_INT), dimension(*), intent(in) :: onembed
+      integer(C_INT), value :: ostride
+      integer(C_INT), value :: odist
+      integer(C_INT), value :: sign
+      integer(C_INT), value :: flags
+    end function fftw_plan_many_dft
+    
+    type(C_PTR) function fftw_plan_guru_dft(rank,dims,howmany_rank,howmany_dims,in,out,sign,flags) &
+                         bind(C, name='fftw_plan_guru_dft')
+      import
+      integer(C_INT), value :: rank
+      type(fftw_iodim), dimension(*), intent(in) :: dims
+      integer(C_INT), value :: howmany_rank
+      type(fftw_iodim), dimension(*), intent(in) :: howmany_dims
+      complex(C_DOUBLE_COMPLEX), dimension(*), intent(out) :: in
+      complex(C_DOUBLE_COMPLEX), dimension(*), intent(out) :: out
+      integer(C_INT), value :: sign
+      integer(C_INT), value :: flags
+    end function fftw_plan_guru_dft
+    
+    type(C_PTR) function fftw_plan_guru_split_dft(rank,dims,howmany_rank,howmany_dims,ri,ii,ro,io,flags) &
+                         bind(C, name='fftw_plan_guru_split_dft')
+      import
+      integer(C_INT), value :: rank
+      type(fftw_iodim), dimension(*), intent(in) :: dims
+      integer(C_INT), value :: howmany_rank
+      type(fftw_iodim), dimension(*), intent(in) :: howmany_dims
+      real(C_DOUBLE), dimension(*), intent(out) :: ri
+      real(C_DOUBLE), dimension(*), intent(out) :: ii
+      real(C_DOUBLE), dimension(*), intent(out) :: ro
+      real(C_DOUBLE), dimension(*), intent(out) :: io
+      integer(C_INT), value :: flags
+    end function fftw_plan_guru_split_dft
+    
+    type(C_PTR) function fftw_plan_guru64_dft(rank,dims,howmany_rank,howmany_dims,in,out,sign,flags) &
+                         bind(C, name='fftw_plan_guru64_dft')
+      import
+      integer(C_INT), value :: rank
+      type(fftw_iodim64), dimension(*), intent(in) :: dims
+      integer(C_INT), value :: howmany_rank
+      type(fftw_iodim64), dimension(*), intent(in) :: howmany_dims
+      complex(C_DOUBLE_COMPLEX), dimension(*), intent(out) :: in
+      complex(C_DOUBLE_COMPLEX), dimension(*), intent(out) :: out
+      integer(C_INT), value :: sign
+      integer(C_INT), value :: flags
+    end function fftw_plan_guru64_dft
+    
+    type(C_PTR) function fftw_plan_guru64_split_dft(rank,dims,howmany_rank,howmany_dims,ri,ii,ro,io,flags) &
+                         bind(C, name='fftw_plan_guru64_split_dft')
+      import
+      integer(C_INT), value :: rank
+      type(fftw_iodim64), dimension(*), intent(in) :: dims
+      integer(C_INT), value :: howmany_rank
+      type(fftw_iodim64), dimension(*), intent(in) :: howmany_dims
+      real(C_DOUBLE), dimension(*), intent(out) :: ri
+      real(C_DOUBLE), dimension(*), intent(out) :: ii
+      real(C_DOUBLE), dimension(*), intent(out) :: ro
+      real(C_DOUBLE), dimension(*), intent(out) :: io
+      integer(C_INT), value :: flags
+    end function fftw_plan_guru64_split_dft
+    
+    subroutine fftw_execute_dft(p,in,out) bind(C, name='fftw_execute_dft')
+      import
+      type(C_PTR), value :: p
+      complex(C_DOUBLE_COMPLEX), dimension(*), intent(inout) :: in
+      complex(C_DOUBLE_COMPLEX), dimension(*), intent(out) :: out
+    end subroutine fftw_execute_dft
+    
+    subroutine fftw_execute_split_dft(p,ri,ii,ro,io) bind(C, name='fftw_execute_split_dft')
+      import
+      type(C_PTR), value :: p
+      real(C_DOUBLE), dimension(*), intent(inout) :: ri
+      real(C_DOUBLE), dimension(*), intent(inout) :: ii
+      real(C_DOUBLE), dimension(*), intent(out) :: ro
+      real(C_DOUBLE), dimension(*), intent(out) :: io
+    end subroutine fftw_execute_split_dft
+    
+    type(C_PTR) function fftw_plan_many_dft_r2c(rank,n,howmany,in,inembed,istride,idist,out,onembed,ostride,odist,flags) &
+                         bind(C, name='fftw_plan_many_dft_r2c')
+      import
+      integer(C_INT), value :: rank
+      integer(C_INT), dimension(*), intent(in) :: n
+      integer(C_INT), value :: howmany
+      real(C_DOUBLE), dimension(*), intent(out) :: in
+      integer(C_INT), dimension(*), intent(in) :: inembed
+      integer(C_INT), value :: istride
+      integer(C_INT), value :: idist
+      complex(C_DOUBLE_COMPLEX), dimension(*), intent(out) :: out
+      integer(C_INT), dimension(*), intent(in) :: onembed
+      integer(C_INT), value :: ostride
+      integer(C_INT), value :: odist
+      integer(C_INT), value :: flags
+    end function fftw_plan_many_dft_r2c
+    
+    type(C_PTR) function fftw_plan_dft_r2c(rank,n,in,out,flags) bind(C, name='fftw_plan_dft_r2c')
+      import
+      integer(C_INT), value :: rank
+      integer(C_INT), dimension(*), intent(in) :: n
+      real(C_DOUBLE), dimension(*), intent(out) :: in
+      complex(C_DOUBLE_COMPLEX), dimension(*), intent(out) :: out
+      integer(C_INT), value :: flags
+    end function fftw_plan_dft_r2c
+    
+    type(C_PTR) function fftw_plan_dft_r2c_1d(n,in,out,flags) bind(C, name='fftw_plan_dft_r2c_1d')
+      import
+      integer(C_INT), value :: n
+      real(C_DOUBLE), dimension(*), intent(out) :: in
+      complex(C_DOUBLE_COMPLEX), dimension(*), intent(out) :: out
+      integer(C_INT), value :: flags
+    end function fftw_plan_dft_r2c_1d
+    
+    type(C_PTR) function fftw_plan_dft_r2c_2d(n0,n1,in,out,flags) bind(C, name='fftw_plan_dft_r2c_2d')
+      import
+      integer(C_INT), value :: n0
+      integer(C_INT), value :: n1
+      real(C_DOUBLE), dimension(*), intent(out) :: in
+      complex(C_DOUBLE_COMPLEX), dimension(*), intent(out) :: out
+      integer(C_INT), value :: flags
+    end function fftw_plan_dft_r2c_2d
+    
+    type(C_PTR) function fftw_plan_dft_r2c_3d(n0,n1,n2,in,out,flags) bind(C, name='fftw_plan_dft_r2c_3d')
+      import
+      integer(C_INT), value :: n0
+      integer(C_INT), value :: n1
+      integer(C_INT), value :: n2
+      real(C_DOUBLE), dimension(*), intent(out) :: in
+      complex(C_DOUBLE_COMPLEX), dimension(*), intent(out) :: out
+      integer(C_INT), value :: flags
+    end function fftw_plan_dft_r2c_3d
+    
+    type(C_PTR) function fftw_plan_many_dft_c2r(rank,n,howmany,in,inembed,istride,idist,out,onembed,ostride,odist,flags) &
+                         bind(C, name='fftw_plan_many_dft_c2r')
+      import
+      integer(C_INT), value :: rank
+      integer(C_INT), dimension(*), intent(in) :: n
+      integer(C_INT), value :: howmany
+      complex(C_DOUBLE_COMPLEX), dimension(*), intent(out) :: in
+      integer(C_INT), dimension(*), intent(in) :: inembed
+      integer(C_INT), value :: istride
+      integer(C_INT), value :: idist
+      real(C_DOUBLE), dimension(*), intent(out) :: out
+      integer(C_INT), dimension(*), intent(in) :: onembed
+      integer(C_INT), value :: ostride
+      integer(C_INT), value :: odist
+      integer(C_INT), value :: flags
+    end function fftw_plan_many_dft_c2r
+    
+    type(C_PTR) function fftw_plan_dft_c2r(rank,n,in,out,flags) bind(C, name='fftw_plan_dft_c2r')
+      import
+      integer(C_INT), value :: rank
+      integer(C_INT), dimension(*), intent(in) :: n
+      complex(C_DOUBLE_COMPLEX), dimension(*), intent(out) :: in
+      real(C_DOUBLE), dimension(*), intent(out) :: out
+      integer(C_INT), value :: flags
+    end function fftw_plan_dft_c2r
+    
+    type(C_PTR) function fftw_plan_dft_c2r_1d(n,in,out,flags) bind(C, name='fftw_plan_dft_c2r_1d')
+      import
+      integer(C_INT), value :: n
+      complex(C_DOUBLE_COMPLEX), dimension(*), intent(out) :: in
+      real(C_DOUBLE), dimension(*), intent(out) :: out
+      integer(C_INT), value :: flags
+    end function fftw_plan_dft_c2r_1d
+    
+    type(C_PTR) function fftw_plan_dft_c2r_2d(n0,n1,in,out,flags) bind(C, name='fftw_plan_dft_c2r_2d')
+      import
+      integer(C_INT), value :: n0
+      integer(C_INT), value :: n1
+      complex(C_DOUBLE_COMPLEX), dimension(*), intent(out) :: in
+      real(C_DOUBLE), dimension(*), intent(out) :: out
+      integer(C_INT), value :: flags
+    end function fftw_plan_dft_c2r_2d
+    
+    type(C_PTR) function fftw_plan_dft_c2r_3d(n0,n1,n2,in,out,flags) bind(C, name='fftw_plan_dft_c2r_3d')
+      import
+      integer(C_INT), value :: n0
+      integer(C_INT), value :: n1
+      integer(C_INT), value :: n2
+      complex(C_DOUBLE_COMPLEX), dimension(*), intent(out) :: in
+      real(C_DOUBLE), dimension(*), intent(out) :: out
+      integer(C_INT), value :: flags
+    end function fftw_plan_dft_c2r_3d
+    
+    type(C_PTR) function fftw_plan_guru_dft_r2c(rank,dims,howmany_rank,howmany_dims,in,out,flags) &
+                         bind(C, name='fftw_plan_guru_dft_r2c')
+      import
+      integer(C_INT), value :: rank
+      type(fftw_iodim), dimension(*), intent(in) :: dims
+      integer(C_INT), value :: howmany_rank
+      type(fftw_iodim), dimension(*), intent(in) :: howmany_dims
+      real(C_DOUBLE), dimension(*), intent(out) :: in
+      complex(C_DOUBLE_COMPLEX), dimension(*), intent(out) :: out
+      integer(C_INT), value :: flags
+    end function fftw_plan_guru_dft_r2c
+    
+    type(C_PTR) function fftw_plan_guru_dft_c2r(rank,dims,howmany_rank,howmany_dims,in,out,flags) &
+                         bind(C, name='fftw_plan_guru_dft_c2r')
+      import
+      integer(C_INT), value :: rank
+      type(fftw_iodim), dimension(*), intent(in) :: dims
+      integer(C_INT), value :: howmany_rank
+      type(fftw_iodim), dimension(*), intent(in) :: howmany_dims
+      complex(C_DOUBLE_COMPLEX), dimension(*), intent(out) :: in
+      real(C_DOUBLE), dimension(*), intent(out) :: out
+      integer(C_INT), value :: flags
+    end function fftw_plan_guru_dft_c2r
+    
+    type(C_PTR) function fftw_plan_guru_split_dft_r2c(rank,dims,howmany_rank,howmany_dims,in,ro,io,flags) &
+                         bind(C, name='fftw_plan_guru_split_dft_r2c')
+      import
+      integer(C_INT), value :: rank
+      type(fftw_iodim), dimension(*), intent(in) :: dims
+      integer(C_INT), value :: howmany_rank
+      type(fftw_iodim), dimension(*), intent(in) :: howmany_dims
+      real(C_DOUBLE), dimension(*), intent(out) :: in
+      real(C_DOUBLE), dimension(*), intent(out) :: ro
+      real(C_DOUBLE), dimension(*), intent(out) :: io
+      integer(C_INT), value :: flags
+    end function fftw_plan_guru_split_dft_r2c
+    
+    type(C_PTR) function fftw_plan_guru_split_dft_c2r(rank,dims,howmany_rank,howmany_dims,ri,ii,out,flags) &
+                         bind(C, name='fftw_plan_guru_split_dft_c2r')
+      import
+      integer(C_INT), value :: rank
+      type(fftw_iodim), dimension(*), intent(in) :: dims
+      integer(C_INT), value :: howmany_rank
+      type(fftw_iodim), dimension(*), intent(in) :: howmany_dims
+      real(C_DOUBLE), dimension(*), intent(out) :: ri
+      real(C_DOUBLE), dimension(*), intent(out) :: ii
+      real(C_DOUBLE), dimension(*), intent(out) :: out
+      integer(C_INT), value :: flags
+    end function fftw_plan_guru_split_dft_c2r
+    
+    type(C_PTR) function fftw_plan_guru64_dft_r2c(rank,dims,howmany_rank,howmany_dims,in,out,flags) &
+                         bind(C, name='fftw_plan_guru64_dft_r2c')
+      import
+      integer(C_INT), value :: rank
+      type(fftw_iodim64), dimension(*), intent(in) :: dims
+      integer(C_INT), value :: howmany_rank
+      type(fftw_iodim64), dimension(*), intent(in) :: howmany_dims
+      real(C_DOUBLE), dimension(*), intent(out) :: in
+      complex(C_DOUBLE_COMPLEX), dimension(*), intent(out) :: out
+      integer(C_INT), value :: flags
+    end function fftw_plan_guru64_dft_r2c
+    
+    type(C_PTR) function fftw_plan_guru64_dft_c2r(rank,dims,howmany_rank,howmany_dims,in,out,flags) &
+                         bind(C, name='fftw_plan_guru64_dft_c2r')
+      import
+      integer(C_INT), value :: rank
+      type(fftw_iodim64), dimension(*), intent(in) :: dims
+      integer(C_INT), value :: howmany_rank
+      type(fftw_iodim64), dimension(*), intent(in) :: howmany_dims
+      complex(C_DOUBLE_COMPLEX), dimension(*), intent(out) :: in
+      real(C_DOUBLE), dimension(*), intent(out) :: out
+      integer(C_INT), value :: flags
+    end function fftw_plan_guru64_dft_c2r
+    
+    type(C_PTR) function fftw_plan_guru64_split_dft_r2c(rank,dims,howmany_rank,howmany_dims,in,ro,io,flags) &
+                         bind(C, name='fftw_plan_guru64_split_dft_r2c')
+      import
+      integer(C_INT), value :: rank
+      type(fftw_iodim64), dimension(*), intent(in) :: dims
+      integer(C_INT), value :: howmany_rank
+      type(fftw_iodim64), dimension(*), intent(in) :: howmany_dims
+      real(C_DOUBLE), dimension(*), intent(out) :: in
+      real(C_DOUBLE), dimension(*), intent(out) :: ro
+      real(C_DOUBLE), dimension(*), intent(out) :: io
+      integer(C_INT), value :: flags
+    end function fftw_plan_guru64_split_dft_r2c
+    
+    type(C_PTR) function fftw_plan_guru64_split_dft_c2r(rank,dims,howmany_rank,howmany_dims,ri,ii,out,flags) &
+                         bind(C, name='fftw_plan_guru64_split_dft_c2r')
+      import
+      integer(C_INT), value :: rank
+      type(fftw_iodim64), dimension(*), intent(in) :: dims
+      integer(C_INT), value :: howmany_rank
+      type(fftw_iodim64), dimension(*), intent(in) :: howmany_dims
+      real(C_DOUBLE), dimension(*), intent(out) :: ri
+      real(C_DOUBLE), dimension(*), intent(out) :: ii
+      real(C_DOUBLE), dimension(*), intent(out) :: out
+      integer(C_INT), value :: flags
+    end function fftw_plan_guru64_split_dft_c2r
+    
+    subroutine fftw_execute_dft_r2c(p,in,out) bind(C, name='fftw_execute_dft_r2c')
+      import
+      type(C_PTR), value :: p
+      real(C_DOUBLE), dimension(*), intent(inout) :: in
+      complex(C_DOUBLE_COMPLEX), dimension(*), intent(out) :: out
+    end subroutine fftw_execute_dft_r2c
+    
+    subroutine fftw_execute_dft_c2r(p,in,out) bind(C, name='fftw_execute_dft_c2r')
+      import
+      type(C_PTR), value :: p
+      complex(C_DOUBLE_COMPLEX), dimension(*), intent(inout) :: in
+      real(C_DOUBLE), dimension(*), intent(out) :: out
+    end subroutine fftw_execute_dft_c2r
+    
+    subroutine fftw_execute_split_dft_r2c(p,in,ro,io) bind(C, name='fftw_execute_split_dft_r2c')
+      import
+      type(C_PTR), value :: p
+      real(C_DOUBLE), dimension(*), intent(inout) :: in
+      real(C_DOUBLE), dimension(*), intent(out) :: ro
+      real(C_DOUBLE), dimension(*), intent(out) :: io
+    end subroutine fftw_execute_split_dft_r2c
+    
+    subroutine fftw_execute_split_dft_c2r(p,ri,ii,out) bind(C, name='fftw_execute_split_dft_c2r')
+      import
+      type(C_PTR), value :: p
+      real(C_DOUBLE), dimension(*), intent(inout) :: ri
+      real(C_DOUBLE), dimension(*), intent(inout) :: ii
+      real(C_DOUBLE), dimension(*), intent(out) :: out
+    end subroutine fftw_execute_split_dft_c2r
+    
+    type(C_PTR) function fftw_plan_many_r2r(rank,n,howmany,in,inembed,istride,idist,out,onembed,ostride,odist,kind,flags) &
+                         bind(C, name='fftw_plan_many_r2r')
+      import
+      integer(C_INT), value :: rank
+      integer(C_INT), dimension(*), intent(in) :: n
+      integer(C_INT), value :: howmany
+      real(C_DOUBLE), dimension(*), intent(out) :: in
+      integer(C_INT), dimension(*), intent(in) :: inembed
+      integer(C_INT), value :: istride
+      integer(C_INT), value :: idist
+      real(C_DOUBLE), dimension(*), intent(out) :: out
+      integer(C_INT), dimension(*), intent(in) :: onembed
+      integer(C_INT), value :: ostride
+      integer(C_INT), value :: odist
+      integer(C_FFTW_R2R_KIND), dimension(*), intent(in) :: kind
+      integer(C_INT), value :: flags
+    end function fftw_plan_many_r2r
+    
+    type(C_PTR) function fftw_plan_r2r(rank,n,in,out,kind,flags) bind(C, name='fftw_plan_r2r')
+      import
+      integer(C_INT), value :: rank
+      integer(C_INT), dimension(*), intent(in) :: n
+      real(C_DOUBLE), dimension(*), intent(out) :: in
+      real(C_DOUBLE), dimension(*), intent(out) :: out
+      integer(C_FFTW_R2R_KIND), dimension(*), intent(in) :: kind
+      integer(C_INT), value :: flags
+    end function fftw_plan_r2r
+    
+    type(C_PTR) function fftw_plan_r2r_1d(n,in,out,kind,flags) bind(C, name='fftw_plan_r2r_1d')
+      import
+      integer(C_INT), value :: n
+      real(C_DOUBLE), dimension(*), intent(out) :: in
+      real(C_DOUBLE), dimension(*), intent(out) :: out
+      integer(C_FFTW_R2R_KIND), value :: kind
+      integer(C_INT), value :: flags
+    end function fftw_plan_r2r_1d
+    
+    type(C_PTR) function fftw_plan_r2r_2d(n0,n1,in,out,kind0,kind1,flags) bind(C, name='fftw_plan_r2r_2d')
+      import
+      integer(C_INT), value :: n0
+      integer(C_INT), value :: n1
+      real(C_DOUBLE), dimension(*), intent(out) :: in
+      real(C_DOUBLE), dimension(*), intent(out) :: out
+      integer(C_FFTW_R2R_KIND), value :: kind0
+      integer(C_FFTW_R2R_KIND), value :: kind1
+      integer(C_INT), value :: flags
+    end function fftw_plan_r2r_2d
+    
+    type(C_PTR) function fftw_plan_r2r_3d(n0,n1,n2,in,out,kind0,kind1,kind2,flags) bind(C, name='fftw_plan_r2r_3d')
+      import
+      integer(C_INT), value :: n0
+      integer(C_INT), value :: n1
+      integer(C_INT), value :: n2
+      real(C_DOUBLE), dimension(*), intent(out) :: in
+      real(C_DOUBLE), dimension(*), intent(out) :: out
+      integer(C_FFTW_R2R_KIND), value :: kind0
+      integer(C_FFTW_R2R_KIND), value :: kind1
+      integer(C_FFTW_R2R_KIND), value :: kind2
+      integer(C_INT), value :: flags
+    end function fftw_plan_r2r_3d
+    
+    type(C_PTR) function fftw_plan_guru_r2r(rank,dims,howmany_rank,howmany_dims,in,out,kind,flags) &
+                         bind(C, name='fftw_plan_guru_r2r')
+      import
+      integer(C_INT), value :: rank
+      type(fftw_iodim), dimension(*), intent(in) :: dims
+      integer(C_INT), value :: howmany_rank
+      type(fftw_iodim), dimension(*), intent(in) :: howmany_dims
+      real(C_DOUBLE), dimension(*), intent(out) :: in
+      real(C_DOUBLE), dimension(*), intent(out) :: out
+      integer(C_FFTW_R2R_KIND), dimension(*), intent(in) :: kind
+      integer(C_INT), value :: flags
+    end function fftw_plan_guru_r2r
+    
+    type(C_PTR) function fftw_plan_guru64_r2r(rank,dims,howmany_rank,howmany_dims,in,out,kind,flags) &
+                         bind(C, name='fftw_plan_guru64_r2r')
+      import
+      integer(C_INT), value :: rank
+      type(fftw_iodim64), dimension(*), intent(in) :: dims
+      integer(C_INT), value :: howmany_rank
+      type(fftw_iodim64), dimension(*), intent(in) :: howmany_dims
+      real(C_DOUBLE), dimension(*), intent(out) :: in
+      real(C_DOUBLE), dimension(*), intent(out) :: out
+      integer(C_FFTW_R2R_KIND), dimension(*), intent(in) :: kind
+      integer(C_INT), value :: flags
+    end function fftw_plan_guru64_r2r
+    
+    subroutine fftw_execute_r2r(p,in,out) bind(C, name='fftw_execute_r2r')
+      import
+      type(C_PTR), value :: p
+      real(C_DOUBLE), dimension(*), intent(inout) :: in
+      real(C_DOUBLE), dimension(*), intent(out) :: out
+    end subroutine fftw_execute_r2r
+    
+    subroutine fftw_destroy_plan(p) bind(C, name='fftw_destroy_plan')
+      import
+      type(C_PTR), value :: p
+    end subroutine fftw_destroy_plan
+    
+    subroutine fftw_forget_wisdom() bind(C, name='fftw_forget_wisdom')
+      import
+    end subroutine fftw_forget_wisdom
+    
+    subroutine fftw_cleanup() bind(C, name='fftw_cleanup')
+      import
+    end subroutine fftw_cleanup
+    
+    subroutine fftw_set_timelimit(t) bind(C, name='fftw_set_timelimit')
+      import
+      real(C_DOUBLE), value :: t
+    end subroutine fftw_set_timelimit
+    
+    subroutine fftw_plan_with_nthreads(nthreads) bind(C, name='fftw_plan_with_nthreads')
+      import
+      integer(C_INT), value :: nthreads
+    end subroutine fftw_plan_with_nthreads
+    
+    integer(C_INT) function fftw_init_threads() bind(C, name='fftw_init_threads')
+      import
+    end function fftw_init_threads
+    
+    subroutine fftw_cleanup_threads() bind(C, name='fftw_cleanup_threads')
+      import
+    end subroutine fftw_cleanup_threads
+    
+    integer(C_INT) function fftw_export_wisdom_to_filename(filename) bind(C, name='fftw_export_wisdom_to_filename')
+      import
+      character(C_CHAR), dimension(*), intent(in) :: filename
+    end function fftw_export_wisdom_to_filename
+    
+    subroutine fftw_export_wisdom_to_file(output_file) bind(C, name='fftw_export_wisdom_to_file')
+      import
+      type(C_PTR), value :: output_file
+    end subroutine fftw_export_wisdom_to_file
+    
+    type(C_PTR) function fftw_export_wisdom_to_string() bind(C, name='fftw_export_wisdom_to_string')
+      import
+    end function fftw_export_wisdom_to_string
+    
+    subroutine fftw_export_wisdom(write_char,data) bind(C, name='fftw_export_wisdom')
+      import
+      type(C_FUNPTR), value :: write_char
+      type(C_PTR), value :: data
+    end subroutine fftw_export_wisdom
+    
+    integer(C_INT) function fftw_import_system_wisdom() bind(C, name='fftw_import_system_wisdom')
+      import
+    end function fftw_import_system_wisdom
+    
+    integer(C_INT) function fftw_import_wisdom_from_filename(filename) bind(C, name='fftw_import_wisdom_from_filename')
+      import
+      character(C_CHAR), dimension(*), intent(in) :: filename
+    end function fftw_import_wisdom_from_filename
+    
+    integer(C_INT) function fftw_import_wisdom_from_file(input_file) bind(C, name='fftw_import_wisdom_from_file')
+      import
+      type(C_PTR), value :: input_file
+    end function fftw_import_wisdom_from_file
+    
+    integer(C_INT) function fftw_import_wisdom_from_string(input_string) bind(C, name='fftw_import_wisdom_from_string')
+      import
+      character(C_CHAR), dimension(*), intent(in) :: input_string
+    end function fftw_import_wisdom_from_string
+    
+    integer(C_INT) function fftw_import_wisdom(read_char,data) bind(C, name='fftw_import_wisdom')
+      import
+      type(C_FUNPTR), value :: read_char
+      type(C_PTR), value :: data
+    end function fftw_import_wisdom
+    
+    subroutine fftw_fprint_plan(p,output_file) bind(C, name='fftw_fprint_plan')
+      import
+      type(C_PTR), value :: p
+      type(C_PTR), value :: output_file
+    end subroutine fftw_fprint_plan
+    
+    subroutine fftw_print_plan(p) bind(C, name='fftw_print_plan')
+      import
+      type(C_PTR), value :: p
+    end subroutine fftw_print_plan
+    
+    type(C_PTR) function fftw_sprint_plan(p) bind(C, name='fftw_sprint_plan')
+      import
+      type(C_PTR), value :: p
+    end function fftw_sprint_plan
+    
+    type(C_PTR) function fftw_malloc(n) bind(C, name='fftw_malloc')
+      import
+      integer(C_SIZE_T), value :: n
+    end function fftw_malloc
+    
+    type(C_PTR) function fftw_alloc_real(n) bind(C, name='fftw_alloc_real')
+      import
+      integer(C_SIZE_T), value :: n
+    end function fftw_alloc_real
+    
+    type(C_PTR) function fftw_alloc_complex(n) bind(C, name='fftw_alloc_complex')
+      import
+      integer(C_SIZE_T), value :: n
+    end function fftw_alloc_complex
+    
+    subroutine fftw_free(p) bind(C, name='fftw_free')
+      import
+      type(C_PTR), value :: p
+    end subroutine fftw_free
+    
+    subroutine fftw_flops(p,add,mul,fmas) bind(C, name='fftw_flops')
+      import
+      type(C_PTR), value :: p
+      real(C_DOUBLE), intent(out) :: add
+      real(C_DOUBLE), intent(out) :: mul
+      real(C_DOUBLE), intent(out) :: fmas
+    end subroutine fftw_flops
+    
+    real(C_DOUBLE) function fftw_estimate_cost(p) bind(C, name='fftw_estimate_cost')
+      import
+      type(C_PTR), value :: p
+    end function fftw_estimate_cost
+    
+    real(C_DOUBLE) function fftw_cost(p) bind(C, name='fftw_cost')
+      import
+      type(C_PTR), value :: p
+    end function fftw_cost
+    
+    integer(C_INT) function fftw_alignment_of(p) bind(C, name='fftw_alignment_of')
+      import
+      real(C_DOUBLE), dimension(*), intent(out) :: p
+    end function fftw_alignment_of
+    
+  end interface
+
+  type, bind(C) :: fftwf_iodim
+     integer(C_INT) n, is, os
+  end type fftwf_iodim
+  type, bind(C) :: fftwf_iodim64
+     integer(C_INTPTR_T) n, is, os
+  end type fftwf_iodim64
+
+  interface
+    type(C_PTR) function fftwf_plan_dft(rank,n,in,out,sign,flags) bind(C, name='fftwf_plan_dft')
+      import
+      integer(C_INT), value :: rank
+      integer(C_INT), dimension(*), intent(in) :: n
+      complex(C_FLOAT_COMPLEX), dimension(*), intent(out) :: in
+      complex(C_FLOAT_COMPLEX), dimension(*), intent(out) :: out
+      integer(C_INT), value :: sign
+      integer(C_INT), value :: flags
+    end function fftwf_plan_dft
+    
+    type(C_PTR) function fftwf_plan_dft_1d(n,in,out,sign,flags) bind(C, name='fftwf_plan_dft_1d')
+      import
+      integer(C_INT), value :: n
+      complex(C_FLOAT_COMPLEX), dimension(*), intent(out) :: in
+      complex(C_FLOAT_COMPLEX), dimension(*), intent(out) :: out
+      integer(C_INT), value :: sign
+      integer(C_INT), value :: flags
+    end function fftwf_plan_dft_1d
+    
+    type(C_PTR) function fftwf_plan_dft_2d(n0,n1,in,out,sign,flags) bind(C, name='fftwf_plan_dft_2d')
+      import
+      integer(C_INT), value :: n0
+      integer(C_INT), value :: n1
+      complex(C_FLOAT_COMPLEX), dimension(*), intent(out) :: in
+      complex(C_FLOAT_COMPLEX), dimension(*), intent(out) :: out
+      integer(C_INT), value :: sign
+      integer(C_INT), value :: flags
+    end function fftwf_plan_dft_2d
+    
+    type(C_PTR) function fftwf_plan_dft_3d(n0,n1,n2,in,out,sign,flags) bind(C, name='fftwf_plan_dft_3d')
+      import
+      integer(C_INT), value :: n0
+      integer(C_INT), value :: n1
+      integer(C_INT), value :: n2
+      complex(C_FLOAT_COMPLEX), dimension(*), intent(out) :: in
+      complex(C_FLOAT_COMPLEX), dimension(*), intent(out) :: out
+      integer(C_INT), value :: sign
+      integer(C_INT), value :: flags
+    end function fftwf_plan_dft_3d
+    
+    type(C_PTR) function fftwf_plan_many_dft(rank,n,howmany,in,inembed,istride,idist,out,onembed,ostride,odist,sign,flags) &
+                         bind(C, name='fftwf_plan_many_dft')
+      import
+      integer(C_INT), value :: rank
+      integer(C_INT), dimension(*), intent(in) :: n
+      integer(C_INT), value :: howmany
+      complex(C_FLOAT_COMPLEX), dimension(*), intent(out) :: in
+      integer(C_INT), dimension(*), intent(in) :: inembed
+      integer(C_INT), value :: istride
+      integer(C_INT), value :: idist
+      complex(C_FLOAT_COMPLEX), dimension(*), intent(out) :: out
+      integer(C_INT), dimension(*), intent(in) :: onembed
+      integer(C_INT), value :: ostride
+      integer(C_INT), value :: odist
+      integer(C_INT), value :: sign
+      integer(C_INT), value :: flags
+    end function fftwf_plan_many_dft
+    
+    type(C_PTR) function fftwf_plan_guru_dft(rank,dims,howmany_rank,howmany_dims,in,out,sign,flags) &
+                         bind(C, name='fftwf_plan_guru_dft')
+      import
+      integer(C_INT), value :: rank
+      type(fftwf_iodim), dimension(*), intent(in) :: dims
+      integer(C_INT), value :: howmany_rank
+      type(fftwf_iodim), dimension(*), intent(in) :: howmany_dims
+      complex(C_FLOAT_COMPLEX), dimension(*), intent(out) :: in
+      complex(C_FLOAT_COMPLEX), dimension(*), intent(out) :: out
+      integer(C_INT), value :: sign
+      integer(C_INT), value :: flags
+    end function fftwf_plan_guru_dft
+    
+    type(C_PTR) function fftwf_plan_guru_split_dft(rank,dims,howmany_rank,howmany_dims,ri,ii,ro,io,flags) &
+                         bind(C, name='fftwf_plan_guru_split_dft')
+      import
+      integer(C_INT), value :: rank
+      type(fftwf_iodim), dimension(*), intent(in) :: dims
+      integer(C_INT), value :: howmany_rank
+      type(fftwf_iodim), dimension(*), intent(in) :: howmany_dims
+      real(C_FLOAT), dimension(*), intent(out) :: ri
+      real(C_FLOAT), dimension(*), intent(out) :: ii
+      real(C_FLOAT), dimension(*), intent(out) :: ro
+      real(C_FLOAT), dimension(*), intent(out) :: io
+      integer(C_INT), value :: flags
+    end function fftwf_plan_guru_split_dft
+    
+    type(C_PTR) function fftwf_plan_guru64_dft(rank,dims,howmany_rank,howmany_dims,in,out,sign,flags) &
+                         bind(C, name='fftwf_plan_guru64_dft')
+      import
+      integer(C_INT), value :: rank
+      type(fftwf_iodim64), dimension(*), intent(in) :: dims
+      integer(C_INT), value :: howmany_rank
+      type(fftwf_iodim64), dimension(*), intent(in) :: howmany_dims
+      complex(C_FLOAT_COMPLEX), dimension(*), intent(out) :: in
+      complex(C_FLOAT_COMPLEX), dimension(*), intent(out) :: out
+      integer(C_INT), value :: sign
+      integer(C_INT), value :: flags
+    end function fftwf_plan_guru64_dft
+    
+    type(C_PTR) function fftwf_plan_guru64_split_dft(rank,dims,howmany_rank,howmany_dims,ri,ii,ro,io,flags) &
+                         bind(C, name='fftwf_plan_guru64_split_dft')
+      import
+      integer(C_INT), value :: rank
+      type(fftwf_iodim64), dimension(*), intent(in) :: dims
+      integer(C_INT), value :: howmany_rank
+      type(fftwf_iodim64), dimension(*), intent(in) :: howmany_dims
+      real(C_FLOAT), dimension(*), intent(out) :: ri
+      real(C_FLOAT), dimension(*), intent(out) :: ii
+      real(C_FLOAT), dimension(*), intent(out) :: ro
+      real(C_FLOAT), dimension(*), intent(out) :: io
+      integer(C_INT), value :: flags
+    end function fftwf_plan_guru64_split_dft
+    
+    subroutine fftwf_execute_dft(p,in,out) bind(C, name='fftwf_execute_dft')
+      import
+      type(C_PTR), value :: p
+      complex(C_FLOAT_COMPLEX), dimension(*), intent(inout) :: in
+      complex(C_FLOAT_COMPLEX), dimension(*), intent(out) :: out
+    end subroutine fftwf_execute_dft
+    
+    subroutine fftwf_execute_split_dft(p,ri,ii,ro,io) bind(C, name='fftwf_execute_split_dft')
+      import
+      type(C_PTR), value :: p
+      real(C_FLOAT), dimension(*), intent(inout) :: ri
+      real(C_FLOAT), dimension(*), intent(inout) :: ii
+      real(C_FLOAT), dimension(*), intent(out) :: ro
+      real(C_FLOAT), dimension(*), intent(out) :: io
+    end subroutine fftwf_execute_split_dft
+    
+    type(C_PTR) function fftwf_plan_many_dft_r2c(rank,n,howmany,in,inembed,istride,idist,out,onembed,ostride,odist,flags) &
+                         bind(C, name='fftwf_plan_many_dft_r2c')
+      import
+      integer(C_INT), value :: rank
+      integer(C_INT), dimension(*), intent(in) :: n
+      integer(C_INT), value :: howmany
+      real(C_FLOAT), dimension(*), intent(out) :: in
+      integer(C_INT), dimension(*), intent(in) :: inembed
+      integer(C_INT), value :: istride
+      integer(C_INT), value :: idist
+      complex(C_FLOAT_COMPLEX), dimension(*), intent(out) :: out
+      integer(C_INT), dimension(*), intent(in) :: onembed
+      integer(C_INT), value :: ostride
+      integer(C_INT), value :: odist
+      integer(C_INT), value :: flags
+    end function fftwf_plan_many_dft_r2c
+    
+    type(C_PTR) function fftwf_plan_dft_r2c(rank,n,in,out,flags) bind(C, name='fftwf_plan_dft_r2c')
+      import
+      integer(C_INT), value :: rank
+      integer(C_INT), dimension(*), intent(in) :: n
+      real(C_FLOAT), dimension(*), intent(out) :: in
+      complex(C_FLOAT_COMPLEX), dimension(*), intent(out) :: out
+      integer(C_INT), value :: flags
+    end function fftwf_plan_dft_r2c
+    
+    type(C_PTR) function fftwf_plan_dft_r2c_1d(n,in,out,flags) bind(C, name='fftwf_plan_dft_r2c_1d')
+      import
+      integer(C_INT), value :: n
+      real(C_FLOAT), dimension(*), intent(out) :: in
+      complex(C_FLOAT_COMPLEX), dimension(*), intent(out) :: out
+      integer(C_INT), value :: flags
+    end function fftwf_plan_dft_r2c_1d
+    
+    type(C_PTR) function fftwf_plan_dft_r2c_2d(n0,n1,in,out,flags) bind(C, name='fftwf_plan_dft_r2c_2d')
+      import
+      integer(C_INT), value :: n0
+      integer(C_INT), value :: n1
+      real(C_FLOAT), dimension(*), intent(out) :: in
+      complex(C_FLOAT_COMPLEX), dimension(*), intent(out) :: out
+      integer(C_INT), value :: flags
+    end function fftwf_plan_dft_r2c_2d
+    
+    type(C_PTR) function fftwf_plan_dft_r2c_3d(n0,n1,n2,in,out,flags) bind(C, name='fftwf_plan_dft_r2c_3d')
+      import
+      integer(C_INT), value :: n0
+      integer(C_INT), value :: n1
+      integer(C_INT), value :: n2
+      real(C_FLOAT), dimension(*), intent(out) :: in
+      complex(C_FLOAT_COMPLEX), dimension(*), intent(out) :: out
+      integer(C_INT), value :: flags
+    end function fftwf_plan_dft_r2c_3d
+    
+    type(C_PTR) function fftwf_plan_many_dft_c2r(rank,n,howmany,in,inembed,istride,idist,out,onembed,ostride,odist,flags) &
+                         bind(C, name='fftwf_plan_many_dft_c2r')
+      import
+      integer(C_INT), value :: rank
+      integer(C_INT), dimension(*), intent(in) :: n
+      integer(C_INT), value :: howmany
+      complex(C_FLOAT_COMPLEX), dimension(*), intent(out) :: in
+      integer(C_INT), dimension(*), intent(in) :: inembed
+      integer(C_INT), value :: istride
+      integer(C_INT), value :: idist
+      real(C_FLOAT), dimension(*), intent(out) :: out
+      integer(C_INT), dimension(*), intent(in) :: onembed
+      integer(C_INT), value :: ostride
+      integer(C_INT), value :: odist
+      integer(C_INT), value :: flags
+    end function fftwf_plan_many_dft_c2r
+    
+    type(C_PTR) function fftwf_plan_dft_c2r(rank,n,in,out,flags) bind(C, name='fftwf_plan_dft_c2r')
+      import
+      integer(C_INT), value :: rank
+      integer(C_INT), dimension(*), intent(in) :: n
+      complex(C_FLOAT_COMPLEX), dimension(*), intent(out) :: in
+      real(C_FLOAT), dimension(*), intent(out) :: out
+      integer(C_INT), value :: flags
+    end function fftwf_plan_dft_c2r
+    
+    type(C_PTR) function fftwf_plan_dft_c2r_1d(n,in,out,flags) bind(C, name='fftwf_plan_dft_c2r_1d')
+      import
+      integer(C_INT), value :: n
+      complex(C_FLOAT_COMPLEX), dimension(*), intent(out) :: in
+      real(C_FLOAT), dimension(*), intent(out) :: out
+      integer(C_INT), value :: flags
+    end function fftwf_plan_dft_c2r_1d
+    
+    type(C_PTR) function fftwf_plan_dft_c2r_2d(n0,n1,in,out,flags) bind(C, name='fftwf_plan_dft_c2r_2d')
+      import
+      integer(C_INT), value :: n0
+      integer(C_INT), value :: n1
+      complex(C_FLOAT_COMPLEX), dimension(*), intent(out) :: in
+      real(C_FLOAT), dimension(*), intent(out) :: out
+      integer(C_INT), value :: flags
+    end function fftwf_plan_dft_c2r_2d
+    
+    type(C_PTR) function fftwf_plan_dft_c2r_3d(n0,n1,n2,in,out,flags) bind(C, name='fftwf_plan_dft_c2r_3d')
+      import
+      integer(C_INT), value :: n0
+      integer(C_INT), value :: n1
+      integer(C_INT), value :: n2
+      complex(C_FLOAT_COMPLEX), dimension(*), intent(out) :: in
+      real(C_FLOAT), dimension(*), intent(out) :: out
+      integer(C_INT), value :: flags
+    end function fftwf_plan_dft_c2r_3d
+    
+    type(C_PTR) function fftwf_plan_guru_dft_r2c(rank,dims,howmany_rank,howmany_dims,in,out,flags) &
+                         bind(C, name='fftwf_plan_guru_dft_r2c')
+      import
+      integer(C_INT), value :: rank
+      type(fftwf_iodim), dimension(*), intent(in) :: dims
+      integer(C_INT), value :: howmany_rank
+      type(fftwf_iodim), dimension(*), intent(in) :: howmany_dims
+      real(C_FLOAT), dimension(*), intent(out) :: in
+      complex(C_FLOAT_COMPLEX), dimension(*), intent(out) :: out
+      integer(C_INT), value :: flags
+    end function fftwf_plan_guru_dft_r2c
+    
+    type(C_PTR) function fftwf_plan_guru_dft_c2r(rank,dims,howmany_rank,howmany_dims,in,out,flags) &
+                         bind(C, name='fftwf_plan_guru_dft_c2r')
+      import
+      integer(C_INT), value :: rank
+      type(fftwf_iodim), dimension(*), intent(in) :: dims
+      integer(C_INT), value :: howmany_rank
+      type(fftwf_iodim), dimension(*), intent(in) :: howmany_dims
+      complex(C_FLOAT_COMPLEX), dimension(*), intent(out) :: in
+      real(C_FLOAT), dimension(*), intent(out) :: out
+      integer(C_INT), value :: flags
+    end function fftwf_plan_guru_dft_c2r
+    
+    type(C_PTR) function fftwf_plan_guru_split_dft_r2c(rank,dims,howmany_rank,howmany_dims,in,ro,io,flags) &
+                         bind(C, name='fftwf_plan_guru_split_dft_r2c')
+      import
+      integer(C_INT), value :: rank
+      type(fftwf_iodim), dimension(*), intent(in) :: dims
+      integer(C_INT), value :: howmany_rank
+      type(fftwf_iodim), dimension(*), intent(in) :: howmany_dims
+      real(C_FLOAT), dimension(*), intent(out) :: in
+      real(C_FLOAT), dimension(*), intent(out) :: ro
+      real(C_FLOAT), dimension(*), intent(out) :: io
+      integer(C_INT), value :: flags
+    end function fftwf_plan_guru_split_dft_r2c
+    
+    type(C_PTR) function fftwf_plan_guru_split_dft_c2r(rank,dims,howmany_rank,howmany_dims,ri,ii,out,flags) &
+                         bind(C, name='fftwf_plan_guru_split_dft_c2r')
+      import
+      integer(C_INT), value :: rank
+      type(fftwf_iodim), dimension(*), intent(in) :: dims
+      integer(C_INT), value :: howmany_rank
+      type(fftwf_iodim), dimension(*), intent(in) :: howmany_dims
+      real(C_FLOAT), dimension(*), intent(out) :: ri
+      real(C_FLOAT), dimension(*), intent(out) :: ii
+      real(C_FLOAT), dimension(*), intent(out) :: out
+      integer(C_INT), value :: flags
+    end function fftwf_plan_guru_split_dft_c2r
+    
+    type(C_PTR) function fftwf_plan_guru64_dft_r2c(rank,dims,howmany_rank,howmany_dims,in,out,flags) &
+                         bind(C, name='fftwf_plan_guru64_dft_r2c')
+      import
+      integer(C_INT), value :: rank
+      type(fftwf_iodim64), dimension(*), intent(in) :: dims
+      integer(C_INT), value :: howmany_rank
+      type(fftwf_iodim64), dimension(*), intent(in) :: howmany_dims
+      real(C_FLOAT), dimension(*), intent(out) :: in
+      complex(C_FLOAT_COMPLEX), dimension(*), intent(out) :: out
+      integer(C_INT), value :: flags
+    end function fftwf_plan_guru64_dft_r2c
+    
+    type(C_PTR) function fftwf_plan_guru64_dft_c2r(rank,dims,howmany_rank,howmany_dims,in,out,flags) &
+                         bind(C, name='fftwf_plan_guru64_dft_c2r')
+      import
+      integer(C_INT), value :: rank
+      type(fftwf_iodim64), dimension(*), intent(in) :: dims
+      integer(C_INT), value :: howmany_rank
+      type(fftwf_iodim64), dimension(*), intent(in) :: howmany_dims
+      complex(C_FLOAT_COMPLEX), dimension(*), intent(out) :: in
+      real(C_FLOAT), dimension(*), intent(out) :: out
+      integer(C_INT), value :: flags
+    end function fftwf_plan_guru64_dft_c2r
+    
+    type(C_PTR) function fftwf_plan_guru64_split_dft_r2c(rank,dims,howmany_rank,howmany_dims,in,ro,io,flags) &
+                         bind(C, name='fftwf_plan_guru64_split_dft_r2c')
+      import
+      integer(C_INT), value :: rank
+      type(fftwf_iodim64), dimension(*), intent(in) :: dims
+      integer(C_INT), value :: howmany_rank
+      type(fftwf_iodim64), dimension(*), intent(in) :: howmany_dims
+      real(C_FLOAT), dimension(*), intent(out) :: in
+      real(C_FLOAT), dimension(*), intent(out) :: ro
+      real(C_FLOAT), dimension(*), intent(out) :: io
+      integer(C_INT), value :: flags
+    end function fftwf_plan_guru64_split_dft_r2c
+    
+    type(C_PTR) function fftwf_plan_guru64_split_dft_c2r(rank,dims,howmany_rank,howmany_dims,ri,ii,out,flags) &
+                         bind(C, name='fftwf_plan_guru64_split_dft_c2r')
+      import
+      integer(C_INT), value :: rank
+      type(fftwf_iodim64), dimension(*), intent(in) :: dims
+      integer(C_INT), value :: howmany_rank
+      type(fftwf_iodim64), dimension(*), intent(in) :: howmany_dims
+      real(C_FLOAT), dimension(*), intent(out) :: ri
+      real(C_FLOAT), dimension(*), intent(out) :: ii
+      real(C_FLOAT), dimension(*), intent(out) :: out
+      integer(C_INT), value :: flags
+    end function fftwf_plan_guru64_split_dft_c2r
+    
+    subroutine fftwf_execute_dft_r2c(p,in,out) bind(C, name='fftwf_execute_dft_r2c')
+      import
+      type(C_PTR), value :: p
+      real(C_FLOAT), dimension(*), intent(inout) :: in
+      complex(C_FLOAT_COMPLEX), dimension(*), intent(out) :: out
+    end subroutine fftwf_execute_dft_r2c
+    
+    subroutine fftwf_execute_dft_c2r(p,in,out) bind(C, name='fftwf_execute_dft_c2r')
+      import
+      type(C_PTR), value :: p
+      complex(C_FLOAT_COMPLEX), dimension(*), intent(inout) :: in
+      real(C_FLOAT), dimension(*), intent(out) :: out
+    end subroutine fftwf_execute_dft_c2r
+    
+    subroutine fftwf_execute_split_dft_r2c(p,in,ro,io) bind(C, name='fftwf_execute_split_dft_r2c')
+      import
+      type(C_PTR), value :: p
+      real(C_FLOAT), dimension(*), intent(inout) :: in
+      real(C_FLOAT), dimension(*), intent(out) :: ro
+      real(C_FLOAT), dimension(*), intent(out) :: io
+    end subroutine fftwf_execute_split_dft_r2c
+    
+    subroutine fftwf_execute_split_dft_c2r(p,ri,ii,out) bind(C, name='fftwf_execute_split_dft_c2r')
+      import
+      type(C_PTR), value :: p
+      real(C_FLOAT), dimension(*), intent(inout) :: ri
+      real(C_FLOAT), dimension(*), intent(inout) :: ii
+      real(C_FLOAT), dimension(*), intent(out) :: out
+    end subroutine fftwf_execute_split_dft_c2r
+    
+    type(C_PTR) function fftwf_plan_many_r2r(rank,n,howmany,in,inembed,istride,idist,out,onembed,ostride,odist,kind,flags) &
+                         bind(C, name='fftwf_plan_many_r2r')
+      import
+      integer(C_INT), value :: rank
+      integer(C_INT), dimension(*), intent(in) :: n
+      integer(C_INT), value :: howmany
+      real(C_FLOAT), dimension(*), intent(out) :: in
+      integer(C_INT), dimension(*), intent(in) :: inembed
+      integer(C_INT), value :: istride
+      integer(C_INT), value :: idist
+      real(C_FLOAT), dimension(*), intent(out) :: out
+      integer(C_INT), dimension(*), intent(in) :: onembed
+      integer(C_INT), value :: ostride
+      integer(C_INT), value :: odist
+      integer(C_FFTW_R2R_KIND), dimension(*), intent(in) :: kind
+      integer(C_INT), value :: flags
+    end function fftwf_plan_many_r2r
+    
+    type(C_PTR) function fftwf_plan_r2r(rank,n,in,out,kind,flags) bind(C, name='fftwf_plan_r2r')
+      import
+      integer(C_INT), value :: rank
+      integer(C_INT), dimension(*), intent(in) :: n
+      real(C_FLOAT), dimension(*), intent(out) :: in
+      real(C_FLOAT), dimension(*), intent(out) :: out
+      integer(C_FFTW_R2R_KIND), dimension(*), intent(in) :: kind
+      integer(C_INT), value :: flags
+    end function fftwf_plan_r2r
+    
+    type(C_PTR) function fftwf_plan_r2r_1d(n,in,out,kind,flags) bind(C, name='fftwf_plan_r2r_1d')
+      import
+      integer(C_INT), value :: n
+      real(C_FLOAT), dimension(*), intent(out) :: in
+      real(C_FLOAT), dimension(*), intent(out) :: out
+      integer(C_FFTW_R2R_KIND), value :: kind
+      integer(C_INT), value :: flags
+    end function fftwf_plan_r2r_1d
+    
+    type(C_PTR) function fftwf_plan_r2r_2d(n0,n1,in,out,kind0,kind1,flags) bind(C, name='fftwf_plan_r2r_2d')
+      import
+      integer(C_INT), value :: n0
+      integer(C_INT), value :: n1
+      real(C_FLOAT), dimension(*), intent(out) :: in
+      real(C_FLOAT), dimension(*), intent(out) :: out
+      integer(C_FFTW_R2R_KIND), value :: kind0
+      integer(C_FFTW_R2R_KIND), value :: kind1
+      integer(C_INT), value :: flags
+    end function fftwf_plan_r2r_2d
+    
+    type(C_PTR) function fftwf_plan_r2r_3d(n0,n1,n2,in,out,kind0,kind1,kind2,flags) bind(C, name='fftwf_plan_r2r_3d')
+      import
+      integer(C_INT), value :: n0
+      integer(C_INT), value :: n1
+      integer(C_INT), value :: n2
+      real(C_FLOAT), dimension(*), intent(out) :: in
+      real(C_FLOAT), dimension(*), intent(out) :: out
+      integer(C_FFTW_R2R_KIND), value :: kind0
+      integer(C_FFTW_R2R_KIND), value :: kind1
+      integer(C_FFTW_R2R_KIND), value :: kind2
+      integer(C_INT), value :: flags
+    end function fftwf_plan_r2r_3d
+    
+    type(C_PTR) function fftwf_plan_guru_r2r(rank,dims,howmany_rank,howmany_dims,in,out,kind,flags) &
+                         bind(C, name='fftwf_plan_guru_r2r')
+      import
+      integer(C_INT), value :: rank
+      type(fftwf_iodim), dimension(*), intent(in) :: dims
+      integer(C_INT), value :: howmany_rank
+      type(fftwf_iodim), dimension(*), intent(in) :: howmany_dims
+      real(C_FLOAT), dimension(*), intent(out) :: in
+      real(C_FLOAT), dimension(*), intent(out) :: out
+      integer(C_FFTW_R2R_KIND), dimension(*), intent(in) :: kind
+      integer(C_INT), value :: flags
+    end function fftwf_plan_guru_r2r
+    
+    type(C_PTR) function fftwf_plan_guru64_r2r(rank,dims,howmany_rank,howmany_dims,in,out,kind,flags) &
+                         bind(C, name='fftwf_plan_guru64_r2r')
+      import
+      integer(C_INT), value :: rank
+      type(fftwf_iodim64), dimension(*), intent(in) :: dims
+      integer(C_INT), value :: howmany_rank
+      type(fftwf_iodim64), dimension(*), intent(in) :: howmany_dims
+      real(C_FLOAT), dimension(*), intent(out) :: in
+      real(C_FLOAT), dimension(*), intent(out) :: out
+      integer(C_FFTW_R2R_KIND), dimension(*), intent(in) :: kind
+      integer(C_INT), value :: flags
+    end function fftwf_plan_guru64_r2r
+    
+    subroutine fftwf_execute_r2r(p,in,out) bind(C, name='fftwf_execute_r2r')
+      import
+      type(C_PTR), value :: p
+      real(C_FLOAT), dimension(*), intent(inout) :: in
+      real(C_FLOAT), dimension(*), intent(out) :: out
+    end subroutine fftwf_execute_r2r
+    
+    subroutine fftwf_destroy_plan(p) bind(C, name='fftwf_destroy_plan')
+      import
+      type(C_PTR), value :: p
+    end subroutine fftwf_destroy_plan
+    
+    subroutine fftwf_forget_wisdom() bind(C, name='fftwf_forget_wisdom')
+      import
+    end subroutine fftwf_forget_wisdom
+    
+    subroutine fftwf_cleanup() bind(C, name='fftwf_cleanup')
+      import
+    end subroutine fftwf_cleanup
+    
+    subroutine fftwf_set_timelimit(t) bind(C, name='fftwf_set_timelimit')
+      import
+      real(C_DOUBLE), value :: t
+    end subroutine fftwf_set_timelimit
+    
+    subroutine fftwf_plan_with_nthreads(nthreads) bind(C, name='fftwf_plan_with_nthreads')
+      import
+      integer(C_INT), value :: nthreads
+    end subroutine fftwf_plan_with_nthreads
+    
+    integer(C_INT) function fftwf_init_threads() bind(C, name='fftwf_init_threads')
+      import
+    end function fftwf_init_threads
+    
+    subroutine fftwf_cleanup_threads() bind(C, name='fftwf_cleanup_threads')
+      import
+    end subroutine fftwf_cleanup_threads
+    
+    integer(C_INT) function fftwf_export_wisdom_to_filename(filename) bind(C, name='fftwf_export_wisdom_to_filename')
+      import
+      character(C_CHAR), dimension(*), intent(in) :: filename
+    end function fftwf_export_wisdom_to_filename
+    
+    subroutine fftwf_export_wisdom_to_file(output_file) bind(C, name='fftwf_export_wisdom_to_file')
+      import
+      type(C_PTR), value :: output_file
+    end subroutine fftwf_export_wisdom_to_file
+    
+    type(C_PTR) function fftwf_export_wisdom_to_string() bind(C, name='fftwf_export_wisdom_to_string')
+      import
+    end function fftwf_export_wisdom_to_string
+    
+    subroutine fftwf_export_wisdom(write_char,data) bind(C, name='fftwf_export_wisdom')
+      import
+      type(C_FUNPTR), value :: write_char
+      type(C_PTR), value :: data
+    end subroutine fftwf_export_wisdom
+    
+    integer(C_INT) function fftwf_import_system_wisdom() bind(C, name='fftwf_import_system_wisdom')
+      import
+    end function fftwf_import_system_wisdom
+    
+    integer(C_INT) function fftwf_import_wisdom_from_filename(filename) bind(C, name='fftwf_import_wisdom_from_filename')
+      import
+      character(C_CHAR), dimension(*), intent(in) :: filename
+    end function fftwf_import_wisdom_from_filename
+    
+    integer(C_INT) function fftwf_import_wisdom_from_file(input_file) bind(C, name='fftwf_import_wisdom_from_file')
+      import
+      type(C_PTR), value :: input_file
+    end function fftwf_import_wisdom_from_file
+    
+    integer(C_INT) function fftwf_import_wisdom_from_string(input_string) bind(C, name='fftwf_import_wisdom_from_string')
+      import
+      character(C_CHAR), dimension(*), intent(in) :: input_string
+    end function fftwf_import_wisdom_from_string
+    
+    integer(C_INT) function fftwf_import_wisdom(read_char,data) bind(C, name='fftwf_import_wisdom')
+      import
+      type(C_FUNPTR), value :: read_char
+      type(C_PTR), value :: data
+    end function fftwf_import_wisdom
+    
+    subroutine fftwf_fprint_plan(p,output_file) bind(C, name='fftwf_fprint_plan')
+      import
+      type(C_PTR), value :: p
+      type(C_PTR), value :: output_file
+    end subroutine fftwf_fprint_plan
+    
+    subroutine fftwf_print_plan(p) bind(C, name='fftwf_print_plan')
+      import
+      type(C_PTR), value :: p
+    end subroutine fftwf_print_plan
+    
+    type(C_PTR) function fftwf_sprint_plan(p) bind(C, name='fftwf_sprint_plan')
+      import
+      type(C_PTR), value :: p
+    end function fftwf_sprint_plan
+    
+    type(C_PTR) function fftwf_malloc(n) bind(C, name='fftwf_malloc')
+      import
+      integer(C_SIZE_T), value :: n
+    end function fftwf_malloc
+    
+    type(C_PTR) function fftwf_alloc_real(n) bind(C, name='fftwf_alloc_real')
+      import
+      integer(C_SIZE_T), value :: n
+    end function fftwf_alloc_real
+    
+    type(C_PTR) function fftwf_alloc_complex(n) bind(C, name='fftwf_alloc_complex')
+      import
+      integer(C_SIZE_T), value :: n
+    end function fftwf_alloc_complex
+    
+    subroutine fftwf_free(p) bind(C, name='fftwf_free')
+      import
+      type(C_PTR), value :: p
+    end subroutine fftwf_free
+    
+    subroutine fftwf_flops(p,add,mul,fmas) bind(C, name='fftwf_flops')
+      import
+      type(C_PTR), value :: p
+      real(C_DOUBLE), intent(out) :: add
+      real(C_DOUBLE), intent(out) :: mul
+      real(C_DOUBLE), intent(out) :: fmas
+    end subroutine fftwf_flops
+    
+    real(C_DOUBLE) function fftwf_estimate_cost(p) bind(C, name='fftwf_estimate_cost')
+      import
+      type(C_PTR), value :: p
+    end function fftwf_estimate_cost
+    
+    real(C_DOUBLE) function fftwf_cost(p) bind(C, name='fftwf_cost')
+      import
+      type(C_PTR), value :: p
+    end function fftwf_cost
+    
+    integer(C_INT) function fftwf_alignment_of(p) bind(C, name='fftwf_alignment_of')
+      import
+      real(C_FLOAT), dimension(*), intent(out) :: p
+    end function fftwf_alignment_of
+    
+  end interface
diff --git a/lib/fftw3mod.f90 b/lib/fftw3mod.f90
new file mode 100644
index 0000000..f9e5f78
--- /dev/null
+++ b/lib/fftw3mod.f90
@@ -0,0 +1,4 @@
+module FFTW3
+  use, intrinsic :: iso_c_binding
+  include 'fftw3.f03'
+end module FFTW3
diff --git a/lib/fil4.f90 b/lib/fil4.f90
new file mode 100644
index 0000000..4946da2
--- /dev/null
+++ b/lib/fil4.f90
@@ -0,0 +1,49 @@
+subroutine fil4(id1,n1,id2,n2)
+
+! FIR lowpass filter designed using ScopeFIR
+
+! fsample     = 48000 Hz
+! Ntaps       = 49
+! fc          = 4500  Hz
+! fstop       = 6000  Hz
+! Ripple      = 1     dB
+! Stop Atten  = 40    dB
+! fout        = 12000 Hz
+
+  parameter (NTAPS=49)
+  parameter (NDOWN=4)             !Downsample ratio
+  integer*2 id1(n1)
+  integer*2 id2(*)
+  real t(NTAPS)
+  data t/NTAPS*0.0/
+
+! Filter coefficients:
+  real w(NTAPS)
+  data w/                                                                 &
+        0.000861074040, 0.010051920210, 0.010161983649, 0.011363155076,   &
+        0.008706594219, 0.002613872664,-0.005202883094,-0.011720748164,   &
+       -0.013752163325,-0.009431602741, 0.000539063909, 0.012636767098,   &
+        0.021494659597, 0.021951235065, 0.011564169382,-0.007656470131,   &
+       -0.028965787341,-0.042637874109,-0.039203309748,-0.013153301537,   &
+        0.034320769178, 0.094717832646, 0.154224604789, 0.197758325022,   &
+        0.213715139513, 0.197758325022, 0.154224604789, 0.094717832646,   &
+        0.034320769178,-0.013153301537,-0.039203309748,-0.042637874109,   &
+       -0.028965787341,-0.007656470131, 0.011564169382, 0.021951235065,   &
+        0.021494659597, 0.012636767098, 0.000539063909,-0.009431602741,   &
+       -0.013752163325,-0.011720748164,-0.005202883094, 0.002613872664,   &
+        0.008706594219, 0.011363155076, 0.010161983649, 0.010051920210,   &
+        0.000861074040/
+  save w,t
+
+  n2=n1/NDOWN
+  if(n2*NDOWN.ne.n1) stop 'Error in fil4'
+  k=1-NDOWN
+  do i=1,n2
+     k=k+NDOWN
+     t(1:NTAPS-NDOWN)=t(1+NDOWN:NTAPS)          !Shift old data down in array t
+     t(1+NTAPS-NDOWN:NTAPS)=id1(k:k+NDOWN-1)    !Insert new data at end of t
+     id2(i)=nint(dot_product(w,t))
+  enddo
+
+  return
+end subroutine fil4
diff --git a/lib/filbig.f90 b/lib/filbig.f90
index cb59b2f..bb1ea52 100644
--- a/lib/filbig.f90
+++ b/lib/filbig.f90
@@ -3,26 +3,30 @@ subroutine filbig(dd,npts,f0,newdat,c4a,n4,sq0)
 ! Filter and downsample the real data in array dd(npts), sampled at 12000 Hz.
 ! Output is complex, sampled at 1378.125 Hz.
 
+  use, intrinsic :: iso_c_binding
+  use FFTW3
+
   parameter (NSZ=3413)
   parameter (NFFT1=672000,NFFT2=77175)
   parameter (NZ2=1000)
   real*4  dd(npts)                           !Input data
-  complex ca(NFFT1)                          !FFT of input
+  real*4 rca(NFFT1)
+  complex ca(NFFT1/2+1)                      !FFT of input
   complex c4a(NFFT2)                         !Output data
   real*4 s(NZ2)
   real*8 df
   real halfpulse(8)                 !Impulse response of filter (one sided)
   complex cfilt(NFFT2)                       !Filter (complex; imag = 0)
   real rfilt(NFFT2)                          !Filter (real)
-  integer*8 plan1,plan2,plan3
+  type(C_PTR) :: plan1,plan2,plan3           !Pointers to FFTW plans
   logical first
-  include 'fftw3.f90'
-  equivalence (rfilt,cfilt)
-  data first/.true./,npatience/0/
+  equivalence (rfilt,cfilt),(rca,ca)
+  data first/.true./
   data halfpulse/114.97547150,36.57879257,-20.93789101,              &
        5.89886379,1.59355187,-2.49138308,0.60910773,-0.04248129/
   common/refspec/dfref,ref(NSZ)
-  save
+  common/patience/npatience,nthreads
+  save first,plan1,plan2,plan3,rfilt,cfilt,df,ca
 
   if(npts.lt.0) go to 900                    !Clean up at end of program
 
@@ -32,12 +36,15 @@ subroutine filbig(dd,npts,f0,newdat,c4a,n4,sq0)
      if(npatience.eq.2) nflags=FFTW_MEASURE
      if(npatience.eq.3) nflags=FFTW_PATIENT
      if(npatience.eq.4) nflags=FFTW_EXHAUSTIVE
+
 ! Plan the FFTs just once
-     call timer('FFTplans ',0)
-     call sfftw_plan_dft_1d(plan1,nfft1,ca,ca,FFTW_BACKWARD,nflags)
-     call sfftw_plan_dft_1d(plan2,nfft2,c4a,c4a,FFTW_FORWARD,nflags)
-     call sfftw_plan_dft_1d(plan3,nfft2,cfilt,cfilt,FFTW_BACKWARD,nflags)
-     call timer('FFTplans ',1)
+     !$omp critical(fftw) ! serialize non thread-safe FFTW3 calls
+     call fftwf_plan_with_nthreads(nthreads)
+     plan1=fftwf_plan_dft_r2c_1d(nfft1,rca,ca,nflags)
+     call fftwf_plan_with_nthreads(1)
+     plan2=fftwf_plan_dft_1d(nfft2,c4a,c4a,-1,nflags)
+     plan3=fftwf_plan_dft_1d(nfft2,cfilt,cfilt,+1,nflags)
+     !$omp end critical(fftw)
 
 ! Convert impulse response to filter function
      do i=1,nfft2
@@ -49,11 +56,9 @@ subroutine filbig(dd,npts,f0,newdat,c4a,n4,sq0)
         cfilt(i)=fac*halfpulse(i)
         cfilt(nfft2+2-i)=fac*halfpulse(i)
      enddo
-     call timer('FFTfilt ',0)
-     call sfftw_execute(plan3)
-     call timer('FFTfilt ',1)
+     call fftwf_execute_dft(plan3,cfilt,cfilt)
 
-     base=cfilt(nfft2/2+1)
+     base=real(cfilt(nfft2/2+1))
      do i=1,nfft2
         rfilt(i)=real(cfilt(i))-base
      enddo
@@ -66,30 +71,31 @@ subroutine filbig(dd,npts,f0,newdat,c4a,n4,sq0)
 ! If we just have a new f0, continue with the existing data in ca.
 
   if(newdat.ne.0) then
-     nz=min(npts,nfft1)
-     ca(1:nz)=dd(1:nz)
-     ca(nz+1:)=0.                   !### Should change this to r2c FFT ###
      call timer('FFTbig  ',0)
-     call sfftw_execute(plan1)
+     nz=min(npts,nfft1)
+     rca(1:nz)=dd(1:nz)
+     rca(nz+1:)=0.
+     call fftwf_execute_dft_r2c(plan1,rca,ca)
      call timer('FFTbig  ',1)
 
-     do i=1,NFFT1/2                             !Flatten the spectrum
-        j=nint(i*df/dfref)
-        if(j.lt.1) j=1
-        if(j.gt.NSZ) j=NSZ
+     ib=0
+     do j=1,NSZ
+        ia=ib+1
+        ib=nint(j*dfref/df)
         fac=sqrt(min(30.0,1.0/ref(j)))
-        ca(i)=fac * ca(i)
+        ca(ia:ib)=fac*conjg(ca(ia:ib))
      enddo
+     newdat=0
   endif
 
 ! NB: f0 is the frequency at which we want our filter centered.
 !     i0 is the bin number in ca closest to f0.
-
+  call timer('loops   ',0)
   i0=nint(f0/df) + 1
   nh=nfft2/2
   do i=1,nh                                !Copy data into c4a and apply
      j=i0+i-1                              !the filter function
-     if(j.ge.1 .and. j.le.nfft1) then
+     if(j.ge.1 .and. j.le.nfft1/2+1) then
         c4a(i)=rfilt(i)*ca(j)
      else
         c4a(i)=0.
@@ -97,8 +103,12 @@ subroutine filbig(dd,npts,f0,newdat,c4a,n4,sq0)
   enddo
   do i=nh+1,nfft2
      j=i0+i-1-nfft2
-     if(j.lt.1) j=j+nfft1                  !nfft1 was nfft2
-     c4a(i)=rfilt(i)*ca(j)
+!     if(j.lt.1) j=j+nfft1                  !nfft1 was nfft2
+     if(j.ge.1) then
+        c4a(i)=rfilt(i)*ca(j)
+     else
+        c4a(i)=rfilt(i)*conjg(ca(2-j))
+     endif
   enddo
 
   nadd=nfft2/NZ2
@@ -111,17 +121,22 @@ subroutine filbig(dd,npts,f0,newdat,c4a,n4,sq0)
      enddo
   enddo
   call pctile(s,NZ2,30,sq0)
+  call timer('loops   ',1)
 
 ! Do the short reverse transform, to go back to time domain.
   call timer('FFTsmall',0)
-  call sfftw_execute(plan2)
+  call fftwf_execute_dft(plan2,c4a,c4a)
   call timer('FFTsmall',1)
   n4=min(npts/8,nfft2)
   return
 
-900 call sfftw_destroy_plan(plan1)
-  call sfftw_destroy_plan(plan2)
-  call sfftw_destroy_plan(plan3)
+900 continue
+
+  !$omp critical(fftw) ! serialize non thread-safe FFTW3 calls
+  call fftwf_destroy_plan(plan1)
+  call fftwf_destroy_plan(plan2)
+  call fftwf_destroy_plan(plan3)
+  !$omp end critical(fftw)
   
   return
 end subroutine filbig
diff --git a/lib/fillcom.f90 b/lib/fillcom.f90
index 03fbb2c..f652378 100644
--- a/lib/fillcom.f90
+++ b/lib/fillcom.f90
@@ -1,7 +1,9 @@
-subroutine fillcom(nutc0,ndepth0,nrxfreq)
+subroutine fillcom(nutc0,ndepth0,nrxfreq,mode,tx9,flow,fsplit,fhigh)
   character*20 datetime
-  common/npar/nutc,ndiskdat,ntrperiod,nfqso,newdat,npts8,nfa,nfb,ntol,  &
-       kin,nzhsym,nsave,nagain,ndepth,ntxmode,nmode,datetime
+  integer mode,flow,fsplit,fhigh
+  logical tx9
+  common/npar/nutc,ndiskdat,ntrperiod,nfqso,newdat,npts8,nfa,nfsplit,nfb,   &
+       ntol,kin,nzhsym,nsave,nagain,ndepth,ntxmode,nmode,datetime
   save
 
   nutc=nutc0
@@ -10,16 +12,26 @@ subroutine fillcom(nutc0,ndepth0,nrxfreq)
   nfqso=nrxfreq
   newdat=1
   npts8=74736
-  nfa=2700
-  nfb=4007
+  nfa=flow
+  nfsplit=fsplit
+  nfb=fhigh
   ntol=3
   kin=1024
   nzhsym=173
   nsave=0
   ndepth=ndepth0
-  ntxmode=9
-  nmode=9+65
+  if (tx9) then
+    ntxmode=9
+  else
+    ntxmode=65
+  end if
+  if (mode.lt.9) then
+    nmode=65+9
+  else
+    nmode=mode
+  end if
   datetime="2013-Apr-16 15:13"
-  
+  if(mode.eq.9 .and. nfsplit.ne.2700) nfa=nfsplit
+
   return
 end subroutine fillcom
diff --git a/lib/flat1.f90 b/lib/flat1.f90
index 526ab9b..b9dfdd1 100644
--- a/lib/flat1.f90
+++ b/lib/flat1.f90
@@ -1,30 +1,27 @@
-subroutine flat1(psavg,s2,nh,nsteps,nhmax,nsmax)
+subroutine flat1(savg,iz,nsmo,syellow)
 
-  real psavg(nh)
-  real s2(nhmax,nsmax)
-  real x(8192),tmp(33)
+  real savg(iz)
+  real syellow(iz)
+  real x(8192)
 
-  nsmo=33
   ia=nsmo/2 + 1
-  ib=nh - nsmo/2 - 1
-  do i=ia,ib
-     call pctile(psavg(i-nsmo/2),nsmo,50,x(i))
+  ib=iz - nsmo/2 - 1
+  nstep=20
+  nh=nstep/2
+  do i=ia,ib,nstep
+     call pctile(savg(i-nsmo/2),nsmo,50,x(i))
+     x(i-nh:i+nh-1)=x(i)
   enddo
   do i=1,ia-1
      x(i)=x(ia)
   enddo
-  do i=ib+1,nh
+  do i=ib+1,iz
      x(i)=x(ib)
   enddo
 
-  do i=1,nh
-     psavg(i)=psavg(i)/x(i)
-     do j=1,nsteps
-        s2(i,j)=s2(i,j)/x(i)
-     enddo
-  enddo
+  x0=0.001*maxval(x(1:iz))
+  syellow(1:iz)=savg(1:iz)/(x(1:iz)+x0)
 
   return
 end subroutine flat1
 
-      
diff --git a/lib/flat4.f90 b/lib/flat4.f90
new file mode 100644
index 0000000..fd96a3a
--- /dev/null
+++ b/lib/flat4.f90
@@ -0,0 +1,50 @@
+subroutine flat4(s,npts,nflatten)
+
+! Flatten a spectrum for optimum display
+! Input:  s(npts)    Linear scale in power
+!         nflatten   If nflatten=0, convert to dB but do not flatten
+! Output: s(npts)    Flattened, with dB scale
+
+
+  implicit real*8 (a-h,o-z)
+  real*4 s(6827)
+  real*4 base
+  real*8 x(1000),y(1000),a(5)
+  data nseg/10/,npct/10/
+
+  if(s(1).gt.1.e29) go to 900         !Boundary between Rx intervals: do nothing
+  do i=1,npts
+     s(i)=10.0*log10(s(i))            !Convert to dB scale
+  enddo
+  if(nflatten.eq.0) go to 900
+
+  nlen=npts/nseg                      !Length of test segment
+  i0=npts/2                           !Midpoint
+  k=0
+  do n=2,nseg                         !Skip first segment, likely rolloff here
+     ib=n*nlen
+     ia=ib-nlen+1
+     if(n.eq.nseg) ib=npts
+     call pctile(s(ia),ib-ia+1,npct,base) !Find lowest npct of points in segment
+     do i=ia,ib
+        if(s(i).le.base) then
+           if (k.lt.1000) k=k+1       !Save these "lower envelope" points
+           x(k)=i-i0
+           y(k)=s(i)
+        endif
+     enddo
+  enddo
+  kz=k
+  a=0.
+  nterms=3
+  
+  call polfit(x,y,y,kz,nterms,0,a,chisqr)  !Fit a low-order polynomial
+
+  do i=1,npts
+     t=i-i0
+     yfit=a(1)+t*(a(2)+t*(a(3)+t*(a(4)+t*(a(5)))))
+     s(i)=s(i)-yfit                    !Subtract the fitted baseline
+  enddo
+
+900 return
+end subroutine flat4
diff --git a/lib/fmtmsg.f90 b/lib/fmtmsg.f90
new file mode 100644
index 0000000..2ceb815
--- /dev/null
+++ b/lib/fmtmsg.f90
@@ -0,0 +1,21 @@
+subroutine fmtmsg(msg,iz)
+
+  character*22 msg
+
+! Convert all letters to upper case
+  iz=22
+  do i=1,22
+     if(msg(i:i).ge.'a' .and. msg(i:i).le.'z')                       &
+          msg(i:i)= char(ichar(msg(i:i))+ichar('A')-ichar('a'))
+     if(msg(i:i).ne.' ') iz=i
+  enddo
+
+  do iter=1,5                           !Collapse multiple blanks into one
+     ib2=index(msg(1:iz),'  ')
+     if(ib2.lt.1) go to 100
+     msg=msg(1:ib2)//msg(ib2+2:)
+     iz=iz-1
+  enddo
+
+100 return
+end subroutine fmtmsg
diff --git a/lib/four2a.f90 b/lib/four2a.f90
index c095629..57c7239 100644
--- a/lib/four2a.f90
+++ b/lib/four2a.f90
@@ -1,90 +1,115 @@
 subroutine four2a(a,nfft,ndim,isign,iform)
 
-!     IFORM = 1, 0 or -1, as data is
-!     complex, real, or the first half of a complex array.  Transform
-!     values are returned in array DATA.  They are complex, real, or
-!     the first half of a complex array, as IFORM = 1, -1 or 0.
-
-!     The transform of a real array (IFORM = 0) dimensioned N(1) by N(2)
-!     by ... will be returned in the same array, now considered to
-!     be complex of dimensions N(1)/2+1 by N(2) by ....  Note that if
-!     IFORM = 0 or -1, N(1) must be even, and enough room must be
-!     reserved.  The missing values may be obtained by complex conjugation.  
-
-!     The reverse transformation of a half complex array dimensioned
-!     N(1)/2+1 by N(2) by ..., is accomplished by setting IFORM
-!     to -1.  In the N array, N(1) must be the true N(1), not N(1)/2+1.
-!     The transform will be real and returned to the input array.
-
-  parameter (NPMAX=100)
-  parameter (NSMALL=16384)
-  complex a(nfft)
-  complex aa(NSMALL)
-  integer nn(NPMAX),ns(NPMAX),nf(NPMAX)
-  integer*8 plan(NPMAX),nl(NPMAX),nloc
-  data nplan/0/,npatience/1/
-!  data nplan/0/,npatience/0/
-  include 'fftw3.f90'
+! IFORM = 1, 0 or -1, as data is
+! complex, real, or the first half of a complex array.  Transform
+! values are returned in array DATA.  They are complex, real, or
+! the first half of a complex array, as IFORM = 1, -1 or 0.
+
+! The transform of a real array (IFORM = 0) dimensioned N(1) by N(2)
+! by ... will be returned in the same array, now considered to
+! be complex of dimensions N(1)/2+1 by N(2) by ....  Note that if
+! IFORM = 0 or -1, N(1) must be even, and enough room must be
+! reserved.  The missing values may be obtained by complex conjugation.  
+
+! The reverse transformation of a half complex array dimensioned
+! N(1)/2+1 by N(2) by ..., is accomplished by setting IFORM
+! to -1.  In the N array, N(1) must be the true N(1), not N(1)/2+1.
+! The transform will be real and returned to the input array.
+
+! This version of four2a makes calls to the FFTW library to do the 
+! actual computations.
+
+  parameter (NPMAX=2100)                 !Max numberf of stored plans
+  parameter (NSMALL=16384)               !Max size of "small" FFTs
+  complex a(nfft)                        !Array to be transformed
+  complex aa(NSMALL)                     !Local copy of "small" a()
+  integer nn(NPMAX),ns(NPMAX),nf(NPMAX)  !Params of stored plans 
+  integer*8 nl(NPMAX),nloc               !More params of plans
+  integer*8 plan(NPMAX)                  !Pointers to stored plans
+  logical found_plan
+  data nplan/0/                          !Number of stored plans
+  common/patience/npatience,nthreads     !Patience and threads for FFTW plans
+  include 'fftw3.f90'                    !FFTW definitions
   save plan,nplan,nn,ns,nf,nl
 
   if(nfft.lt.0) go to 999
 
   nloc=loc(a)
+
+  found_plan = .false.
+  !$omp critical(four2a_setup)
   do i=1,nplan
      if(nfft.eq.nn(i) .and. isign.eq.ns(i) .and.                     &
-          iform.eq.nf(i) .and. nloc.eq.nl(i)) go to 10
+          iform.eq.nf(i) .and. nloc.eq.nl(i)) then
+        found_plan = .true.
+        exit
+     end if
   enddo
-  if(nplan.ge.NPMAX) stop 'Too many FFTW plans requested.'
-  nplan=nplan+1
-  i=nplan
-  nn(i)=nfft
-  ns(i)=isign
-  nf(i)=iform
-  nl(i)=nloc
+
+  if(i.ge.NPMAX) stop 'Too many FFTW plans requested.'
+
+  if (.not. found_plan) then
+     nplan=nplan+1
+     i=nplan
+
+     nn(i)=nfft
+     ns(i)=isign
+     nf(i)=iform
+     nl(i)=nloc
 
 ! Planning: FFTW_ESTIMATE, FFTW_ESTIMATE_PATIENT, FFTW_MEASURE, 
 !            FFTW_PATIENT,  FFTW_EXHAUSTIVE
-  nflags=FFTW_ESTIMATE
-  if(npatience.eq.1) nflags=FFTW_ESTIMATE_PATIENT
-  if(npatience.eq.2) nflags=FFTW_MEASURE
-  if(npatience.eq.3) nflags=FFTW_PATIENT
-  if(npatience.eq.4) nflags=FFTW_EXHAUSTIVE
-
-  if(nfft.le.NSMALL) then
-     jz=nfft
-     if(iform.eq.0) jz=nfft/2
-     do j=1,jz
-        aa(j)=a(j)
-     enddo
-  endif
-  if(isign.eq.-1 .and. iform.eq.1) then
-     call sfftw_plan_dft_1d(plan(i),nfft,a,a,FFTW_FORWARD,nflags)
-  else if(isign.eq.1 .and. iform.eq.1) then
-     call sfftw_plan_dft_1d(plan(i),nfft,a,a,FFTW_BACKWARD,nflags)
-  else if(isign.eq.-1 .and. iform.eq.0) then
-     call sfftw_plan_dft_r2c_1d(plan(i),nfft,a,a,nflags)
-  else if(isign.eq.1 .and. iform.eq.-1) then
-     call sfftw_plan_dft_c2r_1d(plan(i),nfft,a,a,nflags)
-  else
-     stop 'Unsupported request in four2a'
-  endif
-  i=nplan
-  if(nfft.le.NSMALL) then
-     jz=nfft
-     if(iform.eq.0) jz=nfft/2
-     do j=1,jz
-        a(j)=aa(j)
-     enddo
-  endif
-
-10 continue
+     nflags=FFTW_ESTIMATE
+     if(npatience.eq.1) nflags=FFTW_ESTIMATE_PATIENT
+     if(npatience.eq.2) nflags=FFTW_MEASURE
+     if(npatience.eq.3) nflags=FFTW_PATIENT
+     if(npatience.eq.4) nflags=FFTW_EXHAUSTIVE
+
+     if(nfft.le.NSMALL) then
+        jz=nfft
+        if(iform.eq.0) jz=nfft/2
+        aa(1:jz)=a(1:jz)
+     endif
+
+     !$omp critical(fftw) ! serialize non thread-safe FFTW3 calls
+     if(isign.eq.-1 .and. iform.eq.1) then
+        call sfftw_plan_dft_1d(plan(i),nfft,a,a,FFTW_FORWARD,nflags)
+     else if(isign.eq.1 .and. iform.eq.1) then
+        call sfftw_plan_dft_1d(plan(i),nfft,a,a,FFTW_BACKWARD,nflags)
+     else if(isign.eq.-1 .and. iform.eq.0) then
+        call sfftw_plan_dft_r2c_1d(plan(i),nfft,a,a,nflags)
+     else if(isign.eq.1 .and. iform.eq.-1) then
+        call sfftw_plan_dft_c2r_1d(plan(i),nfft,a,a,nflags)
+     else
+        stop 'Unsupported request in four2a'
+     endif
+     !$omp end critical(fftw)
+
+     if(nfft.le.NSMALL) then
+        jz=nfft
+        if(iform.eq.0) jz=nfft/2
+        a(1:jz)=aa(1:jz)
+     endif
+  end if
+  !$omp end critical(four2a_setup)
+
   call sfftw_execute(plan(i))
   return
 
-999 do i=1,nplan
+999 continue
+
+  !$omp critical(four2a)
+  do i=1,nplan
 ! The test is only to silence a compiler warning:
-     if(ndim.ne.-999) call sfftw_destroy_plan(plan(i))
+     if(ndim.ne.-999) then
+        !$omp critical(fftw) ! serialize non thread-safe FFTW3 calls
+        call sfftw_destroy_plan(plan(i))
+        !$omp end critical(fftw)
+     end if
   enddo
 
+  nplan=0
+  !$omp end critical(four2a)
+
   return
 end subroutine four2a
diff --git a/lib/g1 b/lib/g1
new file mode 100644
index 0000000..52f7616
--- /dev/null
+++ b/lib/g1
@@ -0,0 +1,4 @@
+gcc -c gran.c
+gfortran -c four2a.f90
+gfortran -c f77_wisdom.f90
+gfortran -o chkfft chkfft.f90 four2a.o f77_wisdom.o gran.o -lfftw3f
diff --git a/lib/g1.bat b/lib/g1.bat
new file mode 100644
index 0000000..6242f25
--- /dev/null
+++ b/lib/g1.bat
@@ -0,0 +1,4 @@
+gcc -c gran.c
+gfortran -c four2a.f90
+gfortran -c f77_wisdom.f90
+gfortran -o chkfft chkfft.f90 four2a.o f77_wisdom.o gran.o /JTSDK-QT/appsupport/runtime/libfftw3f-3.dll
diff --git a/lib/g2.bat b/lib/g2.bat
new file mode 100644
index 0000000..4067107
--- /dev/null
+++ b/lib/g2.bat
@@ -0,0 +1,4 @@
+gcc -c gran.c
+gfortran -c fftw3mod.f90
+gfortran -c f77_wisdom.f90
+gfortran -o chkfft2 chkfft2.f90 f77_wisdom.o gran.o /JTSDK-QT/appsupport/runtime/libfftw3f-3.dll
diff --git a/lib/g3.bat b/lib/g3.bat
new file mode 100644
index 0000000..904fce9
--- /dev/null
+++ b/lib/g3.bat
@@ -0,0 +1,4 @@
+gcc -c gran.c
+gfortran -c fftw3mod.f90
+gfortran -c f77_wisdom.f90
+gfortran -o chkfft3 chkfft3.f90 f77_wisdom.o gran.o /JTSDK-QT/appsupport/runtime/libfftw3f-3.dll
diff --git a/lib/g4.bat b/lib/g4.bat
new file mode 100644
index 0000000..6475dad
--- /dev/null
+++ b/lib/g4.bat
@@ -0,0 +1,3 @@
+gcc -c gran.c
+gfortran -c -Wall fftw3mod.f90
+gfortran -o timefft -Wall timefft.f90 timefft_opts.f90 gran.o libfftw3f-3.dll
diff --git a/lib/gen24.f90 b/lib/gen24.f90
deleted file mode 100644
index e2aaa77..0000000
--- a/lib/gen24.f90
+++ /dev/null
@@ -1,86 +0,0 @@
-subroutine gen24(message,mode4,samfac,ntxdf,iwave,nwave,sendingsh,msgsent,nmsg)
-
-! Encode a JT4 message into a wavefile.
-
-  parameter (NMAX=60*11025)     !Max length of wave file
-  character*22 message          !Message to be generated
-  character*22 msgsent          !Message as it will be received
-  character*3 cok               !'   ' or 'OOO'
-  real*8 t,dt,phi,f,f0,dfgen,dphi,pi,twopi,samfac,tsymbol
-  integer*2 iwave(NMAX)         !Generated wave file
-  integer sendingsh
-  integer dgen(13)
-  integer*1 data0(13),symbol(216)
-  logical first
-  include 'prcom2.f'
-  data first/.true./
-  save
-
-  nsym=207                               !Symbols per transmission
-  if(first) then
-     do i=1,nsym
-        pr2(i)=2*npr2(i)-1
-     enddo
-     pi=4.d0*atan(1.d0)
-     twopi=2.d0*pi
-     first=.false.
-  endif
-
-  call chkmsg(message,cok,nspecial,flip)
-  call packmsg(message,dgen)  !Pack 72-bit message into 12 six-bit symbols
-  call entail(dgen,data0)
-  call unpackmsg(dgen,msgsent)
-
-  nbytes=(72+31+7)/8
-  call encode(data0,nbytes,symbol(2))    !Convolutional encoding
-  symbol(1)=0                            !Reference phase
-  sendingsh=0
-  if(iand(dgen(10),8).ne.0) sendingsh=-1 !Plain text flag
-  call interleave24(symbol(2),1)         !Apply JT4 interleaving
-
-! Set up necessary constants
-  tsymbol=2520.d0/11025.d0
-  dt=1.d0/(samfac*11025.d0)
-  f0=118*11025.d0/1024 + ntxdf
-  dfgen=11025.d0/2520                     !4.375 Hz
-  t=0.d0
-  phi=0.d0
-  j0=0
-  ndata=(nsym*11025.d0*samfac*tsymbol)/2
-  ndata=2*ndata
-  do i=1,ndata
-     t=t+dt
-     j=int(t/tsymbol) + 1   !Symbol number, 1-207
-     if(j.ne.j0) then
-        f=f0 + (npr2(j)+2*symbol(j)-1.5) * dfgen * mode4
-        if(flip.lt.0.0) f=f0+((1-npr2(j))+2*symbol(j)-1.5)*dfgen*mode4
-        dphi=twopi*dt*f
-        j0=j
-     endif
-     phi=phi+dphi
-     iwave(i)=32767.0*sin(phi)
-  enddo
-
-  do j=1,5512                !Put another 0.5 sec of silence at end
-     i=i+1
-     iwave(i)=0
-  enddo
-  nwave=i
-
-  if(flip.lt.0.0) then
-     do i=22,1,-1
-        if(msgsent(i:i).ne.' ') goto 10
-     enddo
-10   msgsent=msgsent(1:i)//' OOO'
-  endif
-  do i=22,1,-1
-     if(msgsent(i:i).ne.' ') goto 20
-  enddo
-20 nmsg=i
-
-!      write(*,3002) (symbol(i),i=1,207)
-! 3002 format(70i1)
-
-  return
-end subroutine gen24
-
diff --git a/lib/gen65.f90 b/lib/gen65.f90
index 8580238..69388c3 100644
--- a/lib/gen65.f90
+++ b/lib/gen65.f90
@@ -1,4 +1,4 @@
-subroutine gen65(msg0,ichk,msgsent,itone,itext)
+subroutine gen65(msg0,ichk,msgsent,itone,itype)
 
 ! Encodes a JT65 message to yieild itone(1:126)
 ! Temporarily, does not implement EME shorthands
@@ -10,7 +10,6 @@ subroutine gen65(msg0,ichk,msgsent,itone,itext)
 !  character*3 cok               !'   ' or 'OOO'
   integer dgen(13)
   integer sent(63)
-  logical text
   integer nprc(126)
   data nprc/1,0,0,1,1,0,0,0,1,1,1,1,1,1,0,1,0,1,0,0,  &
             0,1,0,1,1,0,0,1,0,0,0,1,1,1,0,0,1,1,1,1,  &
@@ -37,9 +36,7 @@ subroutine gen65(msg0,ichk,msgsent,itone,itext)
   nspecial=0
 !  call chkmsg(message,cok,nspecial,flip)
   if(nspecial.eq.0) then
-     call packmsg(message,dgen,text)     !Pack message into 72 bits
-     itext=0
-     if(text) itext=1
+     call packmsg(message,dgen,itype)    !Pack message into 72 bits
      call unpackmsg(dgen,msgsent)        !Unpack to get message sent
      if(ichk.ne.0) go to 999             !Return if checking only
 
diff --git a/lib/genjt9.f90 b/lib/genjt9.f90
index 90427e1..5dd8c0c 100644
--- a/lib/genjt9.f90
+++ b/lib/genjt9.f90
@@ -1,4 +1,4 @@
-subroutine genjt9(msg0,ichk,msgsent,i4tone,itext)
+subroutine genjt9(msg0,ichk,msgsent,i4tone,itype)
 
 ! Encodes a JT9 message and returns msgsent, the message as it will
 ! be decoded, and an integer array i4tone(85) of 9-FSK tone values 
@@ -14,7 +14,6 @@ subroutine genjt9(msg0,ichk,msgsent,i4tone,itext)
   integer*4 i4DataSymbols(69)             !Data symbols (values 0-7)
   integer*4 i4GrayCodedSymbols(69)        !Gray-coded symbols (values 0-7)
   integer*4 i4tone(85)                    !Tone #s, data and sync (values 0-8)
-  logical text
   include 'jt9sync.f90'
   save
 
@@ -31,9 +30,7 @@ subroutine genjt9(msg0,ichk,msgsent,i4tone,itext)
      message=message(i+1:)
   enddo
 
-  call packmsg(message,i4Msg6BitWords,text)   !Pack message into 12 6-bit bytes
-  itext=0
-  if(text) itext=1
+  call packmsg(message,i4Msg6BitWords,itype)  !Pack into 12 6-bit bytes
   call unpackmsg(i4Msg6BitWords,msgsent)      !Unpack to get msgsent
   if(ichk.ne.0) go to 999
   call entail(i4Msg6BitWords,i1Msg8BitBytes)  !Add tail, convert to 8-bit bytes
diff --git a/lib/geocentric.f90 b/lib/geocentric.f90
new file mode 100644
index 0000000..11ea7cb
--- /dev/null
+++ b/lib/geocentric.f90
@@ -0,0 +1,17 @@
+subroutine geocentric(alat,elev,hlt,erad)
+
+  implicit real*8 (a-h,o-z)
+
+! IAU 1976 flattening f, equatorial radius a
+  f = 1.d0/298.257d0
+  a = 6378140.d0
+  c = 1.d0/sqrt(1.d0 + (-2.d0 + f)*f*sin(alat)*sin(alat))
+  arcf = (a*c + elev)*cos(alat)
+  arsf = (a*(1.d0 - f)*(1.d0 - f)*c + elev)*sin(alat)
+  hlt = datan2(arsf,arcf)
+  erad = sqrt(arcf*arcf + arsf*arsf)
+  erad = 0.001d0*erad
+
+  return
+end subroutine geocentric
+
diff --git a/lib/getpfx1.f90 b/lib/getpfx1.f90
index 4d4e7aa..332278e 100644
--- a/lib/getpfx1.f90
+++ b/lib/getpfx1.f90
@@ -8,12 +8,12 @@ subroutine getpfx1(callsign,k,nv2)
   include 'pfx.f90'
 
   callsign0=callsign
-  nv2=0
+  nv2=1
   iz=index(callsign,' ') - 1
   if(iz.lt.0) iz=12
   islash=index(callsign(1:iz),'/')
   k=0
-  if(k.eq.0) go to 10                             !### Always use JT65v2 ###
+!  if(k.eq.0) go to 10     !Tnx to DL9RDZ for reminder:this was for tests only!
   c='   '
   if(islash.gt.0 .and. islash.le.(iz-4)) then
 ! Add-on prefix
@@ -22,11 +22,13 @@ subroutine getpfx1(callsign,k,nv2)
      do i=1,NZ
         if(pfx(i)(1:4).eq.c) then
            k=i
+           nv2=2
            go to 10
         endif
      enddo
      if(addpfx.eq.c) then
         k=449
+        nv2=2
         go to 10
      endif
 
@@ -37,6 +39,7 @@ subroutine getpfx1(callsign,k,nv2)
      do i=1,NZ2
         if(sfx(i).eq.c(1:1)) then
            k=400+i
+           nv2=3
            go to 10
         endif
      enddo
@@ -75,7 +78,7 @@ subroutine getpfx1(callsign,k,nv2)
            k=37*k + nchar(tpfx(2:2))
            k=37*k + nchar(tpfx(3:3))
            k=37*k + nchar(tpfx(4:4))
-           nv2=1
+           nv2=4
            i=index(callsign0,'/')
            callsign=callsign0(:i-1)
            callsign=callsign0(i+1:)
@@ -85,7 +88,7 @@ subroutine getpfx1(callsign,k,nv2)
            k=nchar(tsfx(1:1))
            k=37*k + nchar(tsfx(2:2))
            k=37*k + nchar(tsfx(3:3))
-           nv2=2
+           nv2=5
            i=index(callsign0,'/')
            callsign=callsign0(:i-1)
         endif
diff --git a/lib/gran.c b/lib/gran.c
index ceeb6da..24b9865 100644
--- a/lib/gran.c
+++ b/lib/gran.c
@@ -1,28 +1,28 @@
-#include <stdlib.h>
-#include <math.h>
-
-/* Generate gaussian random float with mean=0 and std_dev=1 */
-float gran_()
-{
-  float fac,rsq,v1,v2;
-  static float gset;
-  static int iset;
-
-  if(iset){
-    /* Already got one */
-    iset = 0;
-    return gset;
-  }
-  /* Generate two evenly distributed numbers between -1 and +1
-   * that are inside the unit circle
-   */
-  do {
-    v1 = 2.0 * (float)rand() / RAND_MAX - 1;
-    v2 = 2.0 * (float)rand() / RAND_MAX - 1;
-    rsq = v1*v1 + v2*v2;
-  } while(rsq >= 1.0 || rsq == 0.0);
-  fac = sqrt(-2.0*log(rsq)/rsq);
-  gset = v1*fac;
-  iset++;
-  return v2*fac;
-}
+#include <stdlib.h>
+#include <math.h>
+
+/* Generate gaussian random float with mean=0 and std_dev=1 */
+float gran_()
+{
+  float fac,rsq,v1,v2;
+  static float gset;
+  static int iset;
+
+  if(iset){
+    /* Already got one */
+    iset = 0;
+    return gset;
+  }
+  /* Generate two evenly distributed numbers between -1 and +1
+   * that are inside the unit circle
+   */
+  do {
+    v1 = 2.0 * (float)rand() / RAND_MAX - 1;
+    v2 = 2.0 * (float)rand() / RAND_MAX - 1;
+    rsq = v1*v1 + v2*v2;
+  } while(rsq >= 1.0 || rsq == 0.0);
+  fac = sqrt(-2.0*log(rsq)/rsq);
+  gset = v1*fac;
+  iset++;
+  return v2*fac;
+}
diff --git a/lib/init_rs.c b/lib/init_rs.c
index eb27119..b836c1c 100644
--- a/lib/init_rs.c
+++ b/lib/init_rs.c
@@ -38,7 +38,7 @@ void *INIT_RS(int symsize,int gfpoly,int fcr,int prim,
   int i, j, sr,root,iprim;
 
   /* Check parameter ranges */
-  if(symsize < 0 || symsize > 8*sizeof(DTYPE))
+  if(symsize < 0 || symsize > (int)(8*sizeof(DTYPE)))
     return NULL; /* Need version with ints rather than chars */
 
   if(fcr < 0 || fcr >= (1<<symsize))
diff --git a/lib/jt65a.f90 b/lib/jt65a.f90
index 0c061ed..a1578fa 100644
--- a/lib/jt65a.f90
+++ b/lib/jt65a.f90
@@ -1,18 +1,26 @@
-subroutine jt65a(dd,npts,newdat,nutc,nfa,nfqso,ntol,nagain,ndecoded)
+subroutine jt65a(dd0,npts,newdat,nutc,nf1,nf2,nfqso,ntol,nagain,ndecoded)
 
 !  Process dd() data to find and decode JT65 signals.
 
   parameter (NSZ=3413)
   parameter (NZMAX=60*12000)
   parameter (NFFT=8192)
+  real dd0(NZMAX)
   real dd(NZMAX)
   real*4 ss(322,NSZ)
   real*4 savg(NSZ)
   logical done(NSZ)
   real a(5)
   character decoded*22
+  common/decstats/num65,numbm,numkv,num9,numfano
   save
 
+  dd=0.
+  tskip=2.0
+  nskip=12000*tskip
+  dd(1+nskip:npts+nskip)=dd0(1:npts)
+  npts=npts+nskip
+
   if(newdat.ne.0) then
      call timer('symsp65 ',0)
      call symspec65(dd,npts,ss,nhsym,savg)    !Get normalized symbol spectra
@@ -30,8 +38,8 @@ subroutine jt65a(dd,npts,newdat,nutc,nfa,nfqso,ntol,nagain,ndecoded)
         fa=nfqso - ntol
         fb=nfqso + ntol
      else                             !Wideband decode at all freqs
-        fa=200
-        fb=nfa
+        fa=nf1
+        fb=nf2
      endif
      ia=max(51,nint(fa/df))
      ib=min(NSZ-51,nint(fb/df))
@@ -53,7 +61,7 @@ subroutine jt65a(dd,npts,newdat,nutc,nfa,nfqso,ntol,nagain,ndecoded)
 
         nflip=nint(flipk)
         call timer('decod65a',0)
-        call decode65a(dd,npts,newdat,freq,nflip,mode65,sync2,a,dt,   &
+        call decode65a(dd,npts,newdat,nqd,freq,nflip,mode65,sync2,a,dt,   &
              nbmkv,nhist,decoded)
         call timer('decod65a',1)
 
@@ -68,11 +76,23 @@ subroutine jt65a(dd,npts,newdat,nutc,nfa,nfqso,ntol,nagain,ndecoded)
            nsnr=nint(s2db)
            if(nsnr.lt.-30) nsnr=-30
            if(nsnr.gt.-1) nsnr=-1
+           dt=dt-tskip
+           if(nbmkv.eq.1) numbm=numbm+1
+           if(nbmkv.eq.2) numkv=numkv+1 
+
+! Serialize writes - see also decjt9.f90
+
+           !$omp critical(decode_results) 
+
            write(*,1010) nutc,nsnr,dt,nfreq,decoded
 1010       format(i4.4,i4,f5.1,i5,1x,'#',1x,a22)
            write(13,1012) nutc,nint(sync1),nsnr,dt,float(nfreq),ndrift,  &
                 decoded,nbmkv
 1012       format(i4.4,i4,i5,f6.1,f8.0,i4,3x,a22,' JT65',i4)
+           call flush(6)
+           call flush(13)
+           !$omp end critical(decode_results)
+
            freq0=freq+a(1)
            i2=min(NSZ,i+15)                !### ??? ###
            done(i:i2)=.true.
diff --git a/lib/jt65code.f90 b/lib/jt65code.f90
new file mode 100644
index 0000000..9d52890
--- /dev/null
+++ b/lib/jt65code.f90
@@ -0,0 +1,104 @@
+program JT65code
+
+! Provides examples of message packing, bit and symbol ordering,
+! Reed Solomon encoding, and other necessary details of the JT65
+! protocol.
+
+  character*22 testmsg(26)
+  character*22 msg,msg0,msg1,decoded,cok*3,bad*1,msgtype*10
+  integer dgen(12),sent(63),recd(12),era(51)
+
+  nargs=iargc()
+  if(nargs.ne.1) then
+     print*,'Usage: jt65code "message"'
+     print*,'       jt65code -t'
+     go to 999
+  endif
+
+  call getarg(1,msg)                     !Get message from command line
+  nmsg=1
+  if(msg(1:2).eq."-t") then
+     testmsg(1)="KA1ABC WB9XYZ EN34"
+     testmsg(2)="KA1ABC WB9XYZ EN34 OOO"
+     testmsg(3)="KA1ABC WB9XYZ RO"
+     testmsg(4)="KA1ABC WB9XYZ -21"
+     testmsg(5)="KA1ABC WB9XYZ R-19"
+     testmsg(6)="KA1ABC WB9XYZ RRR"
+     testmsg(7)="KA1ABC WB9XYZ 73"
+     testmsg(8)="KA1ABC WB9XYZ"
+     testmsg(9)="KA1ABC WB9XYZ OOO"
+     testmsg(10)="KA1ABC WB9XYZ RO"
+     testmsg(11)="ZL/KA1ABC WB9XYZ"
+     testmsg(12)="KA1ABC ZL/WB9XYZ"
+     testmsg(13)="KA1ABC/4 WB9XYZ"
+     testmsg(14)="KA1ABC WB9XYZ/4"
+     testmsg(15)="CQ ZL4/KA1ABC"
+     testmsg(16)="DE ZL4/KA1ABC"
+     testmsg(17)="QRZ ZL4/KA1ABC"
+     testmsg(18)="CQ WB9XYZ/VE4"
+     testmsg(19)="HELLO WORLD"
+     testmsg(20)="ZL4/KA1ABC 73"
+     testmsg(21)="RO"
+     testmsg(22)="RRR"
+     testmsg(23)="73"
+     testmsg(24)="KA1ABC XL/WB9XYZ"
+     testmsg(25)="KA1ABC WB9XYZ/W4"
+     testmsg(26)="123456789ABCDEFGH"
+     nmsg=26
+  endif
+
+  write(*,1010)
+1010 format("Message                 Decoded                 Err?"/   &
+            "-----------------------------------------------------------------")
+
+  do imsg=1,nmsg
+     if(nmsg.gt.1) msg=testmsg(imsg)
+
+     call fmtmsg(msg,iz)                    !To upper, collapse mult blanks
+     msg0=msg                               !Input message
+     call chkmsg(msg,cok,nspecial,flip)     !See if it includes "OOO" report
+     msg1=msg                               !Message without "OOO"
+
+     if(nspecial.gt.0) then                  !or is a shorthand message
+        if(nspecial.eq.2) decoded="RO"
+        if(nspecial.eq.3) decoded="RRR"
+        if(nspecial.eq.4) decoded="73"
+        itype=-1
+        msgtype="Shorthand"
+        go to 10
+     endif
+
+     call packmsg(msg1,dgen,itype)           !Pack message into 12 six-bit bytes
+     msgtype=""
+     if(itype.eq.1) msgtype="Std Msg"
+     if(itype.eq.2) msgtype="Type 1 pfx"
+     if(itype.eq.3) msgtype="Type 1 sfx"
+     if(itype.eq.4) msgtype="Type 2 pfx"
+     if(itype.eq.5) msgtype="Type 2 sfx"
+     if(itype.eq.6) msgtype="Free text"
+
+     call rs_encode(dgen,sent)               !RS encode
+     call interleave63(sent,1)               !Interleave channel symbols
+     call graycode(sent,63,1,sent)           !Apply Gray code
+     call graycode(sent,63,-1,sent)
+     call interleave63(sent,-1)
+     call rs_decode(sent,era,0,recd,nerr)
+     call unpackmsg(recd,decoded)            !Unpack the user message
+     if(cok.eq."OOO") decoded(20:22)=cok
+     call fmtmsg(decoded,iz)
+
+10     bad=" "
+     if(decoded.ne.msg0) bad="*"
+     write(*,1020) msg0,decoded,bad,itype,msgtype
+1020 format(a22,2x,a22,3x,a1,i3,": ",a10)
+  enddo
+
+  if(nmsg.eq.1 .and. nspecial.eq.0) then
+     write(*,1030) dgen
+1030 format(/'Packed message, 6-bit symbols ',12i3) !Display packed symbols
+
+     write(*,1040) sent
+1040 format(/'Information-carrying channel symbols'/(i5,20i3))
+  endif
+
+999 end program JT65code
diff --git a/lib/jt9.f90 b/lib/jt9.f90
index 1f0a619..5a0b77c 100644
--- a/lib/jt9.f90
+++ b/lib/jt9.f90
@@ -1,111 +1,233 @@
-program jt9
-
-! Decoder for JT9.  Can run stand-alone, reading data from *.wav files;
-! or as the back end of wsjt-x, with data placed in a shared memory region.
-
-  include 'constants.f90'
-  integer*4 ihdr(11)
-  real*4 s(NSMAX)
-  integer*2 id2
-  character*80 arg,infile
-  common/jt9com/ss(184,NSMAX),savg(NSMAX),id2(NMAX),nutc,ndiskdat,       &
-       ntr,mousefqso,newdat,nfa,nfb,ntol,kin,nzhsym,nsynced,ndecoded
-  common/tracer/limtrace,lu
-
-  nargs=iargc()
-  if(nargs.lt.1) then
-     print*,'Usage: jt9 TRperiod ndepth rxfreq file1 [file2 ...]'
-     print*,'       Reads data from *.wav files.'
-     print*,''
-     print*,'       jt9 -s <key>'
-     print*,'       Gets data from shared memory region with key==<key>'
-     go to 999
-  endif
-  call getarg(1,arg)
-  if(arg(1:2).eq.'-s') then
-! Multiple instances:
-     call getarg(2,arg)
-     i0=len(trim(arg))
-     call jt9a(trim(arg))
-     go to 999
-  endif
-  read(arg,*) ntrperiod
-  call getarg(2,arg)
-  read(arg,*) ndepth
-  call getarg(3,arg)
-  read(arg,*) nrxfreq
-  ifile1=4
-
-  limtrace=0
-  lu=12
-
-  do ifile=ifile1,nargs
-     call getarg(ifile,infile)
-     open(10,file=infile,access='stream',status='old',err=998)
-     read(10) ihdr
-     nutc0=ihdr(1)                           !Silence compiler warning
-     i1=index(infile,'.wav')
-     read(infile(i1-4:i1-1),*,err=1) nutc0
-     go to 2
-1    nutc0=0
-2    nsps=0
-     if(ntrperiod.eq.1)  then
-        nsps=6912
-        nzhsym=173
-     else if(ntrperiod.eq.2)  then
-        nsps=15360
-        nzhsym=178
-     else if(ntrperiod.eq.5)  then
-        nsps=40960
-        nzhsym=172
-     else if(ntrperiod.eq.10) then
-        nsps=82944
-        nzhsym=171
-     else if(ntrperiod.eq.30) then
-        nsps=252000
-        nzhsym=167
-     endif
-     if(nsps.eq.0) stop 'Error: bad TRperiod'
-
-     kstep=nsps/2
-     k=0
-     nhsym0=-999
-     npts=(60*ntrperiod-6)*12000
-     if(ifile.eq.ifile1) then
-        open(12,file='timer.out',status='unknown')
-        call timer('jt9     ',0)
-     endif
-
-     id2=0                               !??? Why is this necessary ???
-
-     do iblk=1,npts/kstep
-        k=iblk*kstep
-        call timer('read_wav',0)
-        read(10,end=10) id2(k-kstep+1:k)
-        call timer('read_wav',1)
-
-        nhsym=(k-2048)/kstep
-        if(nhsym.ge.1 .and. nhsym.ne.nhsym0) then
-! Emit signal readyForFFT
-           ingain=0
-           call timer('symspec ',0)
-           call symspec(k,ntrperiod,nsps,ingain,slope,pxdb,s,df3,ihsym,npts8)
-           call timer('symspec ',1)
-           nhsym0=nhsym
-           if(ihsym.ge.173) go to 10
-        endif
-     enddo
-
-10   close(10)
-     call fillcom(nutc0,ndepth,nrxfreq)
-     call decoder(ss,id2)
-  enddo
-
-  call timer('jt9     ',1)
-  call timer('jt9     ',101)
-  go to 999
-
-998 print*,'Cannot open file:'
-  print*,infile
-
-999 end program jt9
+program jt9
+
+! Decoder for JT9.  Can run stand-alone, reading data from *.wav files;
+! or as the back end of wsjt-x, with data placed in a shared memory region.
+
+  use options
+  use prog_args
+  use, intrinsic :: iso_c_binding
+  use FFTW3
+
+  include 'constants.f90'
+  integer(C_INT) iret
+  integer*4 ihdr(11)
+  real*4 s(NSMAX)
+  integer*2 id2
+  character c
+  character(len=500) optarg, infile
+  character wisfile*80
+  integer :: arglen,stat,offset,remain,mode=0,flow=200,fsplit=2700,fhigh=4007,nrxfreq=1500,ntrperiod=1,ndepth=1
+  logical :: shmem = .false., read_files = .false., have_args = .false., tx9 = .false., display_help = .false.
+  type (option) :: long_options(16) = [ &
+    option ('help', .false., 'h', 'Display this help message', ''), &
+    option ('shmem', .true., 's', 'Use shared memory for sample data', '<key>'), &
+    option ('tr-period', .true., 'p', 'Tx/Rx period, default=1', '<minutes>'), &
+    option ('executable-path', .true., 'e', 'Location of subordinate executables (KVASD) default="."', '<path>'), &
+    option ('data-path', .true., 'a', 'Location of writeable data files, detfault="."', '<path>'), &
+    option ('temp-path', .true., 't', 'Temporary files path, default="."', '<path>'), &
+    option ('lowest', .true., 'L', 'Lowest frequency decoded (JT65), default=200Hz', '<hertz>'), &
+    option ('highest', .true., 'H', 'Highest frequency decoded, default=4007Hz', '<hertz>'), &
+    option ('split', .true., 'S', 'Lowest JT9 frequency decoded, default=2700Hz', '<hertz>'), &
+    option ('rx-frequency', .true., 'f', 'Receive frequency offset, default=1500', '<hertz>'), &
+    option ('patience', .true., 'w', 'FFTW3 planing patience (0-4), default=1', '<patience>'), &
+    option ('fft-threads', .true., 'm', 'Number of threads to process large FFTs, default=1', '<number>'), &
+    option ('jt65', .false., '6', 'JT65 mode', ''), &
+    option ('jt9', .false., '9', 'JT9 mode', ''), &
+    option ('depth', .true., 'd', 'JT9 decoding depth (1-3), default=1', '<number>'), &
+    option ('tx-jt9', .false., 'T', 'Tx mode is JT9, default=JT65', '') ]
+  common/jt9com/ss(184,NSMAX),savg(NSMAX),id2(NMAX),nutc,ndiskdat,ntr,       &
+       mousefqso,newdat,nfa,nfsplit,nfb,ntol,kin,nzhsym,nsynced,ndecoded
+  common/tracer/limtrace,lu
+  common/patience/npatience,nthreads
+  common/decstats/num65,numbm,numkv,num9,numfano,infile
+  data npatience/1/,nthreads/1/
+
+  do
+     call getopt('hs:e:a:r:m:p:d:f:w:t:96TL:S:H:',long_options,c,optarg,arglen,stat,     &
+          offset,remain)
+     if (stat .ne. 0) then
+        exit
+     end if
+     have_args = .true.
+     select case (c)
+        case ('h')
+           display_help = .true.
+
+        case ('s')
+           shmem = .true.
+           shm_key = optarg(:arglen)
+
+        case ('e')
+           exe_dir = optarg(:arglen)
+
+        case ('a')
+           data_dir = optarg(:arglen)
+
+        case ('t')
+           temp_dir = optarg(:arglen)
+
+        case ('m')
+           read (optarg(:arglen), *) nthreads
+
+        case ('p')
+           read_files = .true.
+           read (optarg(:arglen), *) ntrperiod
+
+        case ('d')
+           read_files = .true.
+           read (optarg(:arglen), *) ndepth
+
+        case ('f')
+           read_files = .true.
+           read (optarg(:arglen), *) nrxfreq
+
+        case ('L')
+           read_files = .true.
+           read (optarg(:arglen), *) flow
+
+        case ('S')
+           read_files = .true.
+           read (optarg(:arglen), *) fsplit
+
+        case ('H')
+           read_files = .true.
+           read (optarg(:arglen), *) fhigh
+
+        case ('6')
+           read_files = .true.
+           if (mode.lt.65) mode = mode + 65
+
+        case ('9')
+           read_files = .true.
+           if (mode.lt.9.or.mode.eq.65) mode = mode + 9
+
+        case ('T')
+           read_files = .true.
+           tx9 = .true.
+
+        case ('w')
+           read (optarg(:arglen), *) npatience
+
+     end select
+  end do
+
+  if (display_help .or. .not. have_args .or. (stat .lt. 0 .or. (shmem .and. remain .gt. 0)   &
+       .or. (read_files .and. remain .eq. 0) .or.                          &
+       (shmem .and. read_files))) then
+     print*,'Usage: jt9 -p <per> OPTIONS file1 [file2 ...]'
+     print*,'       Reads data from *.wav files.'
+     print*,''
+     print*,'       jt9 -s <key> [-w n] [-m n] [-e path] [-a path] [-t path]'
+     print*,'       Gets data from shared memory region with key==<key>'
+     do i = 1, size (long_options)
+       print*,''
+       call long_options(i) % print (6)
+     end do
+     go to 999
+  endif
+
+  iret=fftwf_init_threads()                   !Initialize FFTW threading 
+  call fftwf_plan_with_nthreads(1)            !Default to 1 thread but use nthreads for the big ones
+! Import FFTW wisdom, if available
+  wisfile=trim(data_dir)//'/jt9_wisdom.dat'// C_NULL_CHAR
+  iret=fftwf_import_wisdom_from_filename(wisfile)
+
+  num65=0
+  numbm=0
+  numkv=0
+  num9=0
+  numfano=0
+
+  if (shmem) then
+     call jt9a()
+     go to 999
+  endif
+
+  limtrace=0
+  lu=12
+  nflatten=0
+
+  do iarg = offset + 1, offset + remain
+     call get_command_argument (iarg, optarg, arglen)
+     infile = optarg(:arglen)
+     open(10,file=infile,access='stream',status='old',err=998)
+     read(10) ihdr
+     nutc0=ihdr(1)                           !Silence compiler warning
+     i1=index(infile,'.wav')
+     read(infile(i1-4:i1-1),*,err=1) nutc0
+     go to 2
+1    nutc0=0
+2    nsps=0
+     if(ntrperiod.eq.1)  then
+        nsps=6912
+        nzhsym=173
+     else if(ntrperiod.eq.2)  then
+        nsps=15360
+        nzhsym=178
+     else if(ntrperiod.eq.5)  then
+        nsps=40960
+        nzhsym=172
+     else if(ntrperiod.eq.10) then
+        nsps=82944
+        nzhsym=171
+     else if(ntrperiod.eq.30) then
+        nsps=252000
+        nzhsym=167
+     endif
+     if(nsps.eq.0) stop 'Error: bad TRperiod'
+
+     kstep=nsps/2
+     k=0
+     nhsym0=-999
+     npts=(60*ntrperiod-6)*12000
+     if(iarg .eq. offset + 1) then
+        open(12,file=trim(data_dir)//'/timer.out',status='unknown')
+        call timer('jt9     ',0)
+     endif
+
+     id2=0                               !??? Why is this necessary ???
+
+     do iblk=1,npts/kstep
+        k=iblk*kstep
+        call timer('read_wav',0)
+        read(10,end=10) id2(k-kstep+1:k)
+        call timer('read_wav',1)
+
+        nhsym=(k-2048)/kstep
+        if(nhsym.ge.1 .and. nhsym.ne.nhsym0) then
+! Emit signal readyForFFT
+           ingain=0
+           call timer('symspec ',0)
+           call symspec(k,ntrperiod,nsps,ingain,nflatten,pxdb,s,df3,ihsym,npts8)
+           call timer('symspec ',1)
+           nhsym0=nhsym
+           if(ihsym.ge.173) go to 10
+        endif
+     enddo
+
+10   close(10)
+     call fillcom(nutc0,ndepth,nrxfreq,mode,tx9,flow,fsplit,fhigh)
+     call decoder(ss,id2)
+  enddo
+
+  call timer('jt9     ',1)
+  call timer('jt9     ',101)
+  go to 999
+
+998 print*,'Cannot open file:'
+  print*,infile
+
+999 continue
+! Output decoder statistics
+  write(12,1100) numbm,numkv,numbm+numkv,num65,numfano,num9
+1100 format(58('-')/'     BM      KV     JT65   Tries     JT9   Tries'/  &
+            58('-')/6i8)
+
+! Save wisdom and free memory
+  iret=fftwf_export_wisdom_to_filename(wisfile)
+  call four2a(a,-1,1,1,1)
+  call filbig(a,-1,1,0.0,0,0,0,0,0)        !used for FFT plans
+  call fftwf_cleanup_threads()
+  call fftwf_cleanup()
+
+end program jt9
diff --git a/lib/jt9a.f90 b/lib/jt9a.f90
index 113533c..ae34c82 100644
--- a/lib/jt9a.f90
+++ b/lib/jt9a.f90
@@ -1,72 +1,71 @@
-subroutine jt9a(thekey)
-
-  character(len=*), intent(in):: thekey
-
-! These routines connect the shared memory region to the decoder.
-  interface
-     function address_jt9()
-     integer*1, pointer :: address_jt9
-     end function address_jt9
-  end interface
-  
-  integer*1 attach_jt9
-!  integer*1 lock_jt9,unlock_jt9
-  integer size_jt9
-  integer*1, pointer :: p_jt9
-  character*80 cwd
-! Multiple instances:
-  character*80 mykey
-  logical fileExists
-  common/tracer/limtrace,lu
-
-! Multiple instances:
-  i0 = len(trim(thekey))
-
-  call getcwd(cwd)
-  open(12,file='timer.out',status='unknown')
-
-  limtrace=0
-!  limtrace=-1                            !Disable all calls to timer()
-  lu=12
-
-! Multiple instances: set the shared memory key before attaching
-  mykey=trim(repeat(thekey,1))
-  i0 = len(mykey)
-  i0=setkey_jt9(trim(mykey))
-
-  i1=attach_jt9()
-
-10 inquire(file=trim(cwd)//'/.lock',exist=fileExists)
-  if(fileExists) then
-     call sleep_msec(100)
-     go to 10
-  endif
-
-  inquire(file=trim(cwd)//'/.quit',exist=fileExists)
-  if(fileExists) then
-!     call ftnquit
-     i1=detach_jt9()
-     go to 999
-  endif
-  if(i1.eq.999999) stop                  !Silence compiler warning
-  
-  nbytes=size_jt9()
-  if(nbytes.le.0) then
-     print*,'jt9a: Shared memory mem_jt9 does not exist.' 
-     print*,"Must start 'jt9 -s <thekey>' from within WSJT-X."
-     go to 999
-  endif
-  p_jt9=>address_jt9()
-  call timer('jt9b    ',0)
-  call jt9b(p_jt9,nbytes)
-  call timer('jt9b    ',1)
-
-100 inquire(file=trim(cwd)//'/.lock',exist=fileExists)
-  if(fileExists) go to 10
-  call sleep_msec(100)
-  go to 100
-
-999 call timer('jt9b    ',101)
-
-  return
-end subroutine jt9a
+subroutine jt9a()
+
+  use prog_args
+
+! These routines connect the shared memory region to the decoder.
+  interface
+     function address_jt9()
+     integer*1, pointer :: address_jt9
+     end function address_jt9
+  end interface
+
+  integer*1 attach_jt9
+!  integer*1 lock_jt9,unlock_jt9
+  integer size_jt9
+  integer*1, pointer :: p_jt9
+  character*80 cwd
+! Multiple instances:
+  character*80 mykey
+  logical fileExists
+  common/tracer/limtrace,lu
+
+! Multiple instances:
+  i0 = len(trim(shm_key))
+
+  call getcwd(cwd)
+  open(12,file=trim(data_dir)//'/timer.out',status='unknown')
+
+  limtrace=0
+!  limtrace=-1                            !Disable all calls to timer()
+  lu=12
+
+! Multiple instances: set the shared memory key before attaching
+  mykey=trim(repeat(shm_key,1))
+  i0 = len(mykey)
+  i0=setkey_jt9(trim(mykey))
+
+  i1=attach_jt9()
+
+10 inquire(file=trim(temp_dir)//'/.lock',exist=fileExists)
+  if(fileExists) then
+     call sleep_msec(100)
+     go to 10
+  endif
+
+  inquire(file=trim(temp_dir)//'/.quit',exist=fileExists)
+  if(fileExists) then
+     i1=detach_jt9()
+     go to 999
+  endif
+  if(i1.eq.999999) stop                  !Silence compiler warning
+
+  nbytes=size_jt9()
+  if(nbytes.le.0) then
+     print*,'jt9a: Shared memory mem_jt9 does not exist.'
+     print*,"Must start 'jt9 -s <thekey>' from within WSJT-X."
+     go to 999
+  endif
+  p_jt9=>address_jt9()
+  call timer('jt9b    ',0)
+  call jt9b(p_jt9,nbytes)
+  call timer('jt9b    ',1)
+
+100 inquire(file=trim(temp_dir)//'/.lock',exist=fileExists)
+  if(fileExists) go to 10
+  call sleep_msec(100)
+  go to 100
+
+999 call timer('jt9b    ',101)
+
+  return
+end subroutine jt9a
diff --git a/lib/jt9c.f90 b/lib/jt9c.f90
index 57b3cb2..9f06274 100644
--- a/lib/jt9c.f90
+++ b/lib/jt9c.f90
@@ -4,17 +4,19 @@ subroutine jt9c(ss,savg,id2,nparams0)
   real*4 ss(184*NSMAX),savg(NSMAX)
   integer*2 id2(NTMAX*12000)
 
-  integer nparams0(21),nparams(21)
+  integer nparams0(22),nparams(22)
   character*20 datetime
-  common/npar/nutc,ndiskdat,ntrperiod,nfqso,newdat,npts8,nfa,nfb,ntol,  &
-       kin,nzhsym,nsave,nagain,ndepth,ntxmode,nmode,datetime
+  common/npar/nutc,ndiskdat,ntrperiod,nfqso,newdat,npts8,nfa,nfsplit,nfb,   &
+       ntol,kin,nzhsym,nsave,nagain,ndepth,ntxmode,nmode,datetime
+  common/patience/npatience,nthreads
   equivalence (nparams,nutc)
 
   nutc=id2(1)+int(savg(1))             !Silence compiler warning
   nparams=nparams0                     !Copy parameters into common/npar/
+  if(ndiskdat.ne.0) npatience=2
 
   call flush(6)
-!  if(sum(nparams).ne.0) call decoder(ss,id2)
+!  if(sum(nparams).ne.0) call decoder(ss,id2,ldir)
   call decoder(ss,id2)
 
   return
diff --git a/lib/jt9code.f90 b/lib/jt9code.f90
index a4f0d3e..12c385a 100644
--- a/lib/jt9code.f90
+++ b/lib/jt9code.f90
@@ -2,28 +2,70 @@ program jt9code
 
 ! Generate simulated data for testing of WSJT-X
 
-  character msg*22,msg0*22,decoded*22
+  character*22 testmsg(20)
+  character msg*22,msg0*22,decoded*22,bad*1,msgtype*10
   integer*4 i4tone(85)                     !Channel symbols (values 0-8)
   include 'jt9sync.f90'
 
   nargs=iargc()
   if(nargs.ne.1) then
      print*,'Usage: jt9code "message"'
+     print*,'       jt9code -t'
      go to 999
   endif
 
-  call getarg(1,msg0)
-  write(*,1000) msg0
-1000 format('Message:',3x,a22)
-  msg=msg0
-  ichk=0
-  itext=0
-  call genjt9(msg,ichk,decoded,i4tone,itext)       !Encode message into tone #s
-  write(*,1002) i4tone
-1002 format('Channel symbols:'/(30i2))
-  if(itext.eq.0) write(*,1004) decoded
-1004 format('Decoded message:',1x,a22)
-  if(itext.ne.0) write(*,1005) decoded
-1005 format('Decoded message:',1x,a22,3x,'(free text)')
+  call getarg(1,msg)
+  nmsg=1
+  if(msg(1:2).eq."-t") then
+     testmsg(1)="KA1ABC WB9XYZ EN34"
+     testmsg(2)="KA1ABC WB9XYZ RO"
+     testmsg(3)="KA1ABC WB9XYZ -21"
+     testmsg(4)="KA1ABC WB9XYZ R-19"
+     testmsg(5)="KA1ABC WB9XYZ RRR"
+     testmsg(6)="KA1ABC WB9XYZ 73"
+     testmsg(7)="KA1ABC WB9XYZ"
+     testmsg(8)="ZL/KA1ABC WB9XYZ"
+     testmsg(9)="KA1ABC ZL/WB9XYZ"
+     testmsg(10)="KA1ABC/4 WB9XYZ"
+     testmsg(11)="KA1ABC WB9XYZ/4"
+     testmsg(12)="CQ ZL4/KA1ABC"
+     testmsg(13)="DE ZL4/KA1ABC"
+     testmsg(14)="QRZ ZL4/KA1ABC"
+     testmsg(15)="CQ WB9XYZ/VE4"
+     testmsg(16)="HELLO WORLD"
+     testmsg(17)="ZL4/KA1ABC 73"
+     testmsg(18)="KA1ABC XL/WB9XYZ"
+     testmsg(19)="KA1ABC WB9XYZ/W4"
+     testmsg(20)="123456789ABCDEFGH"
+     nmsg=20
+  endif
+
+  write(*,1010)
+1010 format("Message                 Decoded                 Err?"/   &
+            "-----------------------------------------------------------------")
+  do imsg=1,nmsg
+     if(nmsg.gt.1) msg=testmsg(imsg)
+     call fmtmsg(msg,iz)                    !To upper, collapse mult blanks
+     msg0=msg                               !Input message
+
+     ichk=0
+     call genjt9(msg,ichk,decoded,i4tone,itype)   !Encode message into tone #s
+
+     msgtype=""
+     if(itype.eq.1) msgtype="Std Msg"
+     if(itype.eq.2) msgtype="Type 1 pfx"
+     if(itype.eq.3) msgtype="Type 1 sfx"
+     if(itype.eq.4) msgtype="Type 2 pfx"
+     if(itype.eq.5) msgtype="Type 2 sfx"
+     if(itype.eq.6) msgtype="Free text"
+
+     bad=" "
+     if(decoded.ne.msg0) bad="*"
+     write(*,1020) msg0,decoded,bad,itype,msgtype
+1020 format(a22,2x,a22,3x,a1,i3,": ",a10)
+  enddo
+
+  if(nmsg.eq.1) write(*,1030) i4tone
+1030 format(/'Channel symbols'/(30i2))
 
 999 end program jt9code
diff --git a/lib/decode9.f90 b/lib/jt9fano.f90
similarity index 84%
rename from lib/decode9.f90
rename to lib/jt9fano.f90
index 06809eb..0cd6b7a 100644
--- a/lib/decode9.f90
+++ b/lib/jt9fano.f90
@@ -1,4 +1,4 @@
-subroutine decode9(i1SoftSymbols,limit,nlim,msg)
+subroutine jt9fano(i1SoftSymbols,limit,nlim,msg)
 
 ! Decoder for JT9
 ! Input:   i1SoftSymbols(207) - Single-bit soft symbols
@@ -14,7 +14,7 @@ subroutine decode9(i1SoftSymbols,limit,nlim,msg)
   real*4 xx0(0:255)
 
   logical first
-  integer*4 mettab(0:255,0:1)
+  integer*4 mettab(-128:127,0:1)
   data first/.true./
   data xx0/                                                      & !Metric table
         1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000,  &
@@ -54,22 +54,26 @@ subroutine decode9(i1SoftSymbols,limit,nlim,msg)
   if(first) then
 ! Get the metric table
      bias=0.5
-     scale=10
+     scale=50
+     ndelta=nint(3.4*scale)
+     ib=160                          !Break point
+     slope=2                         !Slope beyond break
      do i=0,255
-        mettab(i,0)=nint(scale*(xx0(i)-bias))
-        if(i.ge.1) mettab(256-i,1)=mettab(i,0)
+        mettab(i-128,0)=nint(scale*(xx0(i)-bias))
+        if(i.gt.ib) mettab(i-128,0)=mettab(ib-128,0) - slope*(i-ib)
+        if(i.ge.1) mettab(128-i,1)=mettab(i-128,0)
      enddo
+     mettab(-128,1)=mettab(-127,1)
      first=.false.
   endif
 
   msg='                      '
   nbits=72
-  ndelta=17
   call fano232(i1SoftSymbols,nbits+31,mettab,ndelta,limit,i1DecodedBytes,   &
        ncycles,metric,ierr)
 
   nlim=ncycles/(nbits+31)
-  if(ncycles.lt.(nbits*limit)) then
+  if(ncycles.lt.((nbits+31)*limit)) then
      nbytes=(nbits+7)/8
      do i=1,nbytes
         n=i1DecodedBytes(i)
@@ -82,4 +86,4 @@ subroutine decode9(i1SoftSymbols,limit,nlim,msg)
   endif
 
   return
-end subroutine decode9
+end subroutine jt9fano
diff --git a/lib/jt9sim.f90 b/lib/jt9sim.f90
index f4f0cf6..21ed22a 100644
--- a/lib/jt9sim.f90
+++ b/lib/jt9sim.f90
@@ -2,10 +2,12 @@ program jt9sim
 
 ! Generate simulated data for testing of WSJT-X
 
+  use wavhdr
   parameter (NTMAX=120)
   parameter (NMAX=NTMAX*12000)
-  integer ihdr(11)
-  integer*2 iwave                  !Generated waveform (no noise)
+  type(hdr) h
+  integer*2 iwave(NMAX)                  !Generated waveform (no noise)
+  real*4 dat(NMAX)
   real*8 f0,f,dt,twopi,phi,dphi,baud,fspan,fsample,freq
   character msg*22,msg0*22,message*22,msgsent*22,arg*8,fname*11
 
@@ -15,19 +17,20 @@ program jt9sim
   integer*1 i1Bits(207)            !Encoded information-carrying bits
   integer*1 i1SoftSymbols(207)
   include 'jt9sync.f90'
-  common/acom/dat(NMAX),iwave(NMAX)
 
   nargs=iargc()
   if(nargs.ne.6) then
-     print*,'Usage: jt9sim "message" fspan nsigs minutes SNR nfiles'
-     print*,'Example:  "CQ K1ABC FN42" 200  20      2    -28    1'
+     print*,'Usage:   jt9sim "message"     fspan nsigs minutes SNR nfiles'
+     print*,'Example: jt9sim "CQ K1ABC FN42" 200  20      2    -28    1'
      print*,' '
      print*,'Enter message = "" to use entries in msgs.txt.'
      print*,'Enter SNR = 0 to generate a range of SNRs.'
+     print*,'Enter SNR = 99 to generate a noiseless signal at frequency fspan'
      go to 999
   endif
 
-  call getarg(1,msg0)
+  call getarg(1,msg0)  
+  call fmtmsg(msg0,iz)
   message=msg0                       !Transmitted message
   call getarg(2,arg)
   read(arg,*) fspan                  !Total freq range (Hz)
@@ -38,7 +41,7 @@ program jt9sim
   call getarg(5,arg)
   read(arg,*) snrdb                  !S/N in dB (2500 hz reference BW)
   call getarg(6,arg)
-  read(arg,*) nfiles                 !Number of files
+  read(arg,*) nfiles                 !Number of files     
 
   rmsdb=25.
   rms=10.0**(0.05*rmsdb)
@@ -55,17 +58,21 @@ program jt9sim
   if(nsps.eq.0) stop 'Bad value for minutes.'
 
   f0=1400.d0                         !Center frequency (Hz)
+  if(snrdb.gt.90.0) f0=fspan
+!  f0=3000.d0                         !Center frequency (Hz)
+
 !  f0=1500.0
 !  if(minutes.eq.5)  f0=1100.
 !  if(minutes.eq.10) f0=1050.
 !  if(minutes.eq.30) f0=1025.
-  
-  ihdr=0                             !Temporary ###
+
+
+  h=default_header(12000,npts)  
   k=0                                !Silence compiler warning
 
   if(msg0(1:3).eq.'sin') read(msg0(4:),*) sinfreq
   
-  open(12,file='msgs.txt',status='old')
+  if(message.eq."") open(12,file='msgs.txt',status='old')
 
   write(*,1000)
 1000 format('File  N    freq      S/N  Message'/    &
@@ -88,7 +95,7 @@ program jt9sim
      endif
 
      if(msg0.ne.'                      ') then
-        call genjt9(message,msgsent,i4tone) !Encode message into tone #s
+        call genjt9(message,0,msgsent,i4tone,itype) !Encode message into tone #s
      endif
 
      rewind 12
@@ -97,7 +104,7 @@ program jt9sim
         if(msg0.eq.'                      ') then
            read(12,1004) message                !Use pre-generated message texts
 1004       format(a22)
-           call genjt9(message,msgsent,i4tone)
+           call genjt9(message,0,msgsent,i4tone,itype)
         endif
 
         f=f0
@@ -105,6 +112,7 @@ program jt9sim
         snrdbx=snrdb 
 !        snrdbx=snrdb + (ifile-1)*4.0
         sig=10.0**(0.05*snrdbx)
+        if(snrdb.gt.90.0) sig=1.0
         write(*,1020) ifile,isig,f,snrdbx,msgsent
 1020    format(i3,i4,f10.3,f7.1,2x,a22)
 
@@ -132,11 +140,11 @@ program jt9sim
         enddo
      enddo
 
-     do i=1,npts
-        iwave(i)=nint(rms*dat(i))
-     enddo
+     fac=32767.0/nsigs
+     if(snrdb.ge.90.0) iwave(1:npts)=nint(fac*dat(1:npts))
+     if(snrdb.lt.90.0) iwave(1:npts)=nint(rms*dat(1:npts))
 
-     write(10) ihdr,iwave(1:npts)
+     write(10) h,iwave(1:npts)
      close(10)
 
 ! We're done!  Now decode the data symbols from i4tone, as a test.
@@ -153,12 +161,10 @@ program jt9sim
         do i=1,206
            i4=-10
            if(i1Bits(i).eq.1) i4=10
-           i4=i4+128
-           if(i4.le.127) i1SoftSymbols(k)=i4
-           if(i4.ge.128) i1SoftSymbols(k)=i4-256
+           i1SoftSymbols(i)=i4
         enddo
         limit=1000
-        call decode9(i1SoftSymbols,limit,nlim,msg)
+        call jt9fano(i1SoftSymbols,limit,nlim,msg)
         if(msg.ne.msg0) print*,'Decode error: ',msg0,' ',msg
      endif
   enddo
diff --git a/lib/libhamlib.dll.a b/lib/libhamlib.dll.a
deleted file mode 100644
index 7bb6d1b..0000000
Binary files a/lib/libhamlib.dll.a and /dev/null differ
diff --git a/lib/moon2.f90 b/lib/moon2.f90
new file mode 100644
index 0000000..8498267
--- /dev/null
+++ b/lib/moon2.f90
@@ -0,0 +1,166 @@
+subroutine moon2(y,m,Day,UT,lon,lat,RA,Dec,topRA,topDec,              &
+     LST,HA,Az,El,dist)
+
+  implicit none
+
+  integer y                           !Year
+  integer m                           !Month
+  integer Day                         !Day
+  real*8 UT                           !UTC in hours
+  real*8 RA,Dec                       !RA and Dec of moon
+
+! NB: Double caps are single caps in the writeup.
+
+  real*8 NN                           !Longitude of ascending node
+  real*8 i                            !Inclination to the ecliptic
+  real*8 w                            !Argument of perigee
+  real*8 a                            !Semi-major axis
+  real*8 e                            !Eccentricity
+  real*8 MM                           !Mean anomaly
+
+  real*8 v                            !True anomaly
+  real*8 EE                           !Eccentric anomaly
+  real*8 ecl                          !Obliquity of the ecliptic
+
+  real*8 d                            !Ephemeris time argument in days
+  real*8 r                            !Distance to sun, AU
+  real*8 xv,yv                        !x and y coords in ecliptic
+  real*8 lonecl,latecl                !Ecliptic long and lat of moon
+  real*8 xg,yg,zg                     !Ecliptic rectangular coords
+  real*8 Ms                           !Mean anomaly of sun
+  real*8 ws                           !Argument of perihelion of sun
+  real*8 Ls                           !Mean longitude of sun (Ns=0)
+  real*8 Lm                           !Mean longitude of moon
+  real*8 DD                           !Mean elongation of moon
+  real*8 FF                           !Argument of latitude for moon
+  real*8 xe,ye,ze                     !Equatorial geocentric coords of moon
+  real*8 mpar                         !Parallax of moon (r_E / d)
+  real*8 lat,lon                      !Station coordinates on earth
+  real*8 gclat                        !Geocentric latitude
+  real*8 rho                          !Earth radius factor
+  real*8 GMST0,LST,HA
+  real*8 g
+  real*8 topRA,topDec                 !Topocentric coordinates of Moon
+  real*8 Az,El
+  real*8 dist
+
+  real*8 rad,twopi,pi,pio2
+  data rad/57.2957795131d0/,twopi/6.283185307d0/
+
+  d=367*y - 7*(y+(m+9)/12)/4 + 275*m/9 + Day - 730530 + UT/24.d0
+  ecl = 23.4393d0 - 3.563d-7 * d
+
+! Orbital elements for Moon:  
+  NN = 125.1228d0 - 0.0529538083d0 * d
+  i = 5.1454d0
+  w = mod(318.0634d0 + 0.1643573223d0 * d + 360000.d0,360.d0)
+  a = 60.2666d0
+  e = 0.054900d0
+  MM = mod(115.3654d0 + 13.0649929509d0 * d + 360000.d0,360.d0)
+
+  EE = MM + e*rad*sin(MM/rad) * (1.d0 + e*cos(MM/rad))
+  EE = EE - (EE - e*rad*sin(EE/rad)-MM) / (1.d0 - e*cos(EE/rad))
+  EE = EE - (EE - e*rad*sin(EE/rad)-MM) / (1.d0 - e*cos(EE/rad))
+
+  xv = a * (cos(EE/rad) - e)
+  yv = a * (sqrt(1.d0-e*e) * sin(EE/rad))
+
+  v = mod(rad*atan2(yv,xv)+720.d0,360.d0)
+  r = sqrt(xv*xv + yv*yv)
+
+! Get geocentric position in ecliptic rectangular coordinates:
+
+  xg = r * (cos(NN/rad)*cos((v+w)/rad) -                          &
+       sin(NN/rad)*sin((v+w)/rad)*cos(i/rad))
+  yg = r * (sin(NN/rad)*cos((v+w)/rad) +                          &
+       cos(NN/rad)*sin((v+w)/rad)*cos(i/rad))
+  zg = r * (sin((v+w)/rad)*sin(i/rad))
+
+! Ecliptic longitude and latitude of moon:
+  lonecl = mod(rad*atan2(yg/rad,xg/rad)+720.d0,360.d0)
+  latecl = rad*atan2(zg/rad,sqrt(xg*xg + yg*yg)/rad)
+
+! Now include orbital perturbations:
+  Ms = mod(356.0470d0 + 0.9856002585d0 * d + 3600000.d0,360.d0)
+  ws = 282.9404d0 + 4.70935d-5*d
+  Ls = mod(Ms + ws + 720.d0,360.d0)
+  Lm = mod(MM + w + NN+720.d0,360.d0)
+  DD = mod(Lm - Ls + 360.d0,360.d0)
+  FF = mod(Lm - NN + 360.d0,360.d0)
+
+  lonecl = lonecl                                           &
+       -1.274d0 * sin((MM-2.d0*DD)/rad)                     &
+       +0.658d0 * sin(2.d0*DD/rad)                          &
+       -0.186d0 * sin(Ms/rad)                               &
+       -0.059d0 * sin((2.d0*MM-2.d0*DD)/rad)                &
+       -0.057d0 * sin((MM-2.d0*DD+Ms)/rad)                  &
+       +0.053d0 * sin((MM+2.d0*DD)/rad)                     &
+       +0.046d0 * sin((2.d0*DD-Ms)/rad)                     &
+       +0.041d0 * sin((MM-Ms)/rad)                          &
+       -0.035d0 * sin(DD/rad)                               &
+       -0.031d0 * sin((MM+Ms)/rad)                          &
+       -0.015d0 * sin((2.d0*FF-2.d0*DD)/rad)                &
+       +0.011d0 * sin((MM-4.d0*DD)/rad)
+
+  latecl = latecl                                           &
+       -0.173d0 * sin((FF-2.d0*DD)/rad)                     &
+       -0.055d0 * sin((MM-FF-2.d0*DD)/rad)                  &
+       -0.046d0 * sin((MM+FF-2.d0*DD)/rad)                  &
+       +0.033d0 * sin((FF+2.d0*DD)/rad)                     &
+       +0.017d0 * sin((2.d0*MM+FF)/rad)
+
+  r = 60.36298d0                                            &
+       - 3.27746d0*cos(MM/rad)                              &
+       - 0.57994d0*cos((MM-2.d0*DD)/rad)                    &
+       - 0.46357d0*cos(2.d0*DD/rad)                         &
+       - 0.08904d0*cos(2.d0*MM/rad)                         &
+       + 0.03865d0*cos((2.d0*MM-2.d0*DD)/rad)               &
+       - 0.03237d0*cos((2.d0*DD-Ms)/rad)                    &
+       - 0.02688d0*cos((MM+2.d0*DD)/rad)                    &
+       - 0.02358d0*cos((MM-2.d0*DD+Ms)/rad)                 &
+       - 0.02030d0*cos((MM-Ms)/rad)                         &
+       + 0.01719d0*cos(DD/rad)                              &
+       + 0.01671d0*cos((MM+Ms)/rad)
+
+  dist=r*6378.140d0
+
+! Geocentric coordinates:
+! Rectangular ecliptic coordinates of the moon:
+
+  xg = r * cos(lonecl/rad)*cos(latecl/rad)
+  yg = r * sin(lonecl/rad)*cos(latecl/rad)
+  zg = r *                 sin(latecl/rad)
+
+! Rectangular equatorial coordinates of the moon:
+  xe = xg
+  ye = yg*cos(ecl/rad) - zg*sin(ecl/rad)
+  ze = yg*sin(ecl/rad) + zg*cos(ecl/rad)
+   
+! Right Ascension, Declination:
+  RA = mod(rad*atan2(ye,xe)+360.d0,360.d0)
+  Dec = rad*atan2(ze,sqrt(xe*xe + ye*ye))
+
+! Now convert to topocentric system:
+  mpar=rad*asin(1.d0/r)
+!     alt_topoc = alt_geoc - mpar*cos(alt_geoc)
+  gclat = lat - 0.1924d0*sin(2.d0*lat/rad)
+  rho = 0.99883d0 + 0.00167d0*cos(2.d0*lat/rad)
+  GMST0 = (Ls + 180.d0)/15.d0
+  LST = mod(GMST0+UT+lon/15.d0+48.d0,24.d0)    !LST in hours
+  HA = 15.d0*LST - RA                          !HA in degrees
+  g = rad*atan(tan(gclat/rad)/cos(HA/rad))
+  topRA = RA - mpar*rho*cos(gclat/rad)*sin(HA/rad)/cos(Dec/rad)
+  topDec = Dec - mpar*rho*sin(gclat/rad)*sin((g-Dec)/rad)/sin(g/rad)
+
+  HA = 15.d0*LST - topRA                       !HA in degrees
+  if(HA.gt.180.d0) HA=HA-360.d0
+  if(HA.lt.-180.d0) HA=HA+360.d0
+
+  pi=0.5d0*twopi
+  pio2=0.5d0*pi
+  call dcoord(pi,pio2-lat/rad,0.d0,lat/rad,ha*twopi/360,topDec/rad,az,el)
+  Az=az*rad
+  El=El*rad
+
+  return
+end subroutine moon2
diff --git a/lib/moondop.f90 b/lib/moondop.f90
new file mode 100644
index 0000000..2105658
--- /dev/null
+++ b/lib/moondop.f90
@@ -0,0 +1,72 @@
+subroutine MoonDop(nyear,month,nday,uth4,lon4,lat4,RAMoon4,        &
+     DecMoon4,LST4,HA4,AzMoon4,ElMoon4,vr4,dist4)
+
+  implicit real*8 (a-h,o-z)
+  real*4 uth4                    !UT in hours
+  real*4 lon4                    !West longitude, degrees
+  real*4 lat4                    !Latitude, degrees
+  real*4 RAMoon4                 !Topocentric RA of moon, hours
+  real*4 DecMoon4                !Topocentric Dec of Moon, degrees
+  real*4 LST4                    !Locat sidereal time, hours
+  real*4 HA4                     !Local Hour angle, degrees
+  real*4 AzMoon4                 !Topocentric Azimuth of moon, degrees
+  real*4 ElMoon4                 !Topocentric Elevation of moon, degrees
+  real*4 vr4                     !Radial velocity of moon wrt obs, km/s
+  real*4 dist4                   !Echo time, seconds
+
+  real*8 LST
+  real*8 RME(6)                  !Vector from Earth center to Moon
+  real*8 RAE(6)                  !Vector from Earth center to Obs
+  real*8 RMA(6)                  !Vector from Obs to Moon
+  real*8 rme0(6)
+  logical km
+
+  data rad/57.2957795130823d0/,twopi/6.28310530717959d0/
+  
+  km=.true.
+  dlat=lat4/rad
+  dlong1=lon4/rad
+  elev1=200.d0
+  call geocentric(dlat,elev1,dlat1,erad1)
+
+  dt=100.d0                       !For numerical derivative, in seconds
+  UT=uth4
+
+! NB: geodetic latitude used here, but geocentric latitude used when 
+! determining Earth-rotation contribution to Doppler.
+
+  call moon2(nyear,month,nDay,UT-dt/3600.d0,dlong1*rad,dlat*rad,     &
+       RA,Dec,topRA,topDec,LST,HA,Az0,El0,dist)
+  call toxyz(RA/rad,Dec/rad,dist,rme0)      !Convert to rectangular coords
+
+  call moon2(nyear,month,nDay,UT,dlong1*rad,dlat*rad,                &
+       RA,Dec,topRA,topDec,LST,HA,Az,El,dist)
+  call toxyz(RA/rad,Dec/rad,dist,rme)       !Convert to rectangular coords
+
+  phi=LST*twopi/24.d0
+  call toxyz(phi,dlat1,erad1,rae)           !Gencentric numbers used here!
+  radps=twopi/(86400.d0/1.002737909d0)
+  rae(4)=-rae(2)*radps                      !Vel of Obs wrt Earth center
+  rae(5)=rae(1)*radps
+  rae(6)=0.d0
+
+  do i=1,3
+     rme(i+3)=(rme(i)-rme0(i))/dt
+     rma(i)=rme(i)-rae(i)
+     rma(i+3)=rme(i+3)-rae(i+3)
+  enddo
+
+  call fromxyz(rma,alpha1,delta1,dtopo0)     !Get topocentric coords
+  vr=dot(rma(4),rma)/dtopo0
+
+  RAMoon4=topRA
+  DecMoon4=topDec
+  LST4=LST
+  HA4=HA
+  AzMoon4=Az
+  ElMoon4=El
+  vr4=vr
+  dist4=dist
+
+  return
+end subroutine MoonDop
diff --git a/lib/nfft.dat b/lib/nfft.dat
new file mode 100644
index 0000000..6378e64
--- /dev/null
+++ b/lib/nfft.dat
@@ -0,0 +1,2067 @@
+       8    2  2  2
+       9    3  3
+      10    2  5
+      12    2  2  3
+      14    2  7
+      15    3  5
+      16    2  2  2  2
+      18    2  3  3
+      20    2  2  5
+      21    3  7
+      24    2  2  2  3
+      25    5  5
+      27    3  3  3
+      28    2  2  7
+      30    2  3  5
+      32    2  2  2  2  2
+      35    5  7
+      36    2  2  3  3
+      40    2  2  2  5
+      42    2  3  7
+      45    3  3  5
+      48    2  2  2  2  3
+      49    7  7
+      50    2  5  5
+      54    2  3  3  3
+      56    2  2  2  7
+      60    2  2  3  5
+      63    3  3  7
+      64    2  2  2  2  2  2
+      70    2  5  7
+      72    2  2  2  3  3
+      75    3  5  5
+      80    2  2  2  2  5
+      81    3  3  3  3
+      84    2  2  3  7
+      90    2  3  3  5
+      96    2  2  2  2  2  3
+      98    2  7  7
+     100    2  2  5  5
+     105    3  5  7
+     108    2  2  3  3  3
+     112    2  2  2  2  7
+     120    2  2  2  3  5
+     125    5  5  5
+     126    2  3  3  7
+     128    2  2  2  2  2  2  2
+     135    3  3  3  5
+     140    2  2  5  7
+     144    2  2  2  2  3  3
+     147    3  7  7
+     150    2  3  5  5
+     160    2  2  2  2  2  5
+     162    2  3  3  3  3
+     168    2  2  2  3  7
+     175    5  5  7
+     180    2  2  3  3  5
+     189    3  3  3  7
+     192    2  2  2  2  2  2  3
+     196    2  2  7  7
+     200    2  2  2  5  5
+     210    2  3  5  7
+     216    2  2  2  3  3  3
+     224    2  2  2  2  2  7
+     225    3  3  5  5
+     240    2  2  2  2  3  5
+     243    3  3  3  3  3
+     245    5  7  7
+     250    2  5  5  5
+     252    2  2  3  3  7
+     256    2  2  2  2  2  2  2  2
+     270    2  3  3  3  5
+     280    2  2  2  5  7
+     288    2  2  2  2  2  3  3
+     294    2  3  7  7
+     300    2  2  3  5  5
+     315    3  3  5  7
+     320    2  2  2  2  2  2  5
+     324    2  2  3  3  3  3
+     336    2  2  2  2  3  7
+     343    7  7  7
+     350    2  5  5  7
+     360    2  2  2  3  3  5
+     375    3  5  5  5
+     378    2  3  3  3  7
+     384    2  2  2  2  2  2  2  3
+     392    2  2  2  7  7
+     400    2  2  2  2  5  5
+     405    3  3  3  3  5
+     420    2  2  3  5  7
+     432    2  2  2  2  3  3  3
+     441    3  3  7  7
+     448    2  2  2  2  2  2  7
+     450    2  3  3  5  5
+     480    2  2  2  2  2  3  5
+     486    2  3  3  3  3  3
+     490    2  5  7  7
+     500    2  2  5  5  5
+     504    2  2  2  3  3  7
+     512    2  2  2  2  2  2  2  2  2
+     525    3  5  5  7
+     540    2  2  3  3  3  5
+     560    2  2  2  2  5  7
+     567    3  3  3  3  7
+     576    2  2  2  2  2  2  3  3
+     588    2  2  3  7  7
+     600    2  2  2  3  5  5
+     625    5  5  5  5
+     630    2  3  3  5  7
+     640    2  2  2  2  2  2  2  5
+     648    2  2  2  3  3  3  3
+     672    2  2  2  2  2  3  7
+     675    3  3  3  5  5
+     686    2  7  7  7
+     700    2  2  5  5  7
+     720    2  2  2  2  3  3  5
+     729    3  3  3  3  3  3
+     735    3  5  7  7
+     750    2  3  5  5  5
+     756    2  2  3  3  3  7
+     768    2  2  2  2  2  2  2  2  3
+     784    2  2  2  2  7  7
+     800    2  2  2  2  2  5  5
+     810    2  3  3  3  3  5
+     840    2  2  2  3  5  7
+     864    2  2  2  2  2  3  3  3
+     875    5  5  5  7
+     882    2  3  3  7  7
+     896    2  2  2  2  2  2  2  7
+     900    2  2  3  3  5  5
+     945    3  3  3  5  7
+     960    2  2  2  2  2  2  3  5
+     972    2  2  3  3  3  3  3
+     980    2  2  5  7  7
+    1000    2  2  2  5  5  5
+    1008    2  2  2  2  3  3  7
+    1024    2  2  2  2  2  2  2  2  2  2
+    1029    3  7  7  7
+    1050    2  3  5  5  7
+    1080    2  2  2  3  3  3  5
+    1120    2  2  2  2  2  5  7
+    1125    3  3  5  5  5
+    1134    2  3  3  3  3  7
+    1152    2  2  2  2  2  2  2  3  3
+    1176    2  2  2  3  7  7
+    1200    2  2  2  2  3  5  5
+    1215    3  3  3  3  3  5
+    1225    5  5  7  7
+    1250    2  5  5  5  5
+    1260    2  2  3  3  5  7
+    1280    2  2  2  2  2  2  2  2  5
+    1296    2  2  2  2  3  3  3  3
+    1323    3  3  3  7  7
+    1344    2  2  2  2  2  2  3  7
+    1350    2  3  3  3  5  5
+    1372    2  2  7  7  7
+    1400    2  2  2  5  5  7
+    1440    2  2  2  2  2  3  3  5
+    1458    2  3  3  3  3  3  3
+    1470    2  3  5  7  7
+    1500    2  2  3  5  5  5
+    1512    2  2  2  3  3  3  7
+    1536    2  2  2  2  2  2  2  2  2  3
+    1568    2  2  2  2  2  7  7
+    1575    3  3  5  5  7
+    1600    2  2  2  2  2  2  5  5
+    1620    2  2  3  3  3  3  5
+    1680    2  2  2  2  3  5  7
+    1701    3  3  3  3  3  7
+    1715    5  7  7  7
+    1728    2  2  2  2  2  2  3  3  3
+    1750    2  5  5  5  7
+    1764    2  2  3  3  7  7
+    1792    2  2  2  2  2  2  2  2  7
+    1800    2  2  2  3  3  5  5
+    1875    3  5  5  5  5
+    1890    2  3  3  3  5  7
+    1920    2  2  2  2  2  2  2  3  5
+    1944    2  2  2  3  3  3  3  3
+    1960    2  2  2  5  7  7
+    2000    2  2  2  2  5  5  5
+    2016    2  2  2  2  2  3  3  7
+    2025    3  3  3  3  5  5
+    2048    2  2  2  2  2  2  2  2  2  2  2
+    2058    2  3  7  7  7
+    2100    2  2  3  5  5  7
+    2160    2  2  2  2  3  3  3  5
+    2187    3  3  3  3  3  3  3
+    2205    3  3  5  7  7
+    2240    2  2  2  2  2  2  5  7
+    2250    2  3  3  5  5  5
+    2268    2  2  3  3  3  3  7
+    2304    2  2  2  2  2  2  2  2  3  3
+    2352    2  2  2  2  3  7  7
+    2400    2  2  2  2  2  3  5  5
+    2401    7  7  7  7
+    2430    2  3  3  3  3  3  5
+    2450    2  5  5  7  7
+    2500    2  2  5  5  5  5
+    2520    2  2  2  3  3  5  7
+    2560    2  2  2  2  2  2  2  2  2  5
+    2592    2  2  2  2  2  3  3  3  3
+    2625    3  5  5  5  7
+    2646    2  3  3  3  7  7
+    2688    2  2  2  2  2  2  2  3  7
+    2700    2  2  3  3  3  5  5
+    2744    2  2  2  7  7  7
+    2800    2  2  2  2  5  5  7
+    2835    3  3  3  3  5  7
+    2880    2  2  2  2  2  2  3  3  5
+    2916    2  2  3  3  3  3  3  3
+    2940    2  2  3  5  7  7
+    3000    2  2  2  3  5  5  5
+    3024    2  2  2  2  3  3  3  7
+    3072    2  2  2  2  2  2  2  2  2  2  3
+    3087    3  3  7  7  7
+    3125    5  5  5  5  5
+    3136    2  2  2  2  2  2  7  7
+    3150    2  3  3  5  5  7
+    3200    2  2  2  2  2  2  2  5  5
+    3240    2  2  2  3  3  3  3  5
+    3360    2  2  2  2  2  3  5  7
+    3375    3  3  3  5  5  5
+    3402    2  3  3  3  3  3  7
+    3430    2  5  7  7  7
+    3456    2  2  2  2  2  2  2  3  3  3
+    3500    2  2  5  5  5  7
+    3528    2  2  2  3  3  7  7
+    3584    2  2  2  2  2  2  2  2  2  7
+    3600    2  2  2  2  3  3  5  5
+    3645    3  3  3  3  3  3  5
+    3675    3  5  5  7  7
+    3750    2  3  5  5  5  5
+    3780    2  2  3  3  3  5  7
+    3840    2  2  2  2  2  2  2  2  3  5
+    3888    2  2  2  2  3  3  3  3  3
+    3920    2  2  2  2  5  7  7
+    3969    3  3  3  3  7  7
+    4000    2  2  2  2  2  5  5  5
+    4032    2  2  2  2  2  2  3  3  7
+    4050    2  3  3  3  3  5  5
+    4096    2  2  2  2  2  2  2  2  2  2  2  2
+    4116    2  2  3  7  7  7
+    4200    2  2  2  3  5  5  7
+    4320    2  2  2  2  2  3  3  3  5
+    4374    2  3  3  3  3  3  3  3
+    4375    5  5  5  5  7
+    4410    2  3  3  5  7  7
+    4480    2  2  2  2  2  2  2  5  7
+    4500    2  2  3  3  5  5  5
+    4536    2  2  2  3  3  3  3  7
+    4608    2  2  2  2  2  2  2  2  2  3  3
+    4704    2  2  2  2  2  3  7  7
+    4725    3  3  3  5  5  7
+    4800    2  2  2  2  2  2  3  5  5
+    4802    2  7  7  7  7
+    4860    2  2  3  3  3  3  3  5
+    4900    2  2  5  5  7  7
+    5000    2  2  2  5  5  5  5
+    5040    2  2  2  2  3  3  5  7
+    5103    3  3  3  3  3  3  7
+    5120    2  2  2  2  2  2  2  2  2  2  5
+    5145    3  5  7  7  7
+    5184    2  2  2  2  2  2  3  3  3  3
+    5250    2  3  5  5  5  7
+    5292    2  2  3  3  3  7  7
+    5376    2  2  2  2  2  2  2  2  3  7
+    5400    2  2  2  3  3  3  5  5
+    5488    2  2  2  2  7  7  7
+    5600    2  2  2  2  2  5  5  7
+    5625    3  3  5  5  5  5
+    5670    2  3  3  3  3  5  7
+    5760    2  2  2  2  2  2  2  3  3  5
+    5832    2  2  2  3  3  3  3  3  3
+    5880    2  2  2  3  5  7  7
+    6000    2  2  2  2  3  5  5  5
+    6048    2  2  2  2  2  3  3  3  7
+    6075    3  3  3  3  3  5  5
+    6125    5  5  5  7  7
+    6144    2  2  2  2  2  2  2  2  2  2  2  3
+    6174    2  3  3  7  7  7
+    6250    2  5  5  5  5  5
+    6272    2  2  2  2  2  2  2  7  7
+    6300    2  2  3  3  5  5  7
+    6400    2  2  2  2  2  2  2  2  5  5
+    6480    2  2  2  2  3  3  3  3  5
+    6561    3  3  3  3  3  3  3  3
+    6615    3  3  3  5  7  7
+    6720    2  2  2  2  2  2  3  5  7
+    6750    2  3  3  3  5  5  5
+    6804    2  2  3  3  3  3  3  7
+    6860    2  2  5  7  7  7
+    6912    2  2  2  2  2  2  2  2  3  3  3
+    7000    2  2  2  5  5  5  7
+    7056    2  2  2  2  3  3  7  7
+    7168    2  2  2  2  2  2  2  2  2  2  7
+    7200    2  2  2  2  2  3  3  5  5
+    7203    3  7  7  7  7
+    7290    2  3  3  3  3  3  3  5
+    7350    2  3  5  5  7  7
+    7500    2  2  3  5  5  5  5
+    7560    2  2  2  3  3  3  5  7
+    7680    2  2  2  2  2  2  2  2  2  3  5
+    7776    2  2  2  2  2  3  3  3  3  3
+    7840    2  2  2  2  2  5  7  7
+    7875    3  3  5  5  5  7
+    7938    2  3  3  3  3  7  7
+    8000    2  2  2  2  2  2  5  5  5
+    8064    2  2  2  2  2  2  2  3  3  7
+    8100    2  2  3  3  3  3  5  5
+    8192    2  2  2  2  2  2  2  2  2  2  2  2  2
+    8232    2  2  2  3  7  7  7
+    8400    2  2  2  2  3  5  5  7
+    8505    3  3  3  3  3  5  7
+    8575    5  5  7  7  7
+    8640    2  2  2  2  2  2  3  3  3  5
+    8748    2  2  3  3  3  3  3  3  3
+    8750    2  5  5  5  5  7
+    8820    2  2  3  3  5  7  7
+    8960    2  2  2  2  2  2  2  2  5  7
+    9000    2  2  2  3  3  5  5  5
+    9072    2  2  2  2  3  3  3  3  7
+    9216    2  2  2  2  2  2  2  2  2  2  3  3
+    9261    3  3  3  7  7  7
+    9375    3  5  5  5  5  5
+    9408    2  2  2  2  2  2  3  7  7
+    9450    2  3  3  3  5  5  7
+    9600    2  2  2  2  2  2  2  3  5  5
+    9604    2  2  7  7  7  7
+    9720    2  2  2  3  3  3  3  3  5
+    9800    2  2  2  5  5  7  7
+   10000    2  2  2  2  5  5  5  5
+   10080    2  2  2  2  2  3  3  5  7
+   10125    3  3  3  3  5  5  5
+   10206    2  3  3  3  3  3  3  7
+   10240    2  2  2  2  2  2  2  2  2  2  2  5
+   10290    2  3  5  7  7  7
+   10368    2  2  2  2  2  2  2  3  3  3  3
+   10500    2  2  3  5  5  5  7
+   10584    2  2  2  3  3  3  7  7
+   10752    2  2  2  2  2  2  2  2  2  3  7
+   10800    2  2  2  2  3  3  3  5  5
+   10935    3  3  3  3  3  3  3  5
+   10976    2  2  2  2  2  7  7  7
+   11025    3  3  5  5  7  7
+   11200    2  2  2  2  2  2  5  5  7
+   11250    2  3  3  5  5  5  5
+   11340    2  2  3  3  3  3  5  7
+   11520    2  2  2  2  2  2  2  2  3  3  5
+   11664    2  2  2  2  3  3  3  3  3  3
+   11760    2  2  2  2  3  5  7  7
+   11907    3  3  3  3  3  7  7
+   12000    2  2  2  2  2  3  5  5  5
+   12005    5  7  7  7  7
+   12096    2  2  2  2  2  2  3  3  3  7
+   12150    2  3  3  3  3  3  5  5
+   12250    2  5  5  5  7  7
+   12288    2  2  2  2  2  2  2  2  2  2  2  2  3
+   12348    2  2  3  3  7  7  7
+   12500    2  2  5  5  5  5  5
+   12544    2  2  2  2  2  2  2  2  7  7
+   12600    2  2  2  3  3  5  5  7
+   12800    2  2  2  2  2  2  2  2  2  5  5
+   12960    2  2  2  2  2  3  3  3  3  5
+   13122    2  3  3  3  3  3  3  3  3
+   13125    3  5  5  5  5  7
+   13230    2  3  3  3  5  7  7
+   13440    2  2  2  2  2  2  2  3  5  7
+   13500    2  2  3  3  3  5  5  5
+   13608    2  2  2  3  3  3  3  3  7
+   13720    2  2  2  5  7  7  7
+   13824    2  2  2  2  2  2  2  2  2  3  3  3
+   14000    2  2  2  2  5  5  5  7
+   14112    2  2  2  2  2  3  3  7  7
+   14175    3  3  3  3  5  5  7
+   14336    2  2  2  2  2  2  2  2  2  2  2  7
+   14400    2  2  2  2  2  2  3  3  5  5
+   14406    2  3  7  7  7  7
+   14580    2  2  3  3  3  3  3  3  5
+   14700    2  2  3  5  5  7  7
+   15000    2  2  2  3  5  5  5  5
+   15120    2  2  2  2  3  3  3  5  7
+   15309    3  3  3  3  3  3  3  7
+   15360    2  2  2  2  2  2  2  2  2  2  3  5
+   15435    3  3  5  7  7  7
+   15552    2  2  2  2  2  2  3  3  3  3  3
+   15625    5  5  5  5  5  5
+   15680    2  2  2  2  2  2  5  7  7
+   15750    2  3  3  5  5  5  7
+   15876    2  2  3  3  3  3  7  7
+   16000    2  2  2  2  2  2  2  5  5  5
+   16128    2  2  2  2  2  2  2  2  3  3  7
+   16200    2  2  2  3  3  3  3  5  5
+   16384    2  2  2  2  2  2  2  2  2  2  2  2  2  2
+   16464    2  2  2  2  3  7  7  7
+   16800    2  2  2  2  2  3  5  5  7
+   16807    7  7  7  7  7
+   16875    3  3  3  5  5  5  5
+   17010    2  3  3  3  3  3  5  7
+   17150    2  5  5  7  7  7
+   17280    2  2  2  2  2  2  2  3  3  3  5
+   17496    2  2  2  3  3  3  3  3  3  3
+   17500    2  2  5  5  5  5  7
+   17640    2  2  2  3  3  5  7  7
+   17920    2  2  2  2  2  2  2  2  2  5  7
+   18000    2  2  2  2  3  3  5  5  5
+   18144    2  2  2  2  2  3  3  3  3  7
+   18225    3  3  3  3  3  3  5  5
+   18375    3  5  5  5  7  7
+   18432    2  2  2  2  2  2  2  2  2  2  2  3  3
+   18522    2  3  3  3  7  7  7
+   18750    2  3  5  5  5  5  5
+   18816    2  2  2  2  2  2  2  3  7  7
+   18900    2  2  3  3  3  5  5  7
+   19200    2  2  2  2  2  2  2  2  3  5  5
+   19208    2  2  2  7  7  7  7
+   19440    2  2  2  2  3  3  3  3  3  5
+   19600    2  2  2  2  5  5  7  7
+   19683    3  3  3  3  3  3  3  3  3
+   19845    3  3  3  3  5  7  7
+   20000    2  2  2  2  2  5  5  5  5
+   20160    2  2  2  2  2  2  3  3  5  7
+   20250    2  3  3  3  3  5  5  5
+   20412    2  2  3  3  3  3  3  3  7
+   20480    2  2  2  2  2  2  2  2  2  2  2  2  5
+   20580    2  2  3  5  7  7  7
+   20736    2  2  2  2  2  2  2  2  3  3  3  3
+   21000    2  2  2  3  5  5  5  7
+   21168    2  2  2  2  3  3  3  7  7
+   21504    2  2  2  2  2  2  2  2  2  2  3  7
+   21600    2  2  2  2  2  3  3  3  5  5
+   21609    3  3  7  7  7  7
+   21870    2  3  3  3  3  3  3  3  5
+   21875    5  5  5  5  5  7
+   21952    2  2  2  2  2  2  7  7  7
+   22050    2  3  3  5  5  7  7
+   22400    2  2  2  2  2  2  2  5  5  7
+   22500    2  2  3  3  5  5  5  5
+   22680    2  2  2  3  3  3  3  5  7
+   23040    2  2  2  2  2  2  2  2  2  3  3  5
+   23328    2  2  2  2  2  3  3  3  3  3  3
+   23520    2  2  2  2  2  3  5  7  7
+   23625    3  3  3  5  5  5  7
+   23814    2  3  3  3  3  3  7  7
+   24000    2  2  2  2  2  2  3  5  5  5
+   24010    2  5  7  7  7  7
+   24192    2  2  2  2  2  2  2  3  3  3  7
+   24300    2  2  3  3  3  3  3  5  5
+   24500    2  2  5  5  5  7  7
+   24576    2  2  2  2  2  2  2  2  2  2  2  2  2  3
+   24696    2  2  2  3  3  7  7  7
+   25000    2  2  2  5  5  5  5  5
+   25088    2  2  2  2  2  2  2  2  2  7  7
+   25200    2  2  2  2  3  3  5  5  7
+   25515    3  3  3  3  3  3  5  7
+   25600    2  2  2  2  2  2  2  2  2  2  5  5
+   25725    3  5  5  7  7  7
+   25920    2  2  2  2  2  2  3  3  3  3  5
+   26244    2  2  3  3  3  3  3  3  3  3
+   26250    2  3  5  5  5  5  7
+   26460    2  2  3  3  3  5  7  7
+   26880    2  2  2  2  2  2  2  2  3  5  7
+   27000    2  2  2  3  3  3  5  5  5
+   27216    2  2  2  2  3  3  3  3  3  7
+   27440    2  2  2  2  5  7  7  7
+   27648    2  2  2  2  2  2  2  2  2  2  3  3  3
+   27783    3  3  3  3  7  7  7
+   28000    2  2  2  2  2  5  5  5  7
+   28125    3  3  5  5  5  5  5
+   28224    2  2  2  2  2  2  3  3  7  7
+   28350    2  3  3  3  3  5  5  7
+   28672    2  2  2  2  2  2  2  2  2  2  2  2  7
+   28800    2  2  2  2  2  2  2  3  3  5  5
+   28812    2  2  3  7  7  7  7
+   29160    2  2  2  3  3  3  3  3  3  5
+   29400    2  2  2  3  5  5  7  7
+   30000    2  2  2  2  3  5  5  5  5
+   30240    2  2  2  2  2  3  3  3  5  7
+   30375    3  3  3  3  3  5  5  5
+   30618    2  3  3  3  3  3  3  3  7
+   30625    5  5  5  5  7  7
+   30720    2  2  2  2  2  2  2  2  2  2  2  3  5
+   30870    2  3  3  5  7  7  7
+   31104    2  2  2  2  2  2  2  3  3  3  3  3
+   31250    2  5  5  5  5  5  5
+   31360    2  2  2  2  2  2  2  5  7  7
+   31500    2  2  3  3  5  5  5  7
+   31752    2  2  2  3  3  3  3  7  7
+   32000    2  2  2  2  2  2  2  2  5  5  5
+   32256    2  2  2  2  2  2  2  2  2  3  3  7
+   32400    2  2  2  2  3  3  3  3  5  5
+   32768    2  2  2  2  2  2  2  2  2  2  2  2  2  2  2
+   32805    3  3  3  3  3  3  3  3  5
+   32928    2  2  2  2  2  3  7  7  7
+   33075    3  3  3  5  5  7  7
+   33600    2  2  2  2  2  2  3  5  5  7
+   33614    2  7  7  7  7  7
+   33750    2  3  3  3  5  5  5  5
+   34020    2  2  3  3  3  3  3  5  7
+   34300    2  2  5  5  7  7  7
+   34560    2  2  2  2  2  2  2  2  3  3  3  5
+   34992    2  2  2  2  3  3  3  3  3  3  3
+   35000    2  2  2  5  5  5  5  7
+   35280    2  2  2  2  3  3  5  7  7
+   35721    3  3  3  3  3  3  7  7
+   35840    2  2  2  2  2  2  2  2  2  2  5  7
+   36000    2  2  2  2  2  3  3  5  5  5
+   36015    3  5  7  7  7  7
+   36288    2  2  2  2  2  2  3  3  3  3  7
+   36450    2  3  3  3  3  3  3  5  5
+   36750    2  3  5  5  5  7  7
+   36864    2  2  2  2  2  2  2  2  2  2  2  2  3  3
+   37044    2  2  3  3  3  7  7  7
+   37500    2  2  3  5  5  5  5  5
+   37632    2  2  2  2  2  2  2  2  3  7  7
+   37800    2  2  2  3  3  3  5  5  7
+   38400    2  2  2  2  2  2  2  2  2  3  5  5
+   38416    2  2  2  2  7  7  7  7
+   38880    2  2  2  2  2  3  3  3  3  3  5
+   39200    2  2  2  2  2  5  5  7  7
+   39366    2  3  3  3  3  3  3  3  3  3
+   39375    3  3  5  5  5  5  7
+   39690    2  3  3  3  3  5  7  7
+   40000    2  2  2  2  2  2  5  5  5  5
+   40320    2  2  2  2  2  2  2  3  3  5  7
+   40500    2  2  3  3  3  3  5  5  5
+   40824    2  2  2  3  3  3  3  3  3  7
+   40960    2  2  2  2  2  2  2  2  2  2  2  2  2  5
+   41160    2  2  2  3  5  7  7  7
+   41472    2  2  2  2  2  2  2  2  2  3  3  3  3
+   42000    2  2  2  2  3  5  5  5  7
+   42336    2  2  2  2  2  3  3  3  7  7
+   42525    3  3  3  3  3  5  5  7
+   42875    5  5  5  7  7  7
+   43008    2  2  2  2  2  2  2  2  2  2  2  3  7
+   43200    2  2  2  2  2  2  3  3  3  5  5
+   43218    2  3  3  7  7  7  7
+   43740    2  2  3  3  3  3  3  3  3  5
+   43750    2  5  5  5  5  5  7
+   43904    2  2  2  2  2  2  2  7  7  7
+   44100    2  2  3  3  5  5  7  7
+   44800    2  2  2  2  2  2  2  2  5  5  7
+   45000    2  2  2  3  3  5  5  5  5
+   45360    2  2  2  2  3  3  3  3  5  7
+   45927    3  3  3  3  3  3  3  3  7
+   46080    2  2  2  2  2  2  2  2  2  2  3  3  5
+   46305    3  3  3  5  7  7  7
+   46656    2  2  2  2  2  2  3  3  3  3  3  3
+   46875    3  5  5  5  5  5  5
+   47040    2  2  2  2  2  2  3  5  7  7
+   47250    2  3  3  3  5  5  5  7
+   47628    2  2  3  3  3  3  3  7  7
+   48000    2  2  2  2  2  2  2  3  5  5  5
+   48020    2  2  5  7  7  7  7
+   48384    2  2  2  2  2  2  2  2  3  3  3  7
+   48600    2  2  2  3  3  3  3  3  5  5
+   49000    2  2  2  5  5  5  7  7
+   49152    2  2  2  2  2  2  2  2  2  2  2  2  2  2  3
+   49392    2  2  2  2  3  3  7  7  7
+   50000    2  2  2  2  5  5  5  5  5
+   50176    2  2  2  2  2  2  2  2  2  2  7  7
+   50400    2  2  2  2  2  3  3  5  5  7
+   50421    3  7  7  7  7  7
+   50625    3  3  3  3  5  5  5  5
+   51030    2  3  3  3  3  3  3  5  7
+   51200    2  2  2  2  2  2  2  2  2  2  2  5  5
+   51450    2  3  5  5  7  7  7
+   51840    2  2  2  2  2  2  2  3  3  3  3  5
+   52488    2  2  2  3  3  3  3  3  3  3  3
+   52500    2  2  3  5  5  5  5  7
+   52920    2  2  2  3  3  3  5  7  7
+   53760    2  2  2  2  2  2  2  2  2  3  5  7
+   54000    2  2  2  2  3  3  3  5  5  5
+   54432    2  2  2  2  2  3  3  3  3  3  7
+   54675    3  3  3  3  3  3  3  5  5
+   54880    2  2  2  2  2  5  7  7  7
+   55125    3  3  5  5  5  7  7
+   55296    2  2  2  2  2  2  2  2  2  2  2  3  3  3
+   55566    2  3  3  3  3  7  7  7
+   56000    2  2  2  2  2  2  5  5  5  7
+   56250    2  3  3  5  5  5  5  5
+   56448    2  2  2  2  2  2  2  3  3  7  7
+   56700    2  2  3  3  3  3  5  5  7
+   57344    2  2  2  2  2  2  2  2  2  2  2  2  2  7
+   57600    2  2  2  2  2  2  2  2  3  3  5  5
+   57624    2  2  2  3  7  7  7  7
+   58320    2  2  2  2  3  3  3  3  3  3  5
+   58800    2  2  2  2  3  5  5  7  7
+   59049    3  3  3  3  3  3  3  3  3  3
+   59535    3  3  3  3  3  5  7  7
+   60000    2  2  2  2  2  3  5  5  5  5
+   60025    5  5  7  7  7  7
+   60480    2  2  2  2  2  2  3  3  3  5  7
+   60750    2  3  3  3  3  3  5  5  5
+   61236    2  2  3  3  3  3  3  3  3  7
+   61250    2  5  5  5  5  7  7
+   61440    2  2  2  2  2  2  2  2  2  2  2  2  3  5
+   61740    2  2  3  3  5  7  7  7
+   62208    2  2  2  2  2  2  2  2  3  3  3  3  3
+   62500    2  2  5  5  5  5  5  5
+   62720    2  2  2  2  2  2  2  2  5  7  7
+   63000    2  2  2  3  3  5  5  5  7
+   63504    2  2  2  2  3  3  3  3  7  7
+   64000    2  2  2  2  2  2  2  2  2  5  5  5
+   64512    2  2  2  2  2  2  2  2  2  2  3  3  7
+   64800    2  2  2  2  2  3  3  3  3  5  5
+   64827    3  3  3  7  7  7  7
+   65536    2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2
+   65610    2  3  3  3  3  3  3  3  3  5
+   65625    3  5  5  5  5  5  7
+   65856    2  2  2  2  2  2  3  7  7  7
+   66150    2  3  3  3  5  5  7  7
+   67200    2  2  2  2  2  2  2  3  5  5  7
+   67228    2  2  7  7  7  7  7
+   67500    2  2  3  3  3  5  5  5  5
+   68040    2  2  2  3  3  3  3  3  5  7
+   68600    2  2  2  5  5  7  7  7
+   69120    2  2  2  2  2  2  2  2  2  3  3  3  5
+   69984    2  2  2  2  2  3  3  3  3  3  3  3
+   70000    2  2  2  2  5  5  5  5  7
+   70560    2  2  2  2  2  3  3  5  7  7
+   70875    3  3  3  3  5  5  5  7
+   71442    2  3  3  3  3  3  3  7  7
+   71680    2  2  2  2  2  2  2  2  2  2  2  5  7
+   72000    2  2  2  2  2  2  3  3  5  5  5
+   72030    2  3  5  7  7  7  7
+   72576    2  2  2  2  2  2  2  3  3  3  3  7
+   72900    2  2  3  3  3  3  3  3  5  5
+   73500    2  2  3  5  5  5  7  7
+   73728    2  2  2  2  2  2  2  2  2  2  2  2  2  3  3
+   74088    2  2  2  3  3  3  7  7  7
+   75000    2  2  2  3  5  5  5  5  5
+   75264    2  2  2  2  2  2  2  2  2  3  7  7
+   75600    2  2  2  2  3  3  3  5  5  7
+   76545    3  3  3  3  3  3  3  5  7
+   76800    2  2  2  2  2  2  2  2  2  2  3  5  5
+   76832    2  2  2  2  2  7  7  7  7
+   77175    3  3  5  5  7  7  7
+   77760    2  2  2  2  2  2  3  3  3  3  3  5
+   78125    5  5  5  5  5  5  5
+   78400    2  2  2  2  2  2  5  5  7  7
+   78732    2  2  3  3  3  3  3  3  3  3  3
+   78750    2  3  3  5  5  5  5  7
+   79380    2  2  3  3  3  3  5  7  7
+   80000    2  2  2  2  2  2  2  5  5  5  5
+   80640    2  2  2  2  2  2  2  2  3  3  5  7
+   81000    2  2  2  3  3  3  3  5  5  5
+   81648    2  2  2  2  3  3  3  3  3  3  7
+   81920    2  2  2  2  2  2  2  2  2  2  2  2  2  2  5
+   82320    2  2  2  2  3  5  7  7  7
+   82944    2  2  2  2  2  2  2  2  2  2  3  3  3  3
+   83349    3  3  3  3  3  7  7  7
+   84000    2  2  2  2  2  3  5  5  5  7
+   84035    5  7  7  7  7  7
+   84375    3  3  3  5  5  5  5  5
+   84672    2  2  2  2  2  2  3  3  3  7  7
+   85050    2  3  3  3  3  3  5  5  7
+   85750    2  5  5  5  7  7  7
+   86016    2  2  2  2  2  2  2  2  2  2  2  2  3  7
+   86400    2  2  2  2  2  2  2  3  3  3  5  5
+   86436    2  2  3  3  7  7  7  7
+   87480    2  2  2  3  3  3  3  3  3  3  5
+   87500    2  2  5  5  5  5  5  7
+   87808    2  2  2  2  2  2  2  2  7  7  7
+   88200    2  2  2  3  3  5  5  7  7
+   89600    2  2  2  2  2  2  2  2  2  5  5  7
+   90000    2  2  2  2  3  3  5  5  5  5
+   90720    2  2  2  2  2  3  3  3  3  5  7
+   91125    3  3  3  3  3  3  5  5  5
+   91854    2  3  3  3  3  3  3  3  3  7
+   91875    3  5  5  5  5  7  7
+   92160    2  2  2  2  2  2  2  2  2  2  2  3  3  5
+   92610    2  3  3  3  5  7  7  7
+   93312    2  2  2  2  2  2  2  3  3  3  3  3  3
+   93750    2  3  5  5  5  5  5  5
+   94080    2  2  2  2  2  2  2  3  5  7  7
+   94500    2  2  3  3  3  5  5  5  7
+   95256    2  2  2  3  3  3  3  3  7  7
+   96000    2  2  2  2  2  2  2  2  3  5  5  5
+   96040    2  2  2  5  7  7  7  7
+   96768    2  2  2  2  2  2  2  2  2  3  3  3  7
+   97200    2  2  2  2  3  3  3  3  3  5  5
+   98000    2  2  2  2  5  5  5  7  7
+   98304    2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  3
+   98415    3  3  3  3  3  3  3  3  3  5
+   98784    2  2  2  2  2  3  3  7  7  7
+   99225    3  3  3  3  5  5  7  7
+  100000    2  2  2  2  2  5  5  5  5  5
+  100352    2  2  2  2  2  2  2  2  2  2  2  7  7
+  100800    2  2  2  2  2  2  3  3  5  5  7
+  100842    2  3  7  7  7  7  7
+  101250    2  3  3  3  3  5  5  5  5
+  102060    2  2  3  3  3  3  3  3  5  7
+  102400    2  2  2  2  2  2  2  2  2  2  2  2  5  5
+  102900    2  2  3  5  5  7  7  7
+  103680    2  2  2  2  2  2  2  2  3  3  3  3  5
+  104976    2  2  2  2  3  3  3  3  3  3  3  3
+  105000    2  2  2  3  5  5  5  5  7
+  105840    2  2  2  2  3  3  3  5  7  7
+  107163    3  3  3  3  3  3  3  7  7
+  107520    2  2  2  2  2  2  2  2  2  2  3  5  7
+  108000    2  2  2  2  2  3  3  3  5  5  5
+  108045    3  3  5  7  7  7  7
+  108864    2  2  2  2  2  2  3  3  3  3  3  7
+  109350    2  3  3  3  3  3  3  3  5  5
+  109375    5  5  5  5  5  5  7
+  109760    2  2  2  2  2  2  5  7  7  7
+  110250    2  3  3  5  5  5  7  7
+  110592    2  2  2  2  2  2  2  2  2  2  2  2  3  3  3
+  111132    2  2  3  3  3  3  7  7  7
+  112000    2  2  2  2  2  2  2  5  5  5  7
+  112500    2  2  3  3  5  5  5  5  5
+  112896    2  2  2  2  2  2  2  2  3  3  7  7
+  113400    2  2  2  3  3  3  3  5  5  7
+  114688    2  2  2  2  2  2  2  2  2  2  2  2  2  2  7
+  115200    2  2  2  2  2  2  2  2  2  3  3  5  5
+  115248    2  2  2  2  3  7  7  7  7
+  116640    2  2  2  2  2  3  3  3  3  3  3  5
+  117600    2  2  2  2  2  3  5  5  7  7
+  117649    7  7  7  7  7  7
+  118098    2  3  3  3  3  3  3  3  3  3  3
+  118125    3  3  3  5  5  5  5  7
+  119070    2  3  3  3  3  3  5  7  7
+  120000    2  2  2  2  2  2  3  5  5  5  5
+  120050    2  5  5  7  7  7  7
+  120960    2  2  2  2  2  2  2  3  3  3  5  7
+  121500    2  2  3  3  3  3  3  5  5  5
+  122472    2  2  2  3  3  3  3  3  3  3  7
+  122500    2  2  5  5  5  5  7  7
+  122880    2  2  2  2  2  2  2  2  2  2  2  2  2  3  5
+  123480    2  2  2  3  3  5  7  7  7
+  124416    2  2  2  2  2  2  2  2  2  3  3  3  3  3
+  125000    2  2  2  5  5  5  5  5  5
+  125440    2  2  2  2  2  2  2  2  2  5  7  7
+  126000    2  2  2  2  3  3  5  5  5  7
+  127008    2  2  2  2  2  3  3  3  3  7  7
+  127575    3  3  3  3  3  3  5  5  7
+  128000    2  2  2  2  2  2  2  2  2  2  5  5  5
+  128625    3  5  5  5  7  7  7
+  129024    2  2  2  2  2  2  2  2  2  2  2  3  3  7
+  129600    2  2  2  2  2  2  3  3  3  3  5  5
+  129654    2  3  3  3  7  7  7  7
+  131072    2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2
+  131220    2  2  3  3  3  3  3  3  3  3  5
+  131250    2  3  5  5  5  5  5  7
+  131712    2  2  2  2  2  2  2  3  7  7  7
+  132300    2  2  3  3  3  5  5  7  7
+  134400    2  2  2  2  2  2  2  2  3  5  5  7
+  134456    2  2  2  7  7  7  7  7
+  135000    2  2  2  3  3  3  5  5  5  5
+  136080    2  2  2  2  3  3  3  3  3  5  7
+  137200    2  2  2  2  5  5  7  7  7
+  137781    3  3  3  3  3  3  3  3  3  7
+  138240    2  2  2  2  2  2  2  2  2  2  3  3  3  5
+  138915    3  3  3  3  5  7  7  7
+  139968    2  2  2  2  2  2  3  3  3  3  3  3  3
+  140000    2  2  2  2  2  5  5  5  5  7
+  140625    3  3  5  5  5  5  5  5
+  141120    2  2  2  2  2  2  3  3  5  7  7
+  141750    2  3  3  3  3  5  5  5  7
+  142884    2  2  3  3  3  3  3  3  7  7
+  143360    2  2  2  2  2  2  2  2  2  2  2  2  5  7
+  144000    2  2  2  2  2  2  2  3  3  5  5  5
+  144060    2  2  3  5  7  7  7  7
+  145152    2  2  2  2  2  2  2  2  3  3  3  3  7
+  145800    2  2  2  3  3  3  3  3  3  5  5
+  147000    2  2  2  3  5  5  5  7  7
+  147456    2  2  2  2  2  2  2  2  2  2  2  2  2  2  3  3
+  148176    2  2  2  2  3  3  3  7  7  7
+  150000    2  2  2  2  3  5  5  5  5  5
+  150528    2  2  2  2  2  2  2  2  2  2  3  7  7
+  151200    2  2  2  2  2  3  3  3  5  5  7
+  151263    3  3  7  7  7  7  7
+  151875    3  3  3  3  3  5  5  5  5
+  153090    2  3  3  3  3  3  3  3  5  7
+  153125    5  5  5  5  5  7  7
+  153600    2  2  2  2  2  2  2  2  2  2  2  3  5  5
+  153664    2  2  2  2  2  2  7  7  7  7
+  154350    2  3  3  5  5  7  7  7
+  155520    2  2  2  2  2  2  2  3  3  3  3  3  5
+  156250    2  5  5  5  5  5  5  5
+  156800    2  2  2  2  2  2  2  5  5  7  7
+  157464    2  2  2  3  3  3  3  3  3  3  3  3
+  157500    2  2  3  3  5  5  5  5  7
+  158760    2  2  2  3  3  3  3  5  7  7
+  160000    2  2  2  2  2  2  2  2  5  5  5  5
+  161280    2  2  2  2  2  2  2  2  2  3  3  5  7
+  162000    2  2  2  2  3  3  3  3  5  5  5
+  163296    2  2  2  2  2  3  3  3  3  3  3  7
+  163840    2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  5
+  164025    3  3  3  3  3  3  3  3  5  5
+  164640    2  2  2  2  2  3  5  7  7  7
+  165375    3  3  3  5  5  5  7  7
+  165888    2  2  2  2  2  2  2  2  2  2  2  3  3  3  3
+  166698    2  3  3  3  3  3  7  7  7
+  168000    2  2  2  2  2  2  3  5  5  5  7
+  168070    2  5  7  7  7  7  7
+  168750    2  3  3  3  5  5  5  5  5
+  169344    2  2  2  2  2  2  2  3  3  3  7  7
+  170100    2  2  3  3  3  3  3  5  5  7
+  171500    2  2  5  5  5  7  7  7
+  172032    2  2  2  2  2  2  2  2  2  2  2  2  2  3  7
+  172800    2  2  2  2  2  2  2  2  3  3  3  5  5
+  172872    2  2  2  3  3  7  7  7  7
+  174960    2  2  2  2  3  3  3  3  3  3  3  5
+  175000    2  2  2  5  5  5  5  5  7
+  175616    2  2  2  2  2  2  2  2  2  7  7  7
+  176400    2  2  2  2  3  3  5  5  7  7
+  177147    3  3  3  3  3  3  3  3  3  3  3
+  178605    3  3  3  3  3  3  5  7  7
+  179200    2  2  2  2  2  2  2  2  2  2  5  5  7
+  180000    2  2  2  2  2  3  3  5  5  5  5
+  180075    3  5  5  7  7  7  7
+  181440    2  2  2  2  2  2  3  3  3  3  5  7
+  182250    2  3  3  3  3  3  3  5  5  5
+  183708    2  2  3  3  3  3  3  3  3  3  7
+  183750    2  3  5  5  5  5  7  7
+  184320    2  2  2  2  2  2  2  2  2  2  2  2  3  3  5
+  185220    2  2  3  3  3  5  7  7  7
+  186624    2  2  2  2  2  2  2  2  3  3  3  3  3  3
+  187500    2  2  3  5  5  5  5  5  5
+  188160    2  2  2  2  2  2  2  2  3  5  7  7
+  189000    2  2  2  3  3  3  5  5  5  7
+  190512    2  2  2  2  3  3  3  3  3  7  7
+  192000    2  2  2  2  2  2  2  2  2  3  5  5  5
+  192080    2  2  2  2  5  7  7  7  7
+  193536    2  2  2  2  2  2  2  2  2  2  3  3  3  7
+  194400    2  2  2  2  2  3  3  3  3  3  5  5
+  194481    3  3  3  3  7  7  7  7
+  196000    2  2  2  2  2  5  5  5  7  7
+  196608    2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  3
+  196830    2  3  3  3  3  3  3  3  3  3  5
+  196875    3  3  5  5  5  5  5  7
+  197568    2  2  2  2  2  2  3  3  7  7  7
+  198450    2  3  3  3  3  5  5  7  7
+  200000    2  2  2  2  2  2  5  5  5  5  5
+  200704    2  2  2  2  2  2  2  2  2  2  2  2  7  7
+  201600    2  2  2  2  2  2  2  3  3  5  5  7
+  201684    2  2  3  7  7  7  7  7
+  202500    2  2  3  3  3  3  5  5  5  5
+  204120    2  2  2  3  3  3  3  3  3  5  7
+  204800    2  2  2  2  2  2  2  2  2  2  2  2  2  5  5
+  205800    2  2  2  3  5  5  7  7  7
+  207360    2  2  2  2  2  2  2  2  2  3  3  3  3  5
+  209952    2  2  2  2  2  3  3  3  3  3  3  3  3
+  210000    2  2  2  2  3  5  5  5  5  7
+  211680    2  2  2  2  2  3  3  3  5  7  7
+  212625    3  3  3  3  3  5  5  5  7
+  214326    2  3  3  3  3  3  3  3  7  7
+  214375    5  5  5  5  7  7  7
+  215040    2  2  2  2  2  2  2  2  2  2  2  3  5  7
+  216000    2  2  2  2  2  2  3  3  3  5  5  5
+  216090    2  3  3  5  7  7  7  7
+  217728    2  2  2  2  2  2  2  3  3  3  3  3  7
+  218700    2  2  3  3  3  3  3  3  3  5  5
+  218750    2  5  5  5  5  5  5  7
+  219520    2  2  2  2  2  2  2  5  7  7  7
+  220500    2  2  3  3  5  5  5  7  7
+  221184    2  2  2  2  2  2  2  2  2  2  2  2  2  3  3  3
+  222264    2  2  2  3  3  3  3  7  7  7
+  224000    2  2  2  2  2  2  2  2  5  5  5  7
+  225000    2  2  2  3  3  5  5  5  5  5
+  225792    2  2  2  2  2  2  2  2  2  3  3  7  7
+  226800    2  2  2  2  3  3  3  3  5  5  7
+  229376    2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  7
+  229635    3  3  3  3  3  3  3  3  5  7
+  230400    2  2  2  2  2  2  2  2  2  2  3  3  5  5
+  230496    2  2  2  2  2  3  7  7  7  7
+  231525    3  3  3  5  5  7  7  7
+  233280    2  2  2  2  2  2  3  3  3  3  3  3  5
+  234375    3  5  5  5  5  5  5  5
+  235200    2  2  2  2  2  2  3  5  5  7  7
+  235298    2  7  7  7  7  7  7
+  236196    2  2  3  3  3  3  3  3  3  3  3  3
+  236250    2  3  3  3  5  5  5  5  7
+  238140    2  2  3  3  3  3  3  5  7  7
+  240000    2  2  2  2  2  2  2  3  5  5  5  5
+  240100    2  2  5  5  7  7  7  7
+  241920    2  2  2  2  2  2  2  2  3  3  3  5  7
+  243000    2  2  2  3  3  3  3  3  5  5  5
+  244944    2  2  2  2  3  3  3  3  3  3  3  7
+  245000    2  2  2  5  5  5  5  7  7
+  245760    2  2  2  2  2  2  2  2  2  2  2  2  2  2  3  5
+  246960    2  2  2  2  3  3  5  7  7  7
+  248832    2  2  2  2  2  2  2  2  2  2  3  3  3  3  3
+  250000    2  2  2  2  5  5  5  5  5  5
+  250047    3  3  3  3  3  3  7  7  7
+  250880    2  2  2  2  2  2  2  2  2  2  5  7  7
+  252000    2  2  2  2  2  3  3  5  5  5  7
+  252105    3  5  7  7  7  7  7
+  253125    3  3  3  3  5  5  5  5  5
+  254016    2  2  2  2  2  2  3  3  3  3  7  7
+  255150    2  3  3  3  3  3  3  5  5  7
+  256000    2  2  2  2  2  2  2  2  2  2  2  5  5  5
+  257250    2  3  5  5  5  7  7  7
+  258048    2  2  2  2  2  2  2  2  2  2  2  2  3  3  7
+  259200    2  2  2  2  2  2  2  3  3  3  3  5  5
+  259308    2  2  3  3  3  7  7  7  7
+  262144    2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2
+  262440    2  2  2  3  3  3  3  3  3  3  3  5
+  262500    2  2  3  5  5  5  5  5  7
+  263424    2  2  2  2  2  2  2  2  3  7  7  7
+  264600    2  2  2  3  3  3  5  5  7  7
+  268800    2  2  2  2  2  2  2  2  2  3  5  5  7
+  268912    2  2  2  2  7  7  7  7  7
+  270000    2  2  2  2  3  3  3  5  5  5  5
+  272160    2  2  2  2  2  3  3  3  3  3  5  7
+  273375    3  3  3  3  3  3  3  5  5  5
+  274400    2  2  2  2  2  5  5  7  7  7
+  275562    2  3  3  3  3  3  3  3  3  3  7
+  275625    3  3  5  5  5  5  7  7
+  276480    2  2  2  2  2  2  2  2  2  2  2  3  3  3  5
+  277830    2  3  3  3  3  5  7  7  7
+  279936    2  2  2  2  2  2  2  3  3  3  3  3  3  3
+  280000    2  2  2  2  2  2  5  5  5  5  7
+  281250    2  3  3  5  5  5  5  5  5
+  282240    2  2  2  2  2  2  2  3  3  5  7  7
+  283500    2  2  3  3  3  3  5  5  5  7
+  285768    2  2  2  3  3  3  3  3  3  7  7
+  286720    2  2  2  2  2  2  2  2  2  2  2  2  2  5  7
+  288000    2  2  2  2  2  2  2  2  3  3  5  5  5
+  288120    2  2  2  3  5  7  7  7  7
+  290304    2  2  2  2  2  2  2  2  2  3  3  3  3  7
+  291600    2  2  2  2  3  3  3  3  3  3  5  5
+  294000    2  2  2  2  3  5  5  5  7  7
+  294912    2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  3  3
+  295245    3  3  3  3  3  3  3  3  3  3  5
+  296352    2  2  2  2  2  3  3  3  7  7  7
+  297675    3  3  3  3  3  5  5  7  7
+  300000    2  2  2  2  2  3  5  5  5  5  5
+  300125    5  5  5  7  7  7  7
+  301056    2  2  2  2  2  2  2  2  2  2  2  3  7  7
+  302400    2  2  2  2  2  2  3  3  3  5  5  7
+  302526    2  3  3  7  7  7  7  7
+  303750    2  3  3  3  3  3  5  5  5  5
+  306180    2  2  3  3  3  3  3  3  3  5  7
+  306250    2  5  5  5  5  5  7  7
+  307200    2  2  2  2  2  2  2  2  2  2  2  2  3  5  5
+  307328    2  2  2  2  2  2  2  7  7  7  7
+  308700    2  2  3  3  5  5  7  7  7
+  311040    2  2  2  2  2  2  2  2  3  3  3  3  3  5
+  312500    2  2  5  5  5  5  5  5  5
+  313600    2  2  2  2  2  2  2  2  5  5  7  7
+  314928    2  2  2  2  3  3  3  3  3  3  3  3  3
+  315000    2  2  2  3  3  5  5  5  5  7
+  317520    2  2  2  2  3  3  3  3  5  7  7
+  320000    2  2  2  2  2  2  2  2  2  5  5  5  5
+  321489    3  3  3  3  3  3  3  3  7  7
+  322560    2  2  2  2  2  2  2  2  2  2  3  3  5  7
+  324000    2  2  2  2  2  3  3  3  3  5  5  5
+  324135    3  3  3  5  7  7  7  7
+  326592    2  2  2  2  2  2  3  3  3  3  3  3  7
+  327680    2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  5
+  328050    2  3  3  3  3  3  3  3  3  5  5
+  328125    3  5  5  5  5  5  5  7
+  329280    2  2  2  2  2  2  3  5  7  7  7
+  330750    2  3  3  3  5  5  5  7  7
+  331776    2  2  2  2  2  2  2  2  2  2  2  2  3  3  3  3
+  333396    2  2  3  3  3  3  3  7  7  7
+  336000    2  2  2  2  2  2  2  3  5  5  5  7
+  336140    2  2  5  7  7  7  7  7
+  337500    2  2  3  3  3  5  5  5  5  5
+  338688    2  2  2  2  2  2  2  2  3  3  3  7  7
+  340200    2  2  2  3  3  3  3  3  5  5  7
+  343000    2  2  2  5  5  5  7  7  7
+  344064    2  2  2  2  2  2  2  2  2  2  2  2  2  2  3  7
+  345600    2  2  2  2  2  2  2  2  2  3  3  3  5  5
+  345744    2  2  2  2  3  3  7  7  7  7
+  349920    2  2  2  2  2  3  3  3  3  3  3  3  5
+  350000    2  2  2  2  5  5  5  5  5  7
+  351232    2  2  2  2  2  2  2  2  2  2  7  7  7
+  352800    2  2  2  2  2  3  3  5  5  7  7
+  352947    3  7  7  7  7  7  7
+  354294    2  3  3  3  3  3  3  3  3  3  3  3
+  354375    3  3  3  3  5  5  5  5  7
+  357210    2  3  3  3  3  3  3  5  7  7
+  358400    2  2  2  2  2  2  2  2  2  2  2  5  5  7
+  360000    2  2  2  2  2  2  3  3  5  5  5  5
+  360150    2  3  5  5  7  7  7  7
+  362880    2  2  2  2  2  2  2  3  3  3  3  5  7
+  364500    2  2  3  3  3  3  3  3  5  5  5
+  367416    2  2  2  3  3  3  3  3  3  3  3  7
+  367500    2  2  3  5  5  5  5  7  7
+  368640    2  2  2  2  2  2  2  2  2  2  2  2  2  3  3  5
+  370440    2  2  2  3  3  3  5  7  7  7
+  373248    2  2  2  2  2  2  2  2  2  3  3  3  3  3  3
+  375000    2  2  2  3  5  5  5  5  5  5
+  376320    2  2  2  2  2  2  2  2  2  3  5  7  7
+  378000    2  2  2  2  3  3  3  5  5  5  7
+  381024    2  2  2  2  2  3  3  3  3  3  7  7
+  382725    3  3  3  3  3  3  3  5  5  7
+  384000    2  2  2  2  2  2  2  2  2  2  3  5  5  5
+  384160    2  2  2  2  2  5  7  7  7  7
+  385875    3  3  5  5  5  7  7  7
+  387072    2  2  2  2  2  2  2  2  2  2  2  3  3  3  7
+  388800    2  2  2  2  2  2  3  3  3  3  3  5  5
+  388962    2  3  3  3  3  7  7  7  7
+  390625    5  5  5  5  5  5  5  5
+  392000    2  2  2  2  2  2  5  5  5  7  7
+  393216    2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  3
+  393660    2  2  3  3  3  3  3  3  3  3  3  5
+  393750    2  3  3  5  5  5  5  5  7
+  395136    2  2  2  2  2  2  2  3  3  7  7  7
+  396900    2  2  3  3  3  3  5  5  7  7
+  400000    2  2  2  2  2  2  2  5  5  5  5  5
+  401408    2  2  2  2  2  2  2  2  2  2  2  2  2  7  7
+  403200    2  2  2  2  2  2  2  2  3  3  5  5  7
+  403368    2  2  2  3  7  7  7  7  7
+  405000    2  2  2  3  3  3  3  5  5  5  5
+  408240    2  2  2  2  3  3  3  3  3  3  5  7
+  409600    2  2  2  2  2  2  2  2  2  2  2  2  2  2  5  5
+  411600    2  2  2  2  3  5  5  7  7  7
+  413343    3  3  3  3  3  3  3  3  3  3  7
+  414720    2  2  2  2  2  2  2  2  2  2  3  3  3  3  5
+  416745    3  3  3  3  3  5  7  7  7
+  419904    2  2  2  2  2  2  3  3  3  3  3  3  3  3
+  420000    2  2  2  2  2  3  5  5  5  5  7
+  420175    5  5  7  7  7  7  7
+  421875    3  3  3  5  5  5  5  5  5
+  423360    2  2  2  2  2  2  3  3  3  5  7  7
+  425250    2  3  3  3  3  3  5  5  5  7
+  428652    2  2  3  3  3  3  3  3  3  7  7
+  428750    2  5  5  5  5  7  7  7
+  430080    2  2  2  2  2  2  2  2  2  2  2  2  3  5  7
+  432000    2  2  2  2  2  2  2  3  3  3  5  5  5
+  432180    2  2  3  3  5  7  7  7  7
+  435456    2  2  2  2  2  2  2  2  3  3  3  3  3  7
+  437400    2  2  2  3  3  3  3  3  3  3  5  5
+  437500    2  2  5  5  5  5  5  5  7
+  439040    2  2  2  2  2  2  2  2  5  7  7  7
+  441000    2  2  2  3  3  5  5  5  7  7
+  442368    2  2  2  2  2  2  2  2  2  2  2  2  2  2  3  3  3
+  444528    2  2  2  2  3  3  3  3  7  7  7
+  448000    2  2  2  2  2  2  2  2  2  5  5  5  7
+  450000    2  2  2  2  3  3  5  5  5  5  5
+  451584    2  2  2  2  2  2  2  2  2  2  3  3  7  7
+  453600    2  2  2  2  2  3  3  3  3  5  5  7
+  453789    3  3  3  7  7  7  7  7
+  455625    3  3  3  3  3  3  5  5  5  5
+  458752    2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  7
+  459270    2  3  3  3  3  3  3  3  3  5  7
+  459375    3  5  5  5  5  5  7  7
+  460800    2  2  2  2  2  2  2  2  2  2  2  3  3  5  5
+  460992    2  2  2  2  2  2  3  7  7  7  7
+  463050    2  3  3  3  5  5  7  7  7
+  466560    2  2  2  2  2  2  2  3  3  3  3  3  3  5
+  468750    2  3  5  5  5  5  5  5  5
+  470400    2  2  2  2  2  2  2  3  5  5  7  7
+  470596    2  2  7  7  7  7  7  7
+  472392    2  2  2  3  3  3  3  3  3  3  3  3  3
+  472500    2  2  3  3  3  5  5  5  5  7
+  476280    2  2  2  3  3  3  3  3  5  7  7
+  480000    2  2  2  2  2  2  2  2  3  5  5  5  5
+  480200    2  2  2  5  5  7  7  7  7
+  483840    2  2  2  2  2  2  2  2  2  3  3  3  5  7
+  486000    2  2  2  2  3  3  3  3  3  5  5  5
+  489888    2  2  2  2  2  3  3  3  3  3  3  3  7
+  490000    2  2  2  2  5  5  5  5  7  7
+  491520    2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  3  5
+  492075    3  3  3  3  3  3  3  3  3  5  5
+  493920    2  2  2  2  2  3  3  5  7  7  7
+  496125    3  3  3  3  5  5  5  7  7
+  497664    2  2  2  2  2  2  2  2  2  2  2  3  3  3  3  3
+  500000    2  2  2  2  2  5  5  5  5  5  5
+  500094    2  3  3  3  3  3  3  7  7  7
+  501760    2  2  2  2  2  2  2  2  2  2  2  5  7  7
+  504000    2  2  2  2  2  2  3  3  5  5  5  7
+  504210    2  3  5  7  7  7  7  7
+  506250    2  3  3  3  3  5  5  5  5  5
+  508032    2  2  2  2  2  2  2  3  3  3  3  7  7
+  510300    2  2  3  3  3  3  3  3  5  5  7
+  512000    2  2  2  2  2  2  2  2  2  2  2  2  5  5  5
+  514500    2  2  3  5  5  5  7  7  7
+  516096    2  2  2  2  2  2  2  2  2  2  2  2  2  3  3  7
+  518400    2  2  2  2  2  2  2  2  3  3  3  3  5  5
+  518616    2  2  2  3  3  3  7  7  7  7
+  524288    2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2
+  524880    2  2  2  2  3  3  3  3  3  3  3  3  5
+  525000    2  2  2  3  5  5  5  5  5  7
+  526848    2  2  2  2  2  2  2  2  2  3  7  7  7
+  529200    2  2  2  2  3  3  3  5  5  7  7
+  531441    3  3  3  3  3  3  3  3  3  3  3  3
+  535815    3  3  3  3  3  3  3  5  7  7
+  537600    2  2  2  2  2  2  2  2  2  2  3  5  5  7
+  537824    2  2  2  2  2  7  7  7  7  7
+  540000    2  2  2  2  2  3  3  3  5  5  5  5
+  540225    3  3  5  5  7  7  7  7
+  544320    2  2  2  2  2  2  3  3  3  3  3  5  7
+  546750    2  3  3  3  3  3  3  3  5  5  5
+  546875    5  5  5  5  5  5  5  7
+  548800    2  2  2  2  2  2  5  5  7  7  7
+  551124    2  2  3  3  3  3  3  3  3  3  3  7
+  551250    2  3  3  5  5  5  5  7  7
+  552960    2  2  2  2  2  2  2  2  2  2  2  2  3  3  3  5
+  555660    2  2  3  3  3  3  5  7  7  7
+  559872    2  2  2  2  2  2  2  2  3  3  3  3  3  3  3
+  560000    2  2  2  2  2  2  2  5  5  5  5  7
+  562500    2  2  3  3  5  5  5  5  5  5
+  564480    2  2  2  2  2  2  2  2  3  3  5  7  7
+  567000    2  2  2  3  3  3  3  5  5  5  7
+  571536    2  2  2  2  3  3  3  3  3  3  7  7
+  573440    2  2  2  2  2  2  2  2  2  2  2  2  2  2  5  7
+  576000    2  2  2  2  2  2  2  2  2  3  3  5  5  5
+  576240    2  2  2  2  3  5  7  7  7  7
+  580608    2  2  2  2  2  2  2  2  2  2  3  3  3  3  7
+  583200    2  2  2  2  2  3  3  3  3  3  3  5  5
+  583443    3  3  3  3  3  7  7  7  7
+  588000    2  2  2  2  2  3  5  5  5  7  7
+  588245    5  7  7  7  7  7  7
+  589824    2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  3  3
+  590490    2  3  3  3  3  3  3  3  3  3  3  5
+  590625    3  3  3  5  5  5  5  5  7
+  592704    2  2  2  2  2  2  3  3  3  7  7  7
+  595350    2  3  3  3  3  3  5  5  7  7
+  600000    2  2  2  2  2  2  3  5  5  5  5  5
+  600250    2  5  5  5  7  7  7  7
+  602112    2  2  2  2  2  2  2  2  2  2  2  2  3  7  7
+  604800    2  2  2  2  2  2  2  3  3  3  5  5  7
+  605052    2  2  3  3  7  7  7  7  7
+  607500    2  2  3  3  3  3  3  5  5  5  5
+  612360    2  2  2  3  3  3  3  3  3  3  5  7
+  612500    2  2  5  5  5  5  5  7  7
+  614400    2  2  2  2  2  2  2  2  2  2  2  2  2  3  5  5
+  614656    2  2  2  2  2  2  2  2  7  7  7  7
+  617400    2  2  2  3  3  5  5  7  7  7
+  622080    2  2  2  2  2  2  2  2  2  3  3  3  3  3  5
+  625000    2  2  2  5  5  5  5  5  5  5
+  627200    2  2  2  2  2  2  2  2  2  5  5  7  7
+  629856    2  2  2  2  2  3  3  3  3  3  3  3  3  3
+  630000    2  2  2  2  3  3  5  5  5  5  7
+  635040    2  2  2  2  2  3  3  3  3  5  7  7
+  637875    3  3  3  3  3  3  5  5  5  7
+  640000    2  2  2  2  2  2  2  2  2  2  5  5  5  5
+  642978    2  3  3  3  3  3  3  3  3  7  7
+  643125    3  5  5  5  5  7  7  7
+  645120    2  2  2  2  2  2  2  2  2  2  2  3  3  5  7
+  648000    2  2  2  2  2  2  3  3  3  3  5  5  5
+  648270    2  3  3  3  5  7  7  7  7
+  653184    2  2  2  2  2  2  2  3  3  3  3  3  3  7
+  655360    2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  5
+  656100    2  2  3  3  3  3  3  3  3  3  5  5
+  656250    2  3  5  5  5  5  5  5  7
+  658560    2  2  2  2  2  2  2  3  5  7  7  7
+  661500    2  2  3  3  3  5  5  5  7  7
+  663552    2  2  2  2  2  2  2  2  2  2  2  2  2  3  3  3  3
+  666792    2  2  2  3  3  3  3  3  7  7  7
+  672000    2  2  2  2  2  2  2  2  3  5  5  5  7
+  672280    2  2  2  5  7  7  7  7  7
+  675000    2  2  2  3  3  3  5  5  5  5  5
+  677376    2  2  2  2  2  2  2  2  2  3  3  3  7  7
+  680400    2  2  2  2  3  3  3  3  3  5  5  7
+  686000    2  2  2  2  5  5  5  7  7  7
+  688128    2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  3  7
+  688905    3  3  3  3  3  3  3  3  3  5  7
+  691200    2  2  2  2  2  2  2  2  2  2  3  3  3  5  5
+  691488    2  2  2  2  2  3  3  7  7  7  7
+  694575    3  3  3  3  5  5  7  7  7
+  699840    2  2  2  2  2  2  3  3  3  3  3  3  3  5
+  700000    2  2  2  2  2  5  5  5  5  5  7
+  702464    2  2  2  2  2  2  2  2  2  2  2  7  7  7
+  703125    3  3  5  5  5  5  5  5  5
+  705600    2  2  2  2  2  2  3  3  5  5  7  7
+  705894    2  3  7  7  7  7  7  7
+  708588    2  2  3  3  3  3  3  3  3  3  3  3  3
+  708750    2  3  3  3  3  5  5  5  5  7
+  714420    2  2  3  3  3  3  3  3  5  7  7
+  716800    2  2  2  2  2  2  2  2  2  2  2  2  5  5  7
+  720000    2  2  2  2  2  2  2  3  3  5  5  5  5
+  720300    2  2  3  5  5  7  7  7  7
+  725760    2  2  2  2  2  2  2  2  3  3  3  3  5  7
+  729000    2  2  2  3  3  3  3  3  3  5  5  5
+  734832    2  2  2  2  3  3  3  3  3  3  3  3  7
+  735000    2  2  2  3  5  5  5  5  7  7
+  737280    2  2  2  2  2  2  2  2  2  2  2  2  2  2  3  3  5
+  740880    2  2  2  2  3  3  3  5  7  7  7
+  746496    2  2  2  2  2  2  2  2  2  2  3  3  3  3  3  3
+  750000    2  2  2  2  3  5  5  5  5  5  5
+  750141    3  3  3  3  3  3  3  7  7  7
+  752640    2  2  2  2  2  2  2  2  2  2  3  5  7  7
+  756000    2  2  2  2  2  3  3  3  5  5  5  7
+  756315    3  3  5  7  7  7  7  7
+  759375    3  3  3  3  3  5  5  5  5  5
+  762048    2  2  2  2  2  2  3  3  3  3  3  7  7
+  765450    2  3  3  3  3  3  3  3  5  5  7
+  765625    5  5  5  5  5  5  7  7
+  768000    2  2  2  2  2  2  2  2  2  2  2  3  5  5  5
+  768320    2  2  2  2  2  2  5  7  7  7  7
+  771750    2  3  3  5  5  5  7  7  7
+  774144    2  2  2  2  2  2  2  2  2  2  2  2  3  3  3  7
+  777600    2  2  2  2  2  2  2  3  3  3  3  3  5  5
+  777924    2  2  3  3  3  3  7  7  7  7
+  781250    2  5  5  5  5  5  5  5  5
+  784000    2  2  2  2  2  2  2  5  5  5  7  7
+  786432    2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  3
+  787320    2  2  2  3  3  3  3  3  3  3  3  3  5
+  787500    2  2  3  3  5  5  5  5  5  7
+  790272    2  2  2  2  2  2  2  2  3  3  7  7  7
+  793800    2  2  2  3  3  3  3  5  5  7  7
+  800000    2  2  2  2  2  2  2  2  5  5  5  5  5
+  802816    2  2  2  2  2  2  2  2  2  2  2  2  2  2  7  7
+  806400    2  2  2  2  2  2  2  2  2  3  3  5  5  7
+  806736    2  2  2  2  3  7  7  7  7  7
+  810000    2  2  2  2  3  3  3  3  5  5  5  5
+  816480    2  2  2  2  2  3  3  3  3  3  3  5  7
+  819200    2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  5  5
+  820125    3  3  3  3  3  3  3  3  5  5  5
+  823200    2  2  2  2  2  3  5  5  7  7  7
+  823543    7  7  7  7  7  7  7
+  826686    2  3  3  3  3  3  3  3  3  3  3  7
+  826875    3  3  3  5  5  5  5  7  7
+  829440    2  2  2  2  2  2  2  2  2  2  2  3  3  3  3  5
+  833490    2  3  3  3  3  3  5  7  7  7
+  839808    2  2  2  2  2  2  2  3  3  3  3  3  3  3  3
+  840000    2  2  2  2  2  2  3  5  5  5  5  7
+  840350    2  5  5  7  7  7  7  7
+  843750    2  3  3  3  5  5  5  5  5  5
+  846720    2  2  2  2  2  2  2  3  3  3  5  7  7
+  850500    2  2  3  3  3  3  3  5  5  5  7
+  857304    2  2  2  3  3  3  3  3  3  3  7  7
+  857500    2  2  5  5  5  5  7  7  7
+  860160    2  2  2  2  2  2  2  2  2  2  2  2  2  3  5  7
+  864000    2  2  2  2  2  2  2  2  3  3  3  5  5  5
+  864360    2  2  2  3  3  5  7  7  7  7
+  870912    2  2  2  2  2  2  2  2  2  3  3  3  3  3  7
+  874800    2  2  2  2  3  3  3  3  3  3  3  5  5
+  875000    2  2  2  5  5  5  5  5  5  7
+  878080    2  2  2  2  2  2  2  2  2  5  7  7  7
+  882000    2  2  2  2  3  3  5  5  5  7  7
+  884736    2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  3  3  3
+  885735    3  3  3  3  3  3  3  3  3  3  3  5
+  889056    2  2  2  2  2  3  3  3  3  7  7  7
+  893025    3  3  3  3  3  3  5  5  7  7
+  896000    2  2  2  2  2  2  2  2  2  2  5  5  5  7
+  900000    2  2  2  2  2  3  3  5  5  5  5  5
+  900375    3  5  5  5  7  7  7  7
+  903168    2  2  2  2  2  2  2  2  2  2  2  3  3  7  7
+  907200    2  2  2  2  2  2  3  3  3  3  5  5  7
+  907578    2  3  3  3  7  7  7  7  7
+  911250    2  3  3  3  3  3  3  5  5  5  5
+  917504    2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  7
+  918540    2  2  3  3  3  3  3  3  3  3  5  7
+  918750    2  3  5  5  5  5  5  7  7
+  921600    2  2  2  2  2  2  2  2  2  2  2  2  3  3  5  5
+  921984    2  2  2  2  2  2  2  3  7  7  7  7
+  926100    2  2  3  3  3  5  5  7  7  7
+  933120    2  2  2  2  2  2  2  2  3  3  3  3  3  3  5
+  937500    2  2  3  5  5  5  5  5  5  5
+  940800    2  2  2  2  2  2  2  2  3  5  5  7  7
+  941192    2  2  2  7  7  7  7  7  7
+  944784    2  2  2  2  3  3  3  3  3  3  3  3  3  3
+  945000    2  2  2  3  3  3  5  5  5  5  7
+  952560    2  2  2  2  3  3  3  3  3  5  7  7
+  960000    2  2  2  2  2  2  2  2  2  3  5  5  5  5
+  960400    2  2  2  2  5  5  7  7  7  7
+  964467    3  3  3  3  3  3  3  3  3  7  7
+  967680    2  2  2  2  2  2  2  2  2  2  3  3  3  5  7
+  972000    2  2  2  2  2  3  3  3  3  3  5  5  5
+  972405    3  3  3  3  5  7  7  7  7
+  979776    2  2  2  2  2  2  3  3  3  3  3  3  3  7
+  980000    2  2  2  2  2  5  5  5  5  7  7
+  983040    2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  3  5
+  984150    2  3  3  3  3  3  3  3  3  3  5  5
+  984375    3  3  5  5  5  5  5  5  7
+  987840    2  2  2  2  2  2  3  3  5  7  7  7
+  992250    2  3  3  3  3  5  5  5  7  7
+  995328    2  2  2  2  2  2  2  2  2  2  2  2  3  3  3  3  3
+ 1000000    2  2  2  2  2  2  5  5  5  5  5  5
+ 1000188    2  2  3  3  3  3  3  3  7  7  7
+ 1003520    2  2  2  2  2  2  2  2  2  2  2  2  5  7  7
+ 1008000    2  2  2  2  2  2  2  3  3  5  5  5  7
+ 1008420    2  2  3  5  7  7  7  7  7
+ 1012500    2  2  3  3  3  3  5  5  5  5  5
+ 1016064    2  2  2  2  2  2  2  2  3  3  3  3  7  7
+ 1020600    2  2  2  3  3  3  3  3  3  5  5  7
+ 1024000    2  2  2  2  2  2  2  2  2  2  2  2  2  5  5  5
+ 1029000    2  2  2  3  5  5  5  7  7  7
+ 1032192    2  2  2  2  2  2  2  2  2  2  2  2  2  2  3  3  7
+ 1036800    2  2  2  2  2  2  2  2  2  3  3  3  3  5  5
+ 1037232    2  2  2  2  3  3  3  7  7  7  7
+ 1048576    2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2
+ 1049760    2  2  2  2  2  3  3  3  3  3  3  3  3  5
+ 1050000    2  2  2  2  3  5  5  5  5  5  7
+ 1053696    2  2  2  2  2  2  2  2  2  2  3  7  7  7
+ 1058400    2  2  2  2  2  3  3  3  5  5  7  7
+ 1058841    3  3  7  7  7  7  7  7
+ 1062882    2  3  3  3  3  3  3  3  3  3  3  3  3
+ 1063125    3  3  3  3  3  5  5  5  5  7
+ 1071630    2  3  3  3  3  3  3  3  5  7  7
+ 1071875    5  5  5  5  5  7  7  7
+ 1075200    2  2  2  2  2  2  2  2  2  2  2  3  5  5  7
+ 1075648    2  2  2  2  2  2  7  7  7  7  7
+ 1080000    2  2  2  2  2  2  3  3  3  5  5  5  5
+ 1080450    2  3  3  5  5  7  7  7  7
+ 1088640    2  2  2  2  2  2  2  3  3  3  3  3  5  7
+ 1093500    2  2  3  3  3  3  3  3  3  5  5  5
+ 1093750    2  5  5  5  5  5  5  5  7
+ 1097600    2  2  2  2  2  2  2  5  5  7  7  7
+ 1102248    2  2  2  3  3  3  3  3  3  3  3  3  7
+ 1102500    2  2  3  3  5  5  5  5  7  7
+ 1105920    2  2  2  2  2  2  2  2  2  2  2  2  2  3  3  3  5
+ 1111320    2  2  2  3  3  3  3  5  7  7  7
+ 1119744    2  2  2  2  2  2  2  2  2  3  3  3  3  3  3  3
+ 1120000    2  2  2  2  2  2  2  2  5  5  5  5  7
+ 1125000    2  2  2  3  3  5  5  5  5  5  5
+ 1128960    2  2  2  2  2  2  2  2  2  3  3  5  7  7
+ 1134000    2  2  2  2  3  3  3  3  5  5  5  7
+ 1143072    2  2  2  2  2  3  3  3  3  3  3  7  7
+ 1146880    2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  5  7
+ 1148175    3  3  3  3  3  3  3  3  5  5  7
+ 1152000    2  2  2  2  2  2  2  2  2  2  3  3  5  5  5
+ 1152480    2  2  2  2  2  3  5  7  7  7  7
+ 1157625    3  3  3  5  5  5  7  7  7
+ 1161216    2  2  2  2  2  2  2  2  2  2  2  3  3  3  3  7
+ 1166400    2  2  2  2  2  2  3  3  3  3  3  3  5  5
+ 1166886    2  3  3  3  3  3  7  7  7  7
+ 1171875    3  5  5  5  5  5  5  5  5
+ 1176000    2  2  2  2  2  2  3  5  5  5  7  7
+ 1176490    2  5  7  7  7  7  7  7
+ 1179648    2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  3  3
+ 1180980    2  2  3  3  3  3  3  3  3  3  3  3  5
+ 1181250    2  3  3  3  5  5  5  5  5  7
+ 1185408    2  2  2  2  2  2  2  3  3  3  7  7  7
+ 1190700    2  2  3  3  3  3  3  5  5  7  7
+ 1200000    2  2  2  2  2  2  2  3  5  5  5  5  5
+ 1200500    2  2  5  5  5  7  7  7  7
+ 1204224    2  2  2  2  2  2  2  2  2  2  2  2  2  3  7  7
+ 1209600    2  2  2  2  2  2  2  2  3  3  3  5  5  7
+ 1210104    2  2  2  3  3  7  7  7  7  7
+ 1215000    2  2  2  3  3  3  3  3  5  5  5  5
+ 1224720    2  2  2  2  3  3  3  3  3  3  3  5  7
+ 1225000    2  2  2  5  5  5  5  5  7  7
+ 1228800    2  2  2  2  2  2  2  2  2  2  2  2  2  2  3  5  5
+ 1229312    2  2  2  2  2  2  2  2  2  7  7  7  7
+ 1234800    2  2  2  2  3  3  5  5  7  7  7
+ 1240029    3  3  3  3  3  3  3  3  3  3  3  7
+ 1244160    2  2  2  2  2  2  2  2  2  2  3  3  3  3  3  5
+ 1250000    2  2  2  2  5  5  5  5  5  5  5
+ 1250235    3  3  3  3  3  3  5  7  7  7
+ 1254400    2  2  2  2  2  2  2  2  2  2  5  5  7  7
+ 1259712    2  2  2  2  2  2  3  3  3  3  3  3  3  3  3
+ 1260000    2  2  2  2  2  3  3  5  5  5  5  7
+ 1260525    3  5  5  7  7  7  7  7
+ 1265625    3  3  3  3  5  5  5  5  5  5
+ 1270080    2  2  2  2  2  2  3  3  3  3  5  7  7
+ 1275750    2  3  3  3  3  3  3  5  5  5  7
+ 1280000    2  2  2  2  2  2  2  2  2  2  2  5  5  5  5
+ 1285956    2  2  3  3  3  3  3  3  3  3  7  7
+ 1286250    2  3  5  5  5  5  7  7  7
+ 1290240    2  2  2  2  2  2  2  2  2  2  2  2  3  3  5  7
+ 1296000    2  2  2  2  2  2  2  3  3  3  3  5  5  5
+ 1296540    2  2  3  3  3  5  7  7  7  7
+ 1306368    2  2  2  2  2  2  2  2  3  3  3  3  3  3  7
+ 1310720    2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  5
+ 1312200    2  2  2  3  3  3  3  3  3  3  3  5  5
+ 1312500    2  2  3  5  5  5  5  5  5  7
+ 1317120    2  2  2  2  2  2  2  2  3  5  7  7  7
+ 1323000    2  2  2  3  3  3  5  5  5  7  7
+ 1327104    2  2  2  2  2  2  2  2  2  2  2  2  2  2  3  3  3  3
+ 1333584    2  2  2  2  3  3  3  3  3  7  7  7
+ 1344000    2  2  2  2  2  2  2  2  2  3  5  5  5  7
+ 1344560    2  2  2  2  5  7  7  7  7  7
+ 1350000    2  2  2  2  3  3  3  5  5  5  5  5
+ 1354752    2  2  2  2  2  2  2  2  2  2  3  3  3  7  7
+ 1360800    2  2  2  2  2  3  3  3  3  3  5  5  7
+ 1361367    3  3  3  3  7  7  7  7  7
+ 1366875    3  3  3  3  3  3  3  5  5  5  5
+ 1372000    2  2  2  2  2  5  5  5  7  7  7
+ 1376256    2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  3  7
+ 1377810    2  3  3  3  3  3  3  3  3  3  5  7
+ 1378125    3  3  5  5  5  5  5  7  7
+ 1382400    2  2  2  2  2  2  2  2  2  2  2  3  3  3  5  5
+ 1382976    2  2  2  2  2  2  3  3  7  7  7  7
+ 1389150    2  3  3  3  3  5  5  7  7  7
+ 1399680    2  2  2  2  2  2  2  3  3  3  3  3  3  3  5
+ 1400000    2  2  2  2  2  2  5  5  5  5  5  7
+ 1404928    2  2  2  2  2  2  2  2  2  2  2  2  7  7  7
+ 1406250    2  3  3  5  5  5  5  5  5  5
+ 1411200    2  2  2  2  2  2  2  3  3  5  5  7  7
+ 1411788    2  2  3  7  7  7  7  7  7
+ 1417176    2  2  2  3  3  3  3  3  3  3  3  3  3  3
+ 1417500    2  2  3  3  3  3  5  5  5  5  7
+ 1428840    2  2  2  3  3  3  3  3  3  5  7  7
+ 1433600    2  2  2  2  2  2  2  2  2  2  2  2  2  5  5  7
+ 1440000    2  2  2  2  2  2  2  2  3  3  5  5  5  5
+ 1440600    2  2  2  3  5  5  7  7  7  7
+ 1451520    2  2  2  2  2  2  2  2  2  3  3  3  3  5  7
+ 1458000    2  2  2  2  3  3  3  3  3  3  5  5  5
+ 1469664    2  2  2  2  2  3  3  3  3  3  3  3  3  7
+ 1470000    2  2  2  2  3  5  5  5  5  7  7
+ 1474560    2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  3  3  5
+ 1476225    3  3  3  3  3  3  3  3  3  3  5  5
+ 1481760    2  2  2  2  2  3  3  3  5  7  7  7
+ 1488375    3  3  3  3  3  5  5  5  7  7
+ 1492992    2  2  2  2  2  2  2  2  2  2  2  3  3  3  3  3  3
+ 1500000    2  2  2  2  2  3  5  5  5  5  5  5
+ 1500282    2  3  3  3  3  3  3  3  7  7  7
+ 1500625    5  5  5  5  7  7  7  7
+ 1505280    2  2  2  2  2  2  2  2  2  2  2  3  5  7  7
+ 1512000    2  2  2  2  2  2  3  3  3  5  5  5  7
+ 1512630    2  3  3  5  7  7  7  7  7
+ 1518750    2  3  3  3  3  3  5  5  5  5  5
+ 1524096    2  2  2  2  2  2  2  3  3  3  3  3  7  7
+ 1530900    2  2  3  3  3  3  3  3  3  5  5  7
+ 1531250    2  5  5  5  5  5  5  7  7
+ 1536000    2  2  2  2  2  2  2  2  2  2  2  2  3  5  5  5
+ 1536640    2  2  2  2  2  2  2  5  7  7  7  7
+ 1543500    2  2  3  3  5  5  5  7  7  7
+ 1548288    2  2  2  2  2  2  2  2  2  2  2  2  2  3  3  3  7
+ 1555200    2  2  2  2  2  2  2  2  3  3  3  3  3  5  5
+ 1555848    2  2  2  3  3  3  3  7  7  7  7
+ 1562500    2  2  5  5  5  5  5  5  5  5
+ 1568000    2  2  2  2  2  2  2  2  5  5  5  7  7
+ 1572864    2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  3
+ 1574640    2  2  2  2  3  3  3  3  3  3  3  3  3  5
+ 1575000    2  2  2  3  3  5  5  5  5  5  7
+ 1580544    2  2  2  2  2  2  2  2  2  3  3  7  7  7
+ 1587600    2  2  2  2  3  3  3  3  5  5  7  7
+ 1594323    3  3  3  3  3  3  3  3  3  3  3  3  3
+ 1600000    2  2  2  2  2  2  2  2  2  5  5  5  5  5
+ 1605632    2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  7  7
+ 1607445    3  3  3  3  3  3  3  3  5  7  7
+ 1612800    2  2  2  2  2  2  2  2  2  2  3  3  5  5  7
+ 1613472    2  2  2  2  2  3  7  7  7  7  7
+ 1620000    2  2  2  2  2  3  3  3  3  5  5  5  5
+ 1620675    3  3  3  5  5  7  7  7  7
+ 1632960    2  2  2  2  2  2  3  3  3  3  3  3  5  7
+ 1638400    2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  5  5
+ 1640250    2  3  3  3  3  3  3  3  3  5  5  5
+ 1640625    3  5  5  5  5  5  5  5  7
+ 1646400    2  2  2  2  2  2  3  5  5  7  7  7
+ 1647086    2  7  7  7  7  7  7  7
+ 1653372    2  2  3  3  3  3  3  3  3  3  3  3  7
+ 1653750    2  3  3  3  5  5  5  5  7  7
+ 1658880    2  2  2  2  2  2  2  2  2  2  2  2  3  3  3  3  5
+ 1666980    2  2  3  3  3  3  3  5  7  7  7
+ 1679616    2  2  2  2  2  2  2  2  3  3  3  3  3  3  3  3
+ 1680000    2  2  2  2  2  2  2  3  5  5  5  5  7
+ 1680700    2  2  5  5  7  7  7  7  7
+ 1687500    2  2  3  3  3  5  5  5  5  5  5
+ 1693440    2  2  2  2  2  2  2  2  3  3  3  5  7  7
+ 1701000    2  2  2  3  3  3  3  3  5  5  5  7
+ 1714608    2  2  2  2  3  3  3  3  3  3  3  7  7
+ 1715000    2  2  2  5  5  5  5  7  7  7
+ 1720320    2  2  2  2  2  2  2  2  2  2  2  2  2  2  3  5  7
+ 1728000    2  2  2  2  2  2  2  2  2  3  3  3  5  5  5
+ 1728720    2  2  2  2  3  3  5  7  7  7  7
+ 1741824    2  2  2  2  2  2  2  2  2  2  3  3  3  3  3  7
+ 1749600    2  2  2  2  2  3  3  3  3  3  3  3  5  5
+ 1750000    2  2  2  2  5  5  5  5  5  5  7
+ 1750329    3  3  3  3  3  3  7  7  7  7
+ 1756160    2  2  2  2  2  2  2  2  2  2  5  7  7  7
+ 1764000    2  2  2  2  2  3  3  5  5  5  7  7
+ 1764735    3  5  7  7  7  7  7  7
+ 1769472    2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  3  3  3
+ 1771470    2  3  3  3  3  3  3  3  3  3  3  3  5
+ 1771875    3  3  3  3  5  5  5  5  5  7
+ 1778112    2  2  2  2  2  2  3  3  3  3  7  7  7
+ 1786050    2  3  3  3  3  3  3  5  5  7  7
+ 1792000    2  2  2  2  2  2  2  2  2  2  2  5  5  5  7
+ 1800000    2  2  2  2  2  2  3  3  5  5  5  5  5
+ 1800750    2  3  5  5  5  7  7  7  7
+ 1806336    2  2  2  2  2  2  2  2  2  2  2  2  3  3  7  7
+ 1814400    2  2  2  2  2  2  2  3  3  3  3  5  5  7
+ 1815156    2  2  3  3  3  7  7  7  7  7
+ 1822500    2  2  3  3  3  3  3  3  5  5  5  5
+ 1835008    2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  7
+ 1837080    2  2  2  3  3  3  3  3  3  3  3  5  7
+ 1837500    2  2  3  5  5  5  5  5  7  7
+ 1843200    2  2  2  2  2  2  2  2  2  2  2  2  2  3  3  5  5
+ 1843968    2  2  2  2  2  2  2  2  3  7  7  7  7
+ 1852200    2  2  2  3  3  3  5  5  7  7  7
+ 1866240    2  2  2  2  2  2  2  2  2  3  3  3  3  3  3  5
+ 1875000    2  2  2  3  5  5  5  5  5  5  5
+ 1881600    2  2  2  2  2  2  2  2  2  3  5  5  7  7
+ 1882384    2  2  2  2  7  7  7  7  7  7
+ 1889568    2  2  2  2  2  3  3  3  3  3  3  3  3  3  3
+ 1890000    2  2  2  2  3  3  3  5  5  5  5  7
+ 1905120    2  2  2  2  2  3  3  3  3  3  5  7  7
+ 1913625    3  3  3  3  3  3  3  5  5  5  7
+ 1920000    2  2  2  2  2  2  2  2  2  2  3  5  5  5  5
+ 1920800    2  2  2  2  2  5  5  7  7  7  7
+ 1928934    2  3  3  3  3  3  3  3  3  3  7  7
+ 1929375    3  3  5  5  5  5  7  7  7
+ 1935360    2  2  2  2  2  2  2  2  2  2  2  3  3  3  5  7
+ 1944000    2  2  2  2  2  2  3  3  3  3  3  5  5  5
+ 1944810    2  3  3  3  3  5  7  7  7  7
+ 1953125    5  5  5  5  5  5  5  5  5
+ 1959552    2  2  2  2  2  2  2  3  3  3  3  3  3  3  7
+ 1960000    2  2  2  2  2  2  5  5  5  5  7  7
+ 1966080    2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  3  5
+ 1968300    2  2  3  3  3  3  3  3  3  3  3  5  5
+ 1968750    2  3  3  5  5  5  5  5  5  7
+ 1975680    2  2  2  2  2  2  2  3  3  5  7  7  7
+ 1984500    2  2  3  3  3  3  5  5  5  7  7
+ 1990656    2  2  2  2  2  2  2  2  2  2  2  2  2  3  3  3  3  3
+ 2000000    2  2  2  2  2  2  2  5  5  5  5  5  5
+ 2000376    2  2  2  3  3  3  3  3  3  7  7  7
+ 2007040    2  2  2  2  2  2  2  2  2  2  2  2  2  5  7  7
+ 2016000    2  2  2  2  2  2  2  2  3  3  5  5  5  7
+ 2016840    2  2  2  3  5  7  7  7  7  7
+ 2025000    2  2  2  3  3  3  3  5  5  5  5  5
+ 2032128    2  2  2  2  2  2  2  2  2  3  3  3  3  7  7
+ 2041200    2  2  2  2  3  3  3  3  3  3  5  5  7
+ 2048000    2  2  2  2  2  2  2  2  2  2  2  2  2  2  5  5  5
+ 2058000    2  2  2  2  3  5  5  5  7  7  7
+ 2064384    2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  3  3  7
+ 2066715    3  3  3  3  3  3  3  3  3  3  5  7
+ 2073600    2  2  2  2  2  2  2  2  2  2  3  3  3  3  5  5
+ 2074464    2  2  2  2  2  3  3  3  7  7  7  7
+ 2083725    3  3  3  3  3  5  5  7  7  7
+ 2097152    2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2
+ 2099520    2  2  2  2  2  2  3  3  3  3  3  3  3  3  5
+ 2100000    2  2  2  2  2  3  5  5  5  5  5  7
+ 2100875    5  5  5  7  7  7  7  7
+ 2107392    2  2  2  2  2  2  2  2  2  2  2  3  7  7  7
+ 2109375    3  3  3  5  5  5  5  5  5  5
+ 2116800    2  2  2  2  2  2  3  3  3  5  5  7  7
+ 2117682    2  3  3  7  7  7  7  7  7
+ 2125764    2  2  3  3  3  3  3  3  3  3  3  3  3  3
+ 2126250    2  3  3  3  3  3  5  5  5  5  7
+ 2143260    2  2  3  3  3  3  3  3  3  5  7  7
+ 2143750    2  5  5  5  5  5  7  7  7
+ 2150400    2  2  2  2  2  2  2  2  2  2  2  2  3  5  5  7
+ 2151296    2  2  2  2  2  2  2  7  7  7  7  7
+ 2160000    2  2  2  2  2  2  2  3  3  3  5  5  5  5
+ 2160900    2  2  3  3  5  5  7  7  7  7
+ 2177280    2  2  2  2  2  2  2  2  3  3  3  3  3  5  7
+ 2187000    2  2  2  3  3  3  3  3  3  3  5  5  5
+ 2187500    2  2  5  5  5  5  5  5  5  7
+ 2195200    2  2  2  2  2  2  2  2  5  5  7  7  7
+ 2204496    2  2  2  2  3  3  3  3  3  3  3  3  3  7
+ 2205000    2  2  2  3  3  5  5  5  5  7  7
+ 2211840    2  2  2  2  2  2  2  2  2  2  2  2  2  2  3  3  3  5
+ 2222640    2  2  2  2  3  3  3  3  5  7  7  7
+ 2239488    2  2  2  2  2  2  2  2  2  2  3  3  3  3  3  3  3
+ 2240000    2  2  2  2  2  2  2  2  2  5  5  5  5  7
+ 2250000    2  2  2  2  3  3  5  5  5  5  5  5
+ 2250423    3  3  3  3  3  3  3  3  7  7  7
+ 2257920    2  2  2  2  2  2  2  2  2  2  3  3  5  7  7
+ 2268000    2  2  2  2  2  3  3  3  3  5  5  5  7
+ 2268945    3  3  3  5  7  7  7  7  7
+ 2278125    3  3  3  3  3  3  5  5  5  5  5
+ 2286144    2  2  2  2  2  2  3  3  3  3  3  3  7  7
+ 2293760    2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  5  7
+ 2296350    2  3  3  3  3  3  3  3  3  5  5  7
+ 2296875    3  5  5  5  5  5  5  7  7
+ 2304000    2  2  2  2  2  2  2  2  2  2  2  3  3  5  5  5
+ 2304960    2  2  2  2  2  2  3  5  7  7  7  7
+ 2315250    2  3  3  3  5  5  5  7  7  7
+ 2322432    2  2  2  2  2  2  2  2  2  2  2  2  3  3  3  3  7
+ 2332800    2  2  2  2  2  2  2  3  3  3  3  3  3  5  5
+ 2333772    2  2  3  3  3  3  3  7  7  7  7
+ 2343750    2  3  5  5  5  5  5  5  5  5
+ 2352000    2  2  2  2  2  2  2  3  5  5  5  7  7
+ 2352980    2  2  5  7  7  7  7  7  7
+ 2359296    2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  3  3
+ 2361960    2  2  2  3  3  3  3  3  3  3  3  3  3  5
+ 2362500    2  2  3  3  3  5  5  5  5  5  7
+ 2370816    2  2  2  2  2  2  2  2  3  3  3  7  7  7
+ 2381400    2  2  2  3  3  3  3  3  5  5  7  7
+ 2400000    2  2  2  2  2  2  2  2  3  5  5  5  5  5
+ 2401000    2  2  2  5  5  5  7  7  7  7
+ 2408448    2  2  2  2  2  2  2  2  2  2  2  2  2  2  3  7  7
+ 2419200    2  2  2  2  2  2  2  2  2  3  3  3  5  5  7
+ 2420208    2  2  2  2  3  3  7  7  7  7  7
+ 2430000    2  2  2  2  3  3  3  3  3  5  5  5  5
+ 2449440    2  2  2  2  2  3  3  3  3  3  3  3  5  7
+ 2450000    2  2  2  2  5  5  5  5  5  7  7
+ 2457600    2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  3  5  5
+ 2458624    2  2  2  2  2  2  2  2  2  2  7  7  7  7
+ 2460375    3  3  3  3  3  3  3  3  3  5  5  5
+ 2469600    2  2  2  2  2  3  3  5  5  7  7  7
+ 2470629    3  7  7  7  7  7  7  7
+ 2480058    2  3  3  3  3  3  3  3  3  3  3  3  7
+ 2480625    3  3  3  3  5  5  5  5  7  7
+ 2488320    2  2  2  2  2  2  2  2  2  2  2  3  3  3  3  3  5
+ 2500000    2  2  2  2  2  5  5  5  5  5  5  5
+ 2500470    2  3  3  3  3  3  3  5  7  7  7
+ 2508800    2  2  2  2  2  2  2  2  2  2  2  5  5  7  7
+ 2519424    2  2  2  2  2  2  2  3  3  3  3  3  3  3  3  3
+ 2520000    2  2  2  2  2  2  3  3  5  5  5  5  7
+ 2521050    2  3  5  5  7  7  7  7  7
+ 2531250    2  3  3  3  3  5  5  5  5  5  5
+ 2540160    2  2  2  2  2  2  2  3  3  3  3  5  7  7
+ 2551500    2  2  3  3  3  3  3  3  5  5  5  7
+ 2560000    2  2  2  2  2  2  2  2  2  2  2  2  5  5  5  5
+ 2571912    2  2  2  3  3  3  3  3  3  3  3  7  7
+ 2572500    2  2  3  5  5  5  5  7  7  7
+ 2580480    2  2  2  2  2  2  2  2  2  2  2  2  2  3  3  5  7
+ 2592000    2  2  2  2  2  2  2  2  3  3  3  3  5  5  5
+ 2593080    2  2  2  3  3  3  5  7  7  7  7
+ 2612736    2  2  2  2  2  2  2  2  2  3  3  3  3  3  3  7
+ 2621440    2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  5
+ 2624400    2  2  2  2  3  3  3  3  3  3  3  3  5  5
+ 2625000    2  2  2  3  5  5  5  5  5  5  7
+ 2634240    2  2  2  2  2  2  2  2  2  3  5  7  7  7
+ 2646000    2  2  2  2  3  3  3  5  5  5  7  7
+ 2654208    2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  3  3  3  3
+ 2657205    3  3  3  3  3  3  3  3  3  3  3  3  5
+ 2667168    2  2  2  2  2  3  3  3  3  3  7  7  7
+ 2679075    3  3  3  3  3  3  3  5  5  7  7
+ 2688000    2  2  2  2  2  2  2  2  2  2  3  5  5  5  7
+ 2689120    2  2  2  2  2  5  7  7  7  7  7
+ 2700000    2  2  2  2  2  3  3  3  5  5  5  5  5
+ 2701125    3  3  5  5  5  7  7  7  7
+ 2709504    2  2  2  2  2  2  2  2  2  2  2  3  3  3  7  7
+ 2721600    2  2  2  2  2  2  3  3  3  3  3  5  5  7
+ 2722734    2  3  3  3  3  7  7  7  7  7
+ 2733750    2  3  3  3  3  3  3  3  5  5  5  5
+ 2734375    5  5  5  5  5  5  5  5  7
+ 2744000    2  2  2  2  2  2  5  5  5  7  7  7
+ 2752512    2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  3  7
+ 2755620    2  2  3  3  3  3  3  3  3  3  3  5  7
+ 2756250    2  3  3  5  5  5  5  5  7  7
+ 2764800    2  2  2  2  2  2  2  2  2  2  2  2  3  3  3  5  5
+ 2765952    2  2  2  2  2  2  2  3  3  7  7  7  7
+ 2778300    2  2  3  3  3  3  5  5  7  7  7
+ 2799360    2  2  2  2  2  2  2  2  3  3  3  3  3  3  3  5
+ 2800000    2  2  2  2  2  2  2  5  5  5  5  5  7
+ 2809856    2  2  2  2  2  2  2  2  2  2  2  2  2  7  7  7
+ 2812500    2  2  3  3  5  5  5  5  5  5  5
+ 2822400    2  2  2  2  2  2  2  2  3  3  5  5  7  7
+ 2823576    2  2  2  3  7  7  7  7  7  7
+ 2834352    2  2  2  2  3  3  3  3  3  3  3  3  3  3  3
+ 2835000    2  2  2  3  3  3  3  5  5  5  5  7
+ 2857680    2  2  2  2  3  3  3  3  3  3  5  7  7
+ 2867200    2  2  2  2  2  2  2  2  2  2  2  2  2  2  5  5  7
+ 2880000    2  2  2  2  2  2  2  2  2  3  3  5  5  5  5
+ 2881200    2  2  2  2  3  5  5  7  7  7  7
+ 2893401    3  3  3  3  3  3  3  3  3  3  7  7
+ 2903040    2  2  2  2  2  2  2  2  2  2  3  3  3  3  5  7
+ 2916000    2  2  2  2  2  3  3  3  3  3  3  5  5  5
+ 2917215    3  3  3  3  3  5  7  7  7  7
+ 2939328    2  2  2  2  2  2  3  3  3  3  3  3  3  3  7
+ 2940000    2  2  2  2  2  3  5  5  5  5  7  7
+ 2941225    5  5  7  7  7  7  7  7
+ 2949120    2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  3  3  5
+ 2952450    2  3  3  3  3  3  3  3  3  3  3  5  5
+ 2953125    3  3  3  5  5  5  5  5  5  7
+ 2963520    2  2  2  2  2  2  3  3  3  5  7  7  7
+ 2976750    2  3  3  3  3  3  5  5  5  7  7
+ 2985984    2  2  2  2  2  2  2  2  2  2  2  2  3  3  3  3  3  3
+ 3000000    2  2  2  2  2  2  3  5  5  5  5  5  5
+ 3000564    2  2  3  3  3  3  3  3  3  7  7  7
+ 3001250    2  5  5  5  5  7  7  7  7
+ 3010560    2  2  2  2  2  2  2  2  2  2  2  2  3  5  7  7
+ 3024000    2  2  2  2  2  2  2  3  3  3  5  5  5  7
+ 3025260    2  2  3  3  5  7  7  7  7  7
+ 3037500    2  2  3  3  3  3  3  5  5  5  5  5
+ 3048192    2  2  2  2  2  2  2  2  3  3  3  3  3  7  7
+ 3061800    2  2  2  3  3  3  3  3  3  3  5  5  7
+ 3062500    2  2  5  5  5  5  5  5  7  7
+ 3072000    2  2  2  2  2  2  2  2  2  2  2  2  2  3  5  5  5
+ 3073280    2  2  2  2  2  2  2  2  5  7  7  7  7
+ 3087000    2  2  2  3  3  5  5  5  7  7  7
+ 3096576    2  2  2  2  2  2  2  2  2  2  2  2  2  2  3  3  3  7
+ 3110400    2  2  2  2  2  2  2  2  2  3  3  3  3  3  5  5
+ 3111696    2  2  2  2  3  3  3  3  7  7  7  7
+ 3125000    2  2  2  5  5  5  5  5  5  5  5
+ 3136000    2  2  2  2  2  2  2  2  2  5  5  5  7  7
+ 3145728    2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  3
+ 3149280    2  2  2  2  2  3  3  3  3  3  3  3  3  3  5
+ 3150000    2  2  2  2  3  3  5  5  5  5  5  7
+ 3161088    2  2  2  2  2  2  2  2  2  2  3  3  7  7  7
+ 3175200    2  2  2  2  2  3  3  3  3  5  5  7  7
+ 3176523    3  3  3  7  7  7  7  7  7
+ 3188646    2  3  3  3  3  3  3  3  3  3  3  3  3  3
+ 3189375    3  3  3  3  3  3  5  5  5  5  7
+ 3200000    2  2  2  2  2  2  2  2  2  2  5  5  5  5  5
+ 3211264    2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  7  7
+ 3214890    2  3  3  3  3  3  3  3  3  5  7  7
+ 3215625    3  5  5  5  5  5  7  7  7
+ 3225600    2  2  2  2  2  2  2  2  2  2  2  3  3  5  5  7
+ 3226944    2  2  2  2  2  2  3  7  7  7  7  7
+ 3240000    2  2  2  2  2  2  3  3  3  3  5  5  5  5
+ 3241350    2  3  3  3  5  5  7  7  7  7
+ 3265920    2  2  2  2  2  2  2  3  3  3  3  3  3  5  7
+ 3276800    2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  5  5
+ 3280500    2  2  3  3  3  3  3  3  3  3  5  5  5
+ 3281250    2  3  5  5  5  5  5  5  5  7
+ 3292800    2  2  2  2  2  2  2  3  5  5  7  7  7
+ 3294172    2  2  7  7  7  7  7  7  7
+ 3306744    2  2  2  3  3  3  3  3  3  3  3  3  3  7
+ 3307500    2  2  3  3  3  5  5  5  5  7  7
+ 3317760    2  2  2  2  2  2  2  2  2  2  2  2  2  3  3  3  3  5
+ 3333960    2  2  2  3  3  3  3  3  5  7  7  7
+ 3359232    2  2  2  2  2  2  2  2  2  3  3  3  3  3  3  3  3
+ 3360000    2  2  2  2  2  2  2  2  3  5  5  5  5  7
+ 3361400    2  2  2  5  5  7  7  7  7  7
+ 3375000    2  2  2  3  3  3  5  5  5  5  5  5
+ 3386880    2  2  2  2  2  2  2  2  2  3  3  3  5  7  7
+ 3402000    2  2  2  2  3  3  3  3  3  5  5  5  7
+ 3429216    2  2  2  2  2  3  3  3  3  3  3  3  7  7
+ 3430000    2  2  2  2  5  5  5  5  7  7  7
+ 3440640    2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  3  5  7
+ 3444525    3  3  3  3  3  3  3  3  3  5  5  7
+ 3456000    2  2  2  2  2  2  2  2  2  2  3  3  3  5  5  5
+ 3457440    2  2  2  2  2  3  3  5  7  7  7  7
+ 3472875    3  3  3  3  5  5  5  7  7  7
+ 3483648    2  2  2  2  2  2  2  2  2  2  2  3  3  3  3  3  7
+ 3499200    2  2  2  2  2  2  3  3  3  3  3  3  3  5  5
+ 3500000    2  2  2  2  2  5  5  5  5  5  5  7
+ 3500658    2  3  3  3  3  3  3  7  7  7  7
+ 3512320    2  2  2  2  2  2  2  2  2  2  2  5  7  7  7
+ 3515625    3  3  5  5  5  5  5  5  5  5
+ 3528000    2  2  2  2  2  2  3  3  5  5  5  7  7
+ 3529470    2  3  5  7  7  7  7  7  7
+ 3538944    2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  3  3  3
+ 3542940    2  2  3  3  3  3  3  3  3  3  3  3  3  5
+ 3543750    2  3  3  3  3  5  5  5  5  5  7
+ 3556224    2  2  2  2  2  2  2  3  3  3  3  7  7  7
+ 3572100    2  2  3  3  3  3  3  3  5  5  7  7
+ 3584000    2  2  2  2  2  2  2  2  2  2  2  2  5  5  5  7
+ 3600000    2  2  2  2  2  2  2  3  3  5  5  5  5  5
+ 3601500    2  2  3  5  5  5  7  7  7  7
+ 3612672    2  2  2  2  2  2  2  2  2  2  2  2  2  3  3  7  7
+ 3628800    2  2  2  2  2  2  2  2  3  3  3  3  5  5  7
+ 3630312    2  2  2  3  3  3  7  7  7  7  7
+ 3645000    2  2  2  3  3  3  3  3  3  5  5  5  5
+ 3670016    2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  7
+ 3674160    2  2  2  2  3  3  3  3  3  3  3  3  5  7
+ 3675000    2  2  2  3  5  5  5  5  5  7  7
+ 3686400    2  2  2  2  2  2  2  2  2  2  2  2  2  2  3  3  5  5
+ 3687936    2  2  2  2  2  2  2  2  2  3  7  7  7  7
+ 3704400    2  2  2  2  3  3  3  5  5  7  7  7
+ 3720087    3  3  3  3  3  3  3  3  3  3  3  3  7
+ 3732480    2  2  2  2  2  2  2  2  2  2  3  3  3  3  3  3  5
+ 3750000    2  2  2  2  3  5  5  5  5  5  5  5
+ 3750705    3  3  3  3  3  3  3  5  7  7  7
+ 3763200    2  2  2  2  2  2  2  2  2  2  3  5  5  7  7
+ 3764768    2  2  2  2  2  7  7  7  7  7  7
+ 3779136    2  2  2  2  2  2  3  3  3  3  3  3  3  3  3  3
+ 3780000    2  2  2  2  2  3  3  3  5  5  5  5  7
+ 3781575    3  3  5  5  7  7  7  7  7
+ 3796875    3  3  3  3  3  5  5  5  5  5  5
+ 3810240    2  2  2  2  2  2  3  3  3  3  3  5  7  7
+ 3827250    2  3  3  3  3  3  3  3  5  5  5  7
+ 3828125    5  5  5  5  5  5  5  7  7
+ 3840000    2  2  2  2  2  2  2  2  2  2  2  3  5  5  5  5
+ 3841600    2  2  2  2  2  2  5  5  7  7  7  7
+ 3857868    2  2  3  3  3  3  3  3  3  3  3  7  7
+ 3858750    2  3  3  5  5  5  5  7  7  7
+ 3870720    2  2  2  2  2  2  2  2  2  2  2  2  3  3  3  5  7
+ 3888000    2  2  2  2  2  2  2  3  3  3  3  3  5  5  5
+ 3889620    2  2  3  3  3  3  5  7  7  7  7
+ 3906250    2  5  5  5  5  5  5  5  5  5
+ 3919104    2  2  2  2  2  2  2  2  3  3  3  3  3  3  3  7
+ 3920000    2  2  2  2  2  2  2  5  5  5  5  7  7
+ 3932160    2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  3  5
+ 3936600    2  2  2  3  3  3  3  3  3  3  3  3  5  5
+ 3937500    2  2  3  3  5  5  5  5  5  5  7
+ 3951360    2  2  2  2  2  2  2  2  3  3  5  7  7  7
+ 3969000    2  2  2  3  3  3  3  5  5  5  7  7
+ 3981312    2  2  2  2  2  2  2  2  2  2  2  2  2  2  3  3  3  3  3
+ 4000000    2  2  2  2  2  2  2  2  5  5  5  5  5  5
+ 4000752    2  2  2  2  3  3  3  3  3  3  7  7  7
+ 4014080    2  2  2  2  2  2  2  2  2  2  2  2  2  2  5  7  7
+ 4032000    2  2  2  2  2  2  2  2  2  3  3  5  5  5  7
+ 4033680    2  2  2  2  3  5  7  7  7  7  7
+ 4050000    2  2  2  2  3  3  3  3  5  5  5  5  5
+ 4064256    2  2  2  2  2  2  2  2  2  2  3  3  3  3  7  7
+ 4082400    2  2  2  2  2  3  3  3  3  3  3  5  5  7
+ 4084101    3  3  3  3  3  7  7  7  7  7
+ 4096000    2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  5  5  5
+ 4100625    3  3  3  3  3  3  3  3  5  5  5  5
+ 4116000    2  2  2  2  2  3  5  5  5  7  7  7
+ 4117715    5  7  7  7  7  7  7  7
+ 4128768    2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  3  3  7
+ 4133430    2  3  3  3  3  3  3  3  3  3  3  5  7
+ 4134375    3  3  3  5  5  5  5  5  7  7
+ 4147200    2  2  2  2  2  2  2  2  2  2  2  3  3  3  3  5  5
+ 4148928    2  2  2  2  2  2  3  3  3  7  7  7  7
+ 4167450    2  3  3  3  3  3  5  5  7  7  7
+ 4194304    2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2
+ 4199040    2  2  2  2  2  2  2  3  3  3  3  3  3  3  3  5
+ 4200000    2  2  2  2  2  2  3  5  5  5  5  5  7
+ 4201750    2  5  5  5  7  7  7  7  7
+ 4214784    2  2  2  2  2  2  2  2  2  2  2  2  3  7  7  7
+ 4218750    2  3  3  3  5  5  5  5  5  5  5
+ 4233600    2  2  2  2  2  2  2  3  3  3  5  5  7  7
+ 4235364    2  2  3  3  7  7  7  7  7  7
+ 4251528    2  2  2  3  3  3  3  3  3  3  3  3  3  3  3
+ 4252500    2  2  3  3  3  3  3  5  5  5  5  7
+ 4286520    2  2  2  3  3  3  3  3  3  3  5  7  7
+ 4287500    2  2  5  5  5  5  5  7  7  7
+ 4300800    2  2  2  2  2  2  2  2  2  2  2  2  2  3  5  5  7
+ 4302592    2  2  2  2  2  2  2  2  7  7  7  7  7
+ 4320000    2  2  2  2  2  2  2  2  3  3  3  5  5  5  5
+ 4321800    2  2  2  3  3  5  5  7  7  7  7
+ 4354560    2  2  2  2  2  2  2  2  2  3  3  3  3  3  5  7
+ 4374000    2  2  2  2  3  3  3  3  3  3  3  5  5  5
+ 4375000    2  2  2  5  5  5  5  5  5  5  7
+ 4390400    2  2  2  2  2  2  2  2  2  5  5  7  7  7
+ 4408992    2  2  2  2  2  3  3  3  3  3  3  3  3  3  7
+ 4410000    2  2  2  2  3  3  5  5  5  5  7  7
+ 4423680    2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  3  3  3  5
+ 4428675    3  3  3  3  3  3  3  3  3  3  3  5  5
+ 4445280    2  2  2  2  2  3  3  3  3  5  7  7  7
+ 4465125    3  3  3  3  3  3  5  5  5  7  7
+ 4478976    2  2  2  2  2  2  2  2  2  2  2  3  3  3  3  3  3  3
+ 4480000    2  2  2  2  2  2  2  2  2  2  5  5  5  5  7
+ 4500000    2  2  2  2  2  3  3  5  5  5  5  5  5
+ 4500846    2  3  3  3  3  3  3  3  3  7  7  7
+ 4501875    3  5  5  5  5  7  7  7  7
+ 4515840    2  2  2  2  2  2  2  2  2  2  2  3  3  5  7  7
+ 4536000    2  2  2  2  2  2  3  3  3  3  5  5  5  7
+ 4537890    2  3  3  3  5  7  7  7  7  7
+ 4556250    2  3  3  3  3  3  3  5  5  5  5  5
+ 4572288    2  2  2  2  2  2  2  3  3  3  3  3  3  7  7
+ 4587520    2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  5  7
+ 4592700    2  2  3  3  3  3  3  3  3  3  5  5  7
+ 4593750    2  3  5  5  5  5  5  5  7  7
+ 4608000    2  2  2  2  2  2  2  2  2  2  2  2  3  3  5  5  5
+ 4609920    2  2  2  2  2  2  2  3  5  7  7  7  7
+ 4630500    2  2  3  3  3  5  5  5  7  7  7
+ 4644864    2  2  2  2  2  2  2  2  2  2  2  2  2  3  3  3  3  7
+ 4665600    2  2  2  2  2  2  2  2  3  3  3  3  3  3  5  5
+ 4667544    2  2  2  3  3  3  3  3  7  7  7  7
+ 4687500    2  2  3  5  5  5  5  5  5  5  5
+ 4704000    2  2  2  2  2  2  2  2  3  5  5  5  7  7
+ 4705960    2  2  2  5  7  7  7  7  7  7
+ 4718592    2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  3  3
+ 4723920    2  2  2  2  3  3  3  3  3  3  3  3  3  3  5
+ 4725000    2  2  2  3  3  3  5  5  5  5  5  7
+ 4741632    2  2  2  2  2  2  2  2  2  3  3  3  7  7  7
+ 4762800    2  2  2  2  3  3  3  3  3  5  5  7  7
+ 4782969    3  3  3  3  3  3  3  3  3  3  3  3  3  3
+ 4800000    2  2  2  2  2  2  2  2  2  3  5  5  5  5  5
+ 4802000    2  2  2  2  5  5  5  7  7  7  7
+ 4816896    2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  3  7  7
+ 4822335    3  3  3  3  3  3  3  3  3  5  7  7
+ 4838400    2  2  2  2  2  2  2  2  2  2  3  3  3  5  5  7
+ 4840416    2  2  2  2  2  3  3  7  7  7  7  7
+ 4860000    2  2  2  2  2  3  3  3  3  3  5  5  5  5
+ 4862025    3  3  3  3  5  5  7  7  7  7
+ 4898880    2  2  2  2  2  2  3  3  3  3  3  3  3  5  7
+ 4900000    2  2  2  2  2  5  5  5  5  5  7  7
+ 4915200    2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  3  5  5
+ 4917248    2  2  2  2  2  2  2  2  2  2  2  7  7  7  7
+ 4920750    2  3  3  3  3  3  3  3  3  3  5  5  5
+ 4921875    3  3  5  5  5  5  5  5  5  7
+ 4939200    2  2  2  2  2  2  3  3  5  5  7  7  7
+ 4941258    2  3  7  7  7  7  7  7  7
+ 4960116    2  2  3  3  3  3  3  3  3  3  3  3  3  7
+ 4961250    2  3  3  3  3  5  5  5  5  7  7
+ 4976640    2  2  2  2  2  2  2  2  2  2  2  2  3  3  3  3  3  5
+ 5000000    2  2  2  2  2  2  5  5  5  5  5  5  5
+ 5000940    2  2  3  3  3  3  3  3  5  7  7  7
+ 5017600    2  2  2  2  2  2  2  2  2  2  2  2  5  5  7  7
+ 5038848    2  2  2  2  2  2  2  2  3  3  3  3  3  3  3  3  3
+ 5040000    2  2  2  2  2  2  2  3  3  5  5  5  5  7
+ 5042100    2  2  3  5  5  7  7  7  7  7
+ 5062500    2  2  3  3  3  3  5  5  5  5  5  5
+ 5080320    2  2  2  2  2  2  2  2  3  3  3  3  5  7  7
+ 5103000    2  2  2  3  3  3  3  3  3  5  5  5  7
+ 5120000    2  2  2  2  2  2  2  2  2  2  2  2  2  5  5  5  5
+ 5143824    2  2  2  2  3  3  3  3  3  3  3  3  7  7
+ 5145000    2  2  2  3  5  5  5  5  7  7  7
+ 5160960    2  2  2  2  2  2  2  2  2  2  2  2  2  2  3  3  5  7
+ 5184000    2  2  2  2  2  2  2  2  2  3  3  3  3  5  5  5
+ 5186160    2  2  2  2  3  3  3  5  7  7  7  7
+ 5225472    2  2  2  2  2  2  2  2  2  2  3  3  3  3  3  3  7
+ 5242880    2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  5
+ 5248800    2  2  2  2  2  3  3  3  3  3  3  3  3  5  5
+ 5250000    2  2  2  2  3  5  5  5  5  5  5  7
+ 5250987    3  3  3  3  3  3  3  7  7  7  7
+ 5268480    2  2  2  2  2  2  2  2  2  2  3  5  7  7  7
+ 5292000    2  2  2  2  2  3  3  3  5  5  5  7  7
+ 5294205    3  3  5  7  7  7  7  7  7
+ 5308416    2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  3  3  3  3
+ 5314410    2  3  3  3  3  3  3  3  3  3  3  3  3  5
+ 5315625    3  3  3  3  3  5  5  5  5  5  7
+ 5334336    2  2  2  2  2  2  3  3  3  3  3  7  7  7
+ 5358150    2  3  3  3  3  3  3  3  5  5  7  7
+ 5359375    5  5  5  5  5  5  7  7  7
+ 5376000    2  2  2  2  2  2  2  2  2  2  2  3  5  5  5  7
+ 5378240    2  2  2  2  2  2  5  7  7  7  7  7
+ 5400000    2  2  2  2  2  2  3  3  3  5  5  5  5  5
+ 5402250    2  3  3  5  5  5  7  7  7  7
+ 5419008    2  2  2  2  2  2  2  2  2  2  2  2  3  3  3  7  7
+ 5443200    2  2  2  2  2  2  2  3  3  3  3  3  5  5  7
+ 5445468    2  2  3  3  3  3  7  7  7  7  7
+ 5467500    2  2  3  3  3  3  3  3  3  5  5  5  5
+ 5468750    2  5  5  5  5  5  5  5  5  7
+ 5488000    2  2  2  2  2  2  2  5  5  5  7  7  7
+ 5505024    2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  3  7
+ 5511240    2  2  2  3  3  3  3  3  3  3  3  3  5  7
+ 5512500    2  2  3  3  5  5  5  5  5  7  7
+ 5529600    2  2  2  2  2  2  2  2  2  2  2  2  2  3  3  3  5  5
+ 5531904    2  2  2  2  2  2  2  2  3  3  7  7  7  7
+ 5556600    2  2  2  3  3  3  3  5  5  7  7  7
+ 5598720    2  2  2  2  2  2  2  2  2  3  3  3  3  3  3  3  5
+ 5600000    2  2  2  2  2  2  2  2  5  5  5  5  5  7
+ 5619712    2  2  2  2  2  2  2  2  2  2  2  2  2  2  7  7  7
+ 5625000    2  2  2  3  3  5  5  5  5  5  5  5
+ 5644800    2  2  2  2  2  2  2  2  2  3  3  5  5  7  7
+ 5647152    2  2  2  2  3  7  7  7  7  7  7
+ 5668704    2  2  2  2  2  3  3  3  3  3  3  3  3  3  3  3
+ 5670000    2  2  2  2  3  3  3  3  5  5  5  5  7
+ 5715360    2  2  2  2  2  3  3  3  3  3  3  5  7  7
+ 5734400    2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  5  5  7
+ 5740875    3  3  3  3  3  3  3  3  5  5  5  7
+ 5760000    2  2  2  2  2  2  2  2  2  2  3  3  5  5  5  5
+ 5762400    2  2  2  2  2  3  5  5  7  7  7  7
+ 5764801    7  7  7  7  7  7  7  7
+ 5786802    2  3  3  3  3  3  3  3  3  3  3  7  7
+ 5788125    3  3  3  5  5  5  5  7  7  7
+ 5806080    2  2  2  2  2  2  2  2  2  2  2  3  3  3  3  5  7
+ 5832000    2  2  2  2  2  2  3  3  3  3  3  3  5  5  5
+ 5834430    2  3  3  3  3  3  5  7  7  7  7
+ 5859375    3  5  5  5  5  5  5  5  5  5
+ 5878656    2  2  2  2  2  2  2  3  3  3  3  3  3  3  3  7
+ 5880000    2  2  2  2  2  2  3  5  5  5  5  7  7
+ 5882450    2  5  5  7  7  7  7  7  7
+ 5898240    2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  3  3  5
+ 5904900    2  2  3  3  3  3  3  3  3  3  3  3  5  5
+ 5906250    2  3  3  3  5  5  5  5  5  5  7
+ 5927040    2  2  2  2  2  2  2  3  3  3  5  7  7  7
+ 5953500    2  2  3  3  3  3  3  5  5  5  7  7
+ 5971968    2  2  2  2  2  2  2  2  2  2  2  2  2  3  3  3  3  3  3
+ 6000000    2  2  2  2  2  2  2  3  5  5  5  5  5  5
+ 6001128    2  2  2  3  3  3  3  3  3  3  7  7  7
+ 6002500    2  2  5  5  5  5  7  7  7  7
+ 6021120    2  2  2  2  2  2  2  2  2  2  2  2  2  3  5  7  7
+ 6048000    2  2  2  2  2  2  2  2  3  3  3  5  5  5  7
+ 6050520    2  2  2  3  3  5  7  7  7  7  7
+ 6075000    2  2  2  3  3  3  3  3  5  5  5  5  5
+ 6096384    2  2  2  2  2  2  2  2  2  3  3  3  3  3  7  7
+ 6123600    2  2  2  2  3  3  3  3  3  3  3  5  5  7
+ 6125000    2  2  2  5  5  5  5  5  5  7  7
+ 6144000    2  2  2  2  2  2  2  2  2  2  2  2  2  2  3  5  5  5
+ 6146560    2  2  2  2  2  2  2  2  2  5  7  7  7  7
+ 6174000    2  2  2  2  3  3  5  5  5  7  7  7
+ 6193152    2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  3  3  3  7
+ 6200145    3  3  3  3  3  3  3  3  3  3  3  5  7
+ 6220800    2  2  2  2  2  2  2  2  2  2  3  3  3  3  3  5  5
+ 6223392    2  2  2  2  2  3  3  3  3  7  7  7  7
+ 6250000    2  2  2  2  5  5  5  5  5  5  5  5
+ 6251175    3  3  3  3  3  3  5  5  7  7  7
+ 6272000    2  2  2  2  2  2  2  2  2  2  5  5  5  7  7
+ 6291456    2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  3
+ 6298560    2  2  2  2  2  2  3  3  3  3  3  3  3  3  3  5
+ 6300000    2  2  2  2  2  3  3  5  5  5  5  5  7
+ 6302625    3  5  5  5  7  7  7  7  7
+ 6322176    2  2  2  2  2  2  2  2  2  2  2  3  3  7  7  7
+ 6328125    3  3  3  3  5  5  5  5  5  5  5
+ 6350400    2  2  2  2  2  2  3  3  3  3  5  5  7  7
+ 6353046    2  3  3  3  7  7  7  7  7  7
+ 6377292    2  2  3  3  3  3  3  3  3  3  3  3  3  3  3
+ 6378750    2  3  3  3  3  3  3  5  5  5  5  7
+ 6400000    2  2  2  2  2  2  2  2  2  2  2  5  5  5  5  5
+ 6422528    2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  7  7
+ 6429780    2  2  3  3  3  3  3  3  3  3  5  7  7
+ 6431250    2  3  5  5  5  5  5  7  7  7
+ 6451200    2  2  2  2  2  2  2  2  2  2  2  2  3  3  5  5  7
+ 6453888    2  2  2  2  2  2  2  3  7  7  7  7  7
+ 6480000    2  2  2  2  2  2  2  3  3  3  3  5  5  5  5
+ 6482700    2  2  3  3  3  5  5  7  7  7  7
+ 6531840    2  2  2  2  2  2  2  2  3  3  3  3  3  3  5  7
+ 6553600    2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  5  5
+ 6561000    2  2  2  3  3  3  3  3  3  3  3  5  5  5
+ 6562500    2  2  3  5  5  5  5  5  5  5  7
+ 6585600    2  2  2  2  2  2  2  2  3  5  5  7  7  7
+ 6588344    2  2  2  7  7  7  7  7  7  7
+ 6613488    2  2  2  2  3  3  3  3  3  3  3  3  3  3  7
+ 6615000    2  2  2  3  3  3  5  5  5  5  7  7
+ 6635520    2  2  2  2  2  2  2  2  2  2  2  2  2  2  3  3  3  3  5
+ 6667920    2  2  2  2  3  3  3  3  3  5  7  7  7
+ 6718464    2  2  2  2  2  2  2  2  2  2  3  3  3  3  3  3  3  3
+ 6720000    2  2  2  2  2  2  2  2  2  3  5  5  5  5  7
+ 6722800    2  2  2  2  5  5  7  7  7  7  7
+ 6750000    2  2  2  2  3  3  3  5  5  5  5  5  5
+ 6751269    3  3  3  3  3  3  3  3  3  7  7  7
+ 6773760    2  2  2  2  2  2  2  2  2  2  3  3  3  5  7  7
+ 6804000    2  2  2  2  2  3  3  3  3  3  5  5  5  7
+ 6806835    3  3  3  3  5  7  7  7  7  7
+ 6834375    3  3  3  3  3  3  3  5  5  5  5  5
+ 6858432    2  2  2  2  2  2  3  3  3  3  3  3  3  7  7
+ 6860000    2  2  2  2  2  5  5  5  5  7  7  7
+ 6881280    2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  3  5  7
+ 6889050    2  3  3  3  3  3  3  3  3  3  5  5  7
+ 6890625    3  3  5  5  5  5  5  5  7  7
+ 6912000    2  2  2  2  2  2  2  2  2  2  2  3  3  3  5  5  5
+ 6914880    2  2  2  2  2  2  3  3  5  7  7  7  7
+ 6945750    2  3  3  3  3  5  5  5  7  7  7
+ 6967296    2  2  2  2  2  2  2  2  2  2  2  2  3  3  3  3  3  7
+ 6998400    2  2  2  2  2  2  2  3  3  3  3  3  3  3  5  5
+ 7000000    2  2  2  2  2  2  5  5  5  5  5  5  7
+ 7001316    2  2  3  3  3  3  3  3  7  7  7  7
+ 7024640    2  2  2  2  2  2  2  2  2  2  2  2  5  7  7  7
+ 7031250    2  3  3  5  5  5  5  5  5  5  5
+ 7056000    2  2  2  2  2  2  2  3  3  5  5  5  7  7
+ 7058940    2  2  3  5  7  7  7  7  7  7
+ 7077888    2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  3  3  3
+ 7085880    2  2  2  3  3  3  3  3  3  3  3  3  3  3  5
+ 7087500    2  2  3  3  3  3  5  5  5  5  5  7
+ 7112448    2  2  2  2  2  2  2  2  3  3  3  3  7  7  7
+ 7144200    2  2  2  3  3  3  3  3  3  5  5  7  7
+ 7168000    2  2  2  2  2  2  2  2  2  2  2  2  2  5  5  5  7
+ 7200000    2  2  2  2  2  2  2  2  3  3  5  5  5  5  5
+ 7203000    2  2  2  3  5  5  5  7  7  7  7
+ 7225344    2  2  2  2  2  2  2  2  2  2  2  2  2  2  3  3  7  7
+ 7257600    2  2  2  2  2  2  2  2  2  3  3  3  3  5  5  7
+ 7260624    2  2  2  2  3  3  3  7  7  7  7  7
+ 7290000    2  2  2  2  3  3  3  3  3  3  5  5  5  5
+ 7340032    2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  7
+ 7348320    2  2  2  2  2  3  3  3  3  3  3  3  3  5  7
+ 7350000    2  2  2  2  3  5  5  5  5  5  7  7
+ 7372800    2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  3  3  5  5
+ 7375872    2  2  2  2  2  2  2  2  2  2  3  7  7  7  7
+ 7381125    3  3  3  3  3  3  3  3  3  3  5  5  5
+ 7408800    2  2  2  2  2  3  3  3  5  5  7  7  7
+ 7411887    3  3  7  7  7  7  7  7  7
+ 7440174    2  3  3  3  3  3  3  3  3  3  3  3  3  7
+ 7441875    3  3  3  3  3  5  5  5  5  7  7
+ 7464960    2  2  2  2  2  2  2  2  2  2  2  3  3  3  3  3  3  5
+ 7500000    2  2  2  2  2  3  5  5  5  5  5  5  5
+ 7501410    2  3  3  3  3  3  3  3  5  7  7  7
+ 7503125    5  5  5  5  5  7  7  7  7
+ 7526400    2  2  2  2  2  2  2  2  2  2  2  3  5  5  7  7
+ 7529536    2  2  2  2  2  2  7  7  7  7  7  7
+ 7558272    2  2  2  2  2  2  2  3  3  3  3  3  3  3  3  3  3
+ 7560000    2  2  2  2  2  2  3  3  3  5  5  5  5  7
+ 7563150    2  3  3  5  5  7  7  7  7  7
+ 7593750    2  3  3  3  3  3  5  5  5  5  5  5
+ 7620480    2  2  2  2  2  2  2  3  3  3  3  3  5  7  7
+ 7654500    2  2  3  3  3  3  3  3  3  5  5  5  7
+ 7656250    2  5  5  5  5  5  5  5  7  7
+ 7680000    2  2  2  2  2  2  2  2  2  2  2  2  3  5  5  5  5
+ 7683200    2  2  2  2  2  2  2  5  5  7  7  7  7
+ 7715736    2  2  2  3  3  3  3  3  3  3  3  3  7  7
+ 7717500    2  2  3  3  5  5  5  5  7  7  7
+ 7741440    2  2  2  2  2  2  2  2  2  2  2  2  2  3  3  3  5  7
+ 7776000    2  2  2  2  2  2  2  2  3  3  3  3  3  5  5  5
+ 7779240    2  2  2  3  3  3  3  5  7  7  7  7
+ 7812500    2  2  5  5  5  5  5  5  5  5  5
+ 7838208    2  2  2  2  2  2  2  2  2  3  3  3  3  3  3  3  7
+ 7840000    2  2  2  2  2  2  2  2  5  5  5  5  7  7
+ 7864320    2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  3  5
+ 7873200    2  2  2  2  3  3  3  3  3  3  3  3  3  5  5
+ 7875000    2  2  2  3  3  5  5  5  5  5  5  7
+ 7902720    2  2  2  2  2  2  2  2  2  3  3  5  7  7  7
+ 7938000    2  2  2  2  3  3  3  3  5  5  5  7  7
+ 7962624    2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  3  3  3  3  3
+ 7971615    3  3  3  3  3  3  3  3  3  3  3  3  3  5
+ 8000000    2  2  2  2  2  2  2  2  2  5  5  5  5  5  5
+ 8001504    2  2  2  2  2  3  3  3  3  3  3  7  7  7
+ 8028160    2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  5  7  7
+ 8037225    3  3  3  3  3  3  3  3  5  5  7  7
+ 8064000    2  2  2  2  2  2  2  2  2  2  3  3  5  5  5  7
+ 8067360    2  2  2  2  2  3  5  7  7  7  7  7
+ 8100000    2  2  2  2  2  3  3  3  3  5  5  5  5  5
+ 8103375    3  3  3  5  5  5  7  7  7  7
+ 8128512    2  2  2  2  2  2  2  2  2  2  2  3  3  3  3  7  7
+ 8164800    2  2  2  2  2  2  3  3  3  3  3  3  5  5  7
+ 8168202    2  3  3  3  3  3  7  7  7  7  7
+ 8192000    2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  5  5  5
+ 8201250    2  3  3  3  3  3  3  3  3  5  5  5  5
+ 8203125    3  5  5  5  5  5  5  5  5  7
+ 8232000    2  2  2  2  2  2  3  5  5  5  7  7  7
+ 8235430    2  5  7  7  7  7  7  7  7
+ 8257536    2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  3  3  7
+ 8266860    2  2  3  3  3  3  3  3  3  3  3  3  5  7
+ 8268750    2  3  3  3  5  5  5  5  5  7  7
+ 8294400    2  2  2  2  2  2  2  2  2  2  2  2  3  3  3  3  5  5
+ 8297856    2  2  2  2  2  2  2  3  3  3  7  7  7  7
+ 8334900    2  2  3  3  3  3  3  5  5  7  7  7
+ 8388608    2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2
diff --git a/lib/nfft.out b/lib/nfft.out
new file mode 100644
index 0000000..142607a
--- /dev/null
+++ b/lib/nfft.out
@@ -0,0 +1,2067 @@
+       8  0.0000002  0.00000003  32.05   480.8 1000000   0.0
+       9  0.0000002  0.00000010  36.06   571.5 1000000   0.0
+      10  0.0000003  0.00000011  36.63   608.4 1000000   0.0
+      12  0.0000003  0.00000006  41.58   745.3 1000000   0.0
+      14  0.0000003  0.00000018  49.86   949.1 1000000   0.0
+      15  0.0000003  0.00000014  46.90   916.2 1000000   0.0
+      16  0.0000003  0.00000014  46.62   932.4 1000000   0.0
+      18  0.0000005  0.00000012  38.46   801.9 1000000   0.0
+      20  0.0000004  0.00000015  54.55  1178.9 1000000   0.0
+      21  0.0000007  0.00000013  29.54   648.6  713069   0.0
+      24  0.0000005  0.00000018  48.08  1102.1 1000000   0.0
+      25  0.0000005  0.00000012  46.86  1088.1  950368   0.0
+      27  0.0000008  0.00000013  34.88   829.2  654933   0.0
+      28  0.0000006  0.00000016  49.94  1200.4  904282   0.0
+      30  0.0000007  0.00000014  41.13  1009.1  695083   0.0
+      32  0.0000004  0.00000016  75.97  1899.3 1000000   0.0
+      35  0.0000009  0.00000015  40.99  1051.2  593730   0.0
+      36  0.0000006  0.00000016  64.10  1657.0  902775   0.0
+      40  0.0000006  0.00000015  65.49  1742.7  830089   0.0
+      42  0.0000009  0.00000016  49.30  1329.1  595083   0.0
+      45  0.0000010  0.00000016  45.24  1242.4  509755   0.0
+      48  0.0000007  0.00000016  70.88  1979.3  748657   0.0
+      49  0.0000009  0.00000019  56.12  1575.4  580638   0.0
+      50  0.0000008  0.00000019  64.04  1807.1  649334   0.0
+      54  0.0000009  0.00000020  59.11  1700.9  554979   0.0
+      56  0.0000007  0.00000018  83.07  2412.0  752054   0.0
+      60  0.0000008  0.00000017  71.05  2098.3  600342   0.0
+      63  0.0000014  0.00000017  45.62  1363.3  367097   0.0
+      64  0.0000008  0.00000016  79.63  2389.0  630847   0.0
+      70  0.0000011  0.00000019  66.21  2029.0  479524   0.0
+      72  0.0000012  0.00000018  58.27  1797.7  410335   0.0
+      75  0.0000015  0.00000017  51.01  1588.5  344802   0.0
+      80  0.0000010  0.00000018  76.77  2426.6  486510   0.0
+      81  0.0000012  0.00000018  66.71  2114.8  417583   0.0
+      84  0.0000011  0.00000019  74.58  2383.8  450162   0.0
+      90  0.0000015  0.00000018  61.29  1989.3  345250   0.0
+      96  0.0000011  0.00000017  90.90  2992.8  480059   0.1
+      98  0.0000013  0.00000019  73.29  2424.0  379166   0.0
+     100  0.0000012  0.00000020  82.16  2729.2  416548   0.0
+     105  0.0000016  0.00000021  64.79  2175.0  312826   0.0
+     108  0.0000015  0.00000020  72.91  2462.4  342256   0.0
+     112  0.0000014  0.00000017  80.48  2739.1  364301   0.0
+     120  0.0000014  0.00000020  83.73  2891.4  353744   0.1
+     125  0.0000020  0.00000020  61.20  2131.7  248249   0.0
+     126  0.0000019  0.00000019  64.98  2266.9  261472   0.0
+     128  0.0000013  0.00000017 102.07  3572.4  404292   0.0
+     135  0.0000020  0.00000019  66.30  2345.8  248983   0.0
+     140  0.0000016  0.00000021  84.96  3028.7  307695   0.0
+     144  0.0000012  0.00000018 116.47  4175.4  410073   0.1
+     147  0.0000023  0.00000021  62.65  2255.3  216082   0.0
+     150  0.0000015  0.00000023  99.81  3607.5  337364   0.0
+     160  0.0000010  0.00000018 157.76  5775.4  499890   0.1
+     162  0.0000018  0.00000021  89.38  3280.2  279724   0.0
+     168  0.0000012  0.00000019 135.89  5022.8  410109   0.0
+     175  0.0000023  0.00000022  76.10  2835.3  220478   0.0
+     180  0.0000018  0.00000020 101.05  3785.4  284633   0.1
+     189  0.0000029  0.00000022  65.77  2486.9  176433   0.0
+     192  0.0000013  0.00000021 144.48  5479.5  381532   0.1
+     196  0.0000019  0.00000020 103.67  3947.0  268163   0.0
+     200  0.0000017  0.00000020 116.52  4453.2  295374   0.1
+     210  0.0000022  0.00000021  95.01  3664.6  229379   0.0
+     216  0.0000019  0.00000021 111.71  4331.4  262198   0.1
+     224  0.0000016  0.00000021 143.62  5606.6  325073   0.0
+     225  0.0000028  0.00000024  80.24  3135.0  180813   0.0
+     240  0.0000018  0.00000019 136.65  5402.4  288678   0.1
+     243  0.0000037  0.00000022  65.75  2605.3  137187   0.0
+     245  0.0000035  0.00000022  69.66  2764.2  144150   0.0
+     250  0.0000026  0.00000022  96.56  3845.9  195828   0.0
+     252  0.0000027  0.00000022  94.86  3783.6  190847   0.1
+     256  0.0000018  0.00000020 144.00  5760.1  285202   0.0
+     270  0.0000030  0.00000022  90.44  3652.3  169827   0.1
+     280  0.0000018  0.00000020 153.57  6242.0  278071   0.1
+     288  0.0000024  0.00000020 120.47  4921.1  212077   0.1
+     294  0.0000034  0.00000023  85.65  3511.6  147709   0.0
+     300  0.0000023  0.00000020 130.04  5350.5  219771   0.1
+     315  0.0000042  0.00000023  74.49  3091.1  119897   0.0
+     320  0.0000022  0.00000020 143.84  5985.1  227893   0.1
+     324  0.0000035  0.00000023  92.99  3877.5  145508   0.1
+     336  0.0000031  0.00000021 107.57  4514.0  162322   0.1
+     343  0.0000051  0.00000023  67.61  2847.2   99940   0.0
+     350  0.0000038  0.00000024  91.20  3853.7  132109   0.0
+     360  0.0000033  0.00000022 109.15  4634.3  153716   0.2
+     375  0.0000054  0.00000024  69.05  2952.3   93361   0.0
+     378  0.0000038  0.00000023 100.29  4293.5  134514   0.0
+     384  0.0000029  0.00000022 133.04  5710.7  175655   0.1
+     392  0.0000041  0.00000022  94.58  4074.1  122333   0.0
+     400  0.0000030  0.00000021 132.30  5718.1  167698   0.1
+     405  0.0000057  0.00000023  71.36  3090.4   89328   0.0
+     420  0.0000040  0.00000023 105.23  4585.0  127032   0.1
+     432  0.0000039  0.00000022 111.37  4875.0  130702   0.1
+     441  0.0000073  0.00000024  60.29  2648.0   69310   0.0
+     448  0.0000035  0.00000021 128.02  5637.5  144878   0.1
+     450  0.0000045  0.00000023 100.94  4448.2  113724   0.1
+     480  0.0000042  0.00000021 115.27  5133.6  121758   0.2
+     486  0.0000053  0.00000024  91.52  4084.0   95475   0.0
+     490  0.0000054  0.00000023  90.51  4044.1   93646   0.0
+     500  0.0000054  0.00000023  92.18  4132.4   93472   0.1
+     504  0.0000047  0.00000022 108.33  4862.7  108981   0.1
+     512  0.0000032  0.00000020 157.83  7102.4  156292   0.0
+     525  0.0000063  0.00000023  82.97  3748.6   80126   0.0
+     540  0.0000046  0.00000022 116.98  5309.0  109830   0.1
+     560  0.0000049  0.00000021 115.38  5266.7  104464   0.1
+     567  0.0000086  0.00000024  66.26  3030.4   59247   0.0
+     576  0.0000045  0.00000021 128.17  5876.7  112819   0.2
+     588  0.0000057  0.00000024 102.49  4714.6   88379   0.0
+     600  0.0000053  0.00000022 112.66  5198.5   95195   0.2
+     625  0.0000084  0.00000026  74.25  3448.1   60231   0.0
+     630  0.0000054  0.00000023 115.65  5377.5   93074   0.1
+     640  0.0000039  0.00000020 165.92  7733.5  131443   0.2
+     648  0.0000057  0.00000023 113.93  5320.6   89140   0.1
+     672  0.0000059  0.00000023 113.15  5313.9   85367   0.1
+     675  0.0000088  0.00000024  77.13  3624.4   57930   0.1
+     686  0.0000065  0.00000023 106.10  4998.2   78411   0.0
+     700  0.0000072  0.00000023  97.15  4591.1   70368   0.1
+     720  0.0000060  0.00000022 119.85  5687.8   84388   0.3
+     729  0.0000097  0.00000024  74.86  3559.7   52066   0.0
+     735  0.0000097  0.00000024  75.90  3613.4   52355   0.0
+     750  0.0000068  0.00000025 111.07  5303.9   75083   0.1
+     756  0.0000073  0.00000024 104.04  4974.2   69771   0.1
+     768  0.0000051  0.00000022 149.42  7161.0   98641   0.2
+     784  0.0000072  0.00000024 108.16  5199.4   69943   0.1
+     800  0.0000065  0.00000023 124.02  5980.0   78593   0.2
+     810  0.0000073  0.00000024 111.58  5390.3   69839   0.1
+     840  0.0000067  0.00000023 124.60  6052.1   75206   0.2
+     864  0.0000071  0.00000024 120.93  5898.2   70962   0.2
+     875  0.0000114  0.00000025  77.01  3763.2   44622   0.0
+     882  0.0000088  0.00000024 100.07  4895.5   57520   0.0
+     896  0.0000064  0.00000023 140.21  6875.4   79337   0.1
+     900  0.0000078  0.00000023 115.27  5656.0   64935   0.2
+     945  0.0000122  0.00000024  77.64  3836.9   41652   0.1
+     960  0.0000073  0.00000024 131.61  6519.2   69506   0.3
+     972  0.0000103  0.00000024  94.08  4668.6   49072   0.1
+     980  0.0000089  0.00000023 109.95  5462.9   56884   0.1
+    1000  0.0000097  0.00000024 103.30  5147.2   52372   0.1
+    1008  0.0000085  0.00000023 118.42  5907.6   59564   0.2
+    1024  0.0000062  0.00000022 166.42  8321.0   82399   0.0
+    1029  0.0000169  0.00000026  61.00  3052.4   30058   0.0
+    1050  0.0000095  0.00000024 111.07  5573.6   53630   0.1
+    1080  0.0000095  0.00000023 114.00  5743.9   53519   0.3
+    1120  0.0000105  0.00000023 106.32  5384.9   48129   0.2
+    1125  0.0000150  0.00000026  74.83  3792.4   33724   0.1
+    1134  0.0000121  0.00000025  93.70  4754.1   41894   0.1
+    1152  0.0000095  0.00000024 121.83  6194.9   53617   0.3
+    1176  0.0000111  0.00000024 105.85  5398.1   45634   0.1
+    1200  0.0000095  0.00000024 125.75  6431.3   53129   0.3
+    1215  0.0000161  0.00000025  75.67  3877.1   31577   0.1
+    1225  0.0000174  0.00000026  70.49  3615.8   29176   0.0
+    1250  0.0000149  0.00000027  83.88  4314.8   34023   0.0
+    1260  0.0000113  0.00000025 111.18  5725.2   44737   0.2
+    1280  0.0000089  0.00000022 144.22  7443.3   57126   0.2
+    1296  0.0000120  0.00000023 107.71  5568.3   42134   0.2
+    1323  0.0000204  0.00000026  64.88  3363.8   24863   0.0
+    1344  0.0000110  0.00000026 122.35  6357.6   46155   0.2
+    1350  0.0000117  0.00000024 115.22  5990.5   43269   0.2
+    1372  0.0000159  0.00000024  86.29  4496.6   31888   0.0
+    1400  0.0000129  0.00000024 108.17  5652.7   39175   0.2
+    1440  0.0000109  0.00000025 132.63  6957.5   46695   0.4
+    1458  0.0000174  0.00000026  83.93  4410.3   29185   0.1
+    1470  0.0000141  0.00000026 104.57  5501.4   36068   0.1
+    1500  0.0000135  0.00000024 110.72  5840.9   37424   0.2
+    1512  0.0000144  0.00000025 104.89  5539.6   35173   0.2
+    1536  0.0000121  0.00000023 126.98  6720.5   41914   0.2
+    1568  0.0000143  0.00000025 109.51  5812.3   35411   0.1
+    1575  0.0000229  0.00000026  68.67  3646.9   22106   0.1
+    1600  0.0000132  0.00000023 120.78  6427.7   38272   0.3
+    1620  0.0000161  0.00000024 100.89  5378.4   31576   0.3
+    1680  0.0000135  0.00000025 124.52  6670.8   37579   0.3
+    1701  0.0000272  0.00000027  62.52  3355.0   18635   0.1
+    1715  0.0000268  0.00000027  63.96  3436.0   18908   0.0
+    1728  0.0000147  0.00000024 117.91  6340.7   34596   0.4
+    1750  0.0000183  0.00000027  95.88  5164.6   27778   0.1
+    1764  0.0000171  0.00000026 103.10  5559.5   29631   0.1
+    1792  0.0000141  0.00000025 127.25  6876.3   36002   0.2
+    1800  0.0000154  0.00000024 116.90  6320.5   32926   0.4
+    1875  0.0000258  0.00000027  72.75  3955.1   19673   0.1
+    1890  0.0000196  0.00000026  96.45  5249.0   25874   0.2
+    1920  0.0000156  0.00000024 122.71  6692.2   32404   0.4
+    1944  0.0000211  0.00000027  91.93  5021.6   23976   0.2
+    1960  0.0000194  0.00000024 100.83  5513.9   26083   0.1
+    2000  0.0000184  0.00000026 108.89  5970.1   27603   0.2
+    2016  0.0000191  0.00000025 105.55  5793.4   26545   0.4
+    2025  0.0000284  0.00000026  71.29  3915.1   17849   0.1
+    2048  0.0000129  0.00000024 158.66  8726.3   39279   0.0
+    2058  0.0000236  0.00000027  87.27  4802.9   21500   0.0
+    2100  0.0000193  0.00000025 108.66  5995.9   26234   0.3
+    2160  0.0000188  0.00000024 114.92  6364.8   26976   0.5
+    2187  0.0000377  0.00000027  57.94  3214.1   13432   0.0
+    2205  0.0000318  0.00000027  69.36  3851.8   15948   0.1
+    2240  0.0000209  0.00000024 106.94  5950.8   24204   0.3
+    2250  0.0000232  0.00000026  96.98  5400.0   21854   0.2
+    2268  0.0000260  0.00000027  87.26  4863.7   19507   0.2
+    2304  0.0000188  0.00000025 122.85  6861.0   27034   0.5
+    2352  0.0000246  0.00000026  95.53  5349.6   20593   0.2
+    2400  0.0000207  0.00000024 115.74  6498.3   24451   0.5
+    2401  0.0000407  0.00000027  58.94  3309.6   12447   0.0
+    2430  0.0000271  0.00000026  89.58  5037.6   18691   0.2
+    2450  0.0000296  0.00000027  82.67  4653.9   17109   0.1
+    2500  0.0000286  0.00000028  87.41  4933.2   17726   0.1
+    2520  0.0000243  0.00000025 103.83  5865.8   20889   0.4
+    2560  0.0000217  0.00000024 118.13  6687.5   23396   0.4
+    2592  0.0000255  0.00000026 101.69  5765.8   19891   0.4
+    2625  0.0000398  0.00000028  65.98  3747.0   12743   0.1
+    2646  0.0000331  0.00000028  79.92  4543.3   15314   0.1
+    2688  0.0000241  0.00000027 111.51  6351.9   21032   0.4
+    2700  0.0000255  0.00000026 105.77  6028.1   19861   0.4
+    2744  0.0000308  0.00000026  89.07  5086.6   16457   0.1
+    2800  0.0000276  0.00000025 101.39  5805.2   18359   0.3
+    2835  0.0000446  0.00000027  63.59  3646.5   11372   0.1
+    2880  0.0000245  0.00000024 117.36  6743.5   20660   0.8
+    2916  0.0000321  0.00000028  90.73  5221.5   15776   0.2
+    2940  0.0000328  0.00000027  89.62  5162.8   15455   0.2
+    3000  0.0000285  0.00000026 105.17  6074.2   17775   0.4
+    3024  0.0000321  0.00000026  94.27  5449.6   15805   0.4
+    3072  0.0000271  0.00000026 113.19  6556.5   18681   0.4
+    3087  0.0000514  0.00000028  60.10  3483.2    9870   0.0
+    3125  0.0000509  0.00000030  61.43  3565.7    9966   0.0
+    3136  0.0000324  0.00000027  96.80  5621.7   15650   0.2
+    3150  0.0000328  0.00000026  95.95  5575.2   15443   0.3
+    3200  0.0000277  0.00000024 115.73  6737.5   18335   0.5
+    3240  0.0000338  0.00000025  95.81  5586.4   14992   0.5
+    3360  0.0000322  0.00000026 104.28  6107.5   15734   0.6
+    3375  0.0000511  0.00000028  66.05  3870.8    9922   0.1
+    3402  0.0000425  0.00000028  80.08  4697.8   11935   0.2
+    3430  0.0000405  0.00000027  84.69  4972.9   12519   0.1
+    3456  0.0000353  0.00000026  97.91  5754.3   14363   0.6
+    3500  0.0000399  0.00000028  87.77  5166.7   12714   0.2
+    3528  0.0000382  0.00000027  92.34  5441.2   13271   0.3
+    3584  0.0000334  0.00000025 107.29  6334.0   15178   0.3
+    3600  0.0000339  0.00000025 106.06  6264.7   14937   0.8
+    3645  0.0000583  0.00000028  62.48  3696.5    8691   0.1
+    3675  0.0000574  0.00000028  63.99  3789.4    8828   0.1
+    3750  0.0000414  0.00000028  90.56  5376.2   12244   0.2
+    3780  0.0000426  0.00000026  88.65  5267.5   11890   0.5
+    3840  0.0000333  0.00000025 115.29  6863.7   15222   0.7
+    3888  0.0000428  0.00000027  90.75  5411.2   11835   0.5
+    3920  0.0000422  0.00000026  92.81  5539.1   12004   0.3
+    3969  0.0000713  0.00000029  55.64  3326.0    7108   0.1
+    4000  0.0000382  0.00000026 104.77  6268.4   13280   0.5
+    4032  0.0000427  0.00000028  94.43  5655.0   11874   0.7
+    4050  0.0000444  0.00000027  91.20  5464.7   11417   0.4
+    4096  0.0000328  0.00000027 124.70  7481.8   15434   0.0
+    4116  0.0000492  0.00000028  83.66  5022.6   10305   0.1
+    4200  0.0000401  0.00000027 104.83  6309.0   12655   0.6
+    4320  0.0000428  0.00000026 101.04  6101.1   11858   0.9
+    4374  0.0000585  0.00000029  74.78  4522.4    8668   0.1
+    4375  0.0000724  0.00000030  60.45  3655.7    7005   0.1
+    4410  0.0000505  0.00000027  87.33  5286.3   10040   0.2
+    4480  0.0000450  0.00000026  99.53  6036.2   11264   0.6
+    4500  0.0000464  0.00000027  96.97  5883.8   10925   0.6
+    4536  0.0000511  0.00000028  88.73  5389.1    9918   0.5
+    4608  0.0000432  0.00000027 106.66  6490.0   11735   0.7
+    4704  0.0000510  0.00000027  92.27  5628.3    9945   0.4
+    4725  0.0000743  0.00000028  63.61  3882.4    6826   0.2
+    4800  0.0000443  0.00000025 108.34  6624.1   11443   0.9
+    4802  0.0000622  0.00000028  77.17  4718.9    8148   0.0
+    4860  0.0000543  0.00000028  89.58  5485.2    9345   0.5
+    4900  0.0000589  0.00000028  83.20  5099.7    8609   0.3
+    5000  0.0000567  0.00000029  88.12  5413.7    8935   0.4
+    5040  0.0000559  0.00000027  90.09  5540.4    9063   0.9
+    5103  0.0000908  0.00000029  56.22  3462.5    5586   0.1
+    5120  0.0000433  0.00000025 118.26  7285.8   11710   0.6
+    5145  0.0000854  0.00000029  60.27  3715.3    5939   0.1
+    5184  0.0000528  0.00000027  98.26  6062.8    9610   0.8
+    5250  0.0000593  0.00000028  88.53  5470.1    8549   0.3
+    5292  0.0000639  0.00000029  82.81  5121.8    7934   0.3
+    5376  0.0000555  0.00000027  96.83  5999.6    9132   0.7
+    5400  0.0000584  0.00000027  92.48  5733.2    8683   0.9
+    5488  0.0000658  0.00000028  83.36  5177.6    7701   0.2
+    5600  0.0000589  0.00000027  95.02  5915.7    8603   0.7
+    5625  0.0001000  0.00000030  56.23  3502.3    5068   0.2
+    5670  0.0000688  0.00000028  82.42  5138.8    7370   0.4
+    5760  0.0000579  0.00000027  99.49  6213.9    8757   1.3
+    5832  0.0000688  0.00000028  84.79  5303.4    7371   0.5
+    5880  0.0000716  0.00000027  82.10  5140.1    7079   0.5
+    6000  0.0000572  0.00000027 104.91  6583.5    8865   0.9
+    6048  0.0000671  0.00000027  90.09  5658.7    7552   0.9
+    6075  0.0001024  0.00000029  59.35  3729.6    4953   0.2
+    6125  0.0000971  0.00000029  63.05  3965.9    5219   0.1
+    6144  0.0000530  0.00000027 115.85  7290.1    9560   0.7
+    6174  0.0000834  0.00000029  74.00  4659.2    6077   0.1
+    6250  0.0000907  0.00000031  68.93  4346.2    5592   0.2
+    6272  0.0000682  0.00000028  92.03  5804.7    7439   0.5
+    6300  0.0000716  0.00000027  87.99  5552.9    7081   0.8
+    6400  0.0000610  0.00000025 104.83  6627.4    8305   0.8
+    6480  0.0000693  0.00000027  93.55  5922.3    7319   1.1
+    6561  0.0001160  0.00000030  56.54  3584.3    4369   0.1
+    6615  0.0001087  0.00000029  60.84  3860.6    4663   0.2
+    6720  0.0000680  0.00000027  98.84  6283.4    7457   1.2
+    6750  0.0000789  0.00000028  85.53  5439.9    6424   0.5
+    6804  0.0000858  0.00000029  79.31  5048.9    5910   0.5
+    6860  0.0000876  0.00000028  78.27  4987.6    5785   0.2
+    6912  0.0000633  0.00000028 109.22  6965.5    8011   1.1
+    7000  0.0000849  0.00000029  82.46  5266.1    5972   0.6
+    7056  0.0000832  0.00000028  84.85  5424.0    6097   0.7
+    7168  0.0000721  0.00000028  99.47  6370.0    7036   0.5
+    7200  0.0000729  0.00000027  98.75  6327.1    6954   1.5
+    7203  0.0001417  0.00000031  50.85  3258.0    3579   0.0
+    7290  0.0000933  0.00000029  78.17  5015.5    5437   0.4
+    7350  0.0000874  0.00000028  84.11  5401.1    5802   0.4
+    7500  0.0000911  0.00000029  82.32  5298.5    5565   0.6
+    7560  0.0000880  0.00000028  85.92  5534.7    5762   1.1
+    7680  0.0000727  0.00000026 105.70  6821.6    6978   1.3
+    7776  0.0000912  0.00000028  85.23  5507.8    5557   0.9
+    7840  0.0000884  0.00000027  88.65  5734.3    5733   0.6
+    7875  0.0001371  0.00000030  57.45  3718.1    3699   0.3
+    7938  0.0001107  0.00000030  71.69  4643.8    4579   0.2
+    8000  0.0000790  0.00000027 101.32  6568.3    6421   0.9
+    8064  0.0000899  0.00000029  89.65  5817.4    5637   1.2
+    8100  0.0000940  0.00000028  86.19  5595.4    5395   1.0
+    8192  0.0000708  0.00000026 115.70  7520.6    7161   0.0
+    8232  0.0001013  0.00000029  81.26  5284.9    5005   0.3
+    8400  0.0000906  0.00000027  92.72  6043.4    5596   1.3
+    8505  0.0001480  0.00000029  57.47  3751.2    3426   0.3
+    8575  0.0001531  0.00000030  56.00  3658.5    3311   0.1
+    8640  0.0000854  0.00000026 101.14  6613.1    5935   1.8
+    8748  0.0001209  0.00000029  72.37  4738.1    4194   0.4
+    8750  0.0001166  0.00000030  75.06  4914.5    4349   0.3
+    8820  0.0001036  0.00000028  85.12  5578.2    4893   0.7
+    8960  0.0000907  0.00000027  98.77  6484.0    5589   1.1
+    9000  0.0000971  0.00000028  92.71  6089.2    5223   1.3
+    9072  0.0001067  0.00000029  84.99  5587.0    4750   1.1
+    9216  0.0000911  0.00000028 101.14  6659.8    5564   1.2
+    9261  0.0001883  0.00000031  49.17  3239.8    2692   0.1
+    9375  0.0001636  0.00000031  57.32  3781.6    3100   0.2
+    9408  0.0001097  0.00000029  85.78  5661.1    4623   0.9
+    9450  0.0001135  0.00000028  83.24  5496.6    4466   0.8
+    9600  0.0001036  0.00000026  92.71  6132.0    4896   1.7
+    9604  0.0001322  0.00000030  72.64  4804.7    3834   0.1
+    9720  0.0001090  0.00000028  89.17  5906.4    4651   1.2
+    9800  0.0001150  0.00000029  85.24  5650.8    4410   0.7
+   10000  0.0001157  0.00000029  86.41  5741.1    4381   0.8
+   10080  0.0001141  0.00000027  88.32  5872.7    4442   1.8
+   10125  0.0001838  0.00000031  55.10  3665.7    2759   0.4
+   10206  0.0001506  0.00000031  67.78  4512.9    3367   0.4
+   10240  0.0001002  0.00000026 102.19  6807.1    5060   1.0
+   10290  0.0001228  0.00000029  83.81  5585.4    4129   0.3
+   10368  0.0001172  0.00000029  88.45  5899.3    4325   1.6
+   10500  0.0001273  0.00000029  82.47  5508.2    3982   1.0
+   10584  0.0001373  0.00000029  77.07  5152.0    3692   0.7
+   10752  0.0001129  0.00000029  95.22  6376.2    4490   1.3
+   10800  0.0001133  0.00000028  95.32  6385.6    4475   1.9
+   10935  0.0001960  0.00000030  55.79  3742.9    2587   0.2
+   10976  0.0001338  0.00000030  82.05  5506.2    3790   0.4
+   11025  0.0002038  0.00000030  54.10  3632.2    2488   0.3
+   11200  0.0001160  0.00000027  96.54  6492.8    4370   1.4
+   11250  0.0001358  0.00000030  82.85  5574.6    3734   0.7
+   11340  0.0001359  0.00000029  83.43  5618.3    3730   1.2
+   11520  0.0001171  0.00000028  98.42  6639.1    4331   2.3
+   11664  0.0001419  0.00000029  82.23  5554.2    3574   1.1
+   11760  0.0001343  0.00000028  87.57  5920.4    3775   1.2
+   11907  0.0002425  0.00000032  49.11  3324.3    2091   0.2
+   12000  0.0001319  0.00000028  91.00  6165.8    3845   1.8
+   12005  0.0002249  0.00000031  53.37  3616.1    2254   0.1
+   12096  0.0001445  0.00000028  83.72  5677.1    3509   1.8
+   12150  0.0001611  0.00000029  75.42  5116.6    3147   0.8
+   12250  0.0001721  0.00000030  71.18  4833.4    2946   0.4
+   12288  0.0001231  0.00000030  99.83  6781.1    4119   1.2
+   12348  0.0001642  0.00000031  75.19  5109.9    3087   0.5
+   12500  0.0001733  0.00000032  72.14  4909.1    2926   0.6
+   12544  0.0001542  0.00000029  81.35  5537.6    3288   0.9
+   12600  0.0001485  0.00000029  84.84  5778.2    3414   1.9
+   12800  0.0001319  0.00000027  97.02  6619.0    3843   1.5
+   12960  0.0001357  0.00000028  95.48  6522.3    3735   2.3
+   13122  0.0002021  0.00000031  64.94  4441.7    2509   0.3
+   13125  0.0002455  0.00000031  53.46  3656.4    2065   0.4
+   13230  0.0001777  0.00000030  74.45  5096.7    2853   0.6
+   13440  0.0001463  0.00000029  91.89  6300.8    3466   2.3
+   13500  0.0001546  0.00000029  87.34  5992.1    3280   1.5
+   13608  0.0001810  0.00000030  75.18  5161.7    2801   1.2
+   13720  0.0001694  0.00000029  81.00  5566.0    2993   0.6
+   13824  0.0001446  0.00000029  95.63  6577.0    3507   1.9
+   14000  0.0001811  0.00000029  77.29  5322.7    2799   1.4
+   14112  0.0001714  0.00000029  82.31  5673.3    2957   1.4
+   14175  0.0002602  0.00000031  54.49  3757.1    1949   0.6
+   14336  0.0001544  0.00000030  92.83  6408.9    3283   1.0
+   14400  0.0001522  0.00000028  94.58  6532.7    3330   3.0
+   14406  0.0002123  0.00000031  67.85  4686.9    2388   0.2
+   14580  0.0001862  0.00000029  78.31  5415.7    2723   1.3
+   14700  0.0001859  0.00000029  79.07  5472.9    2727   1.1
+   15000  0.0001819  0.00000030  82.48  5721.2    2788   1.5
+   15120  0.0001809  0.00000028  83.59  5803.2    2803   2.5
+   15309  0.0003149  0.00000032  48.62  3379.3    1610   0.3
+   15360  0.0001543  0.00000028  99.52  6920.4    3285   2.3
+   15435  0.0003032  0.00000031  50.90  3541.3    1672   0.3
+   15552  0.0001849  0.00000029  84.11  5855.8    2742   2.0
+   15625  0.0003060  0.00000034  51.06  3557.0    1657   0.1
+   15680  0.0001883  0.00000029  83.28  5803.4    2693   1.4
+   15750  0.0002002  0.00000030  78.69  5485.9    2533   1.2
+   15876  0.0002314  0.00000031  68.61  4787.1    2191   0.8
+   16000  0.0001781  0.00000028  89.84  6273.6    2847   1.9
+   16128  0.0001852  0.00000030  87.10  6087.1    2738   2.3
+   16200  0.0001931  0.00000028  83.91  5866.8    2626   2.4
+   16384  0.0001589  0.00000028 103.12  7218.1    3191   0.0
+   16464  0.0002205  0.00000030  74.68  5230.3    2300   0.8
+   16800  0.0001976  0.00000028  85.03  5967.4    2566   2.6
+   16807  0.0003405  0.00000032  49.36  3464.2    1489   0.0
+   16875  0.0003167  0.00000032  53.29  3741.4    1601   0.5
+   17010  0.0002316  0.00000030  73.44  5160.6    2189   1.0
+   17150  0.0002507  0.00000031  68.40  4810.4    2022   0.4
+   17280  0.0001873  0.00000029  92.27  6494.3    2707   3.3
+   17496  0.0002608  0.00000031  67.08  4727.6    1944   1.2
+   17500  0.0002381  0.00000031  73.48  5178.8    2129   0.9
+   17640  0.0002287  0.00000029  77.13  5440.4    2217   1.7
+   17920  0.0001879  0.00000028  95.39  6738.8    2699   2.0
+   18000  0.0002015  0.00000028  89.33  6313.5    2516   2.7
+   18144  0.0002326  0.00000030  78.02  5518.6    2180   2.2
+   18225  0.0003426  0.00000031  53.20  3765.0    1480   0.6
+   18375  0.0003465  0.00000031  53.02  3755.6    1463   0.4
+   18432  0.0001985  0.00000029  92.88  6580.4    2555   2.2
+   18522  0.0002727  0.00000032  67.91  4813.9    1859   0.4
+   18750  0.0002630  0.00000032  71.30  5060.3    1928   0.8
+   18816  0.0002192  0.00000030  85.84  6094.7    2313   1.7
+   18900  0.0002211  0.00000029  85.48  6071.7    2293   2.3
+   19200  0.0002152  0.00000028  89.22  6347.3    2356   3.1
+   19208  0.0002705  0.00000031  71.00  5051.7    1874   0.4
+   19440  0.0002414  0.00000029  80.52  5735.6    2100   2.7
+   19600  0.0002515  0.00000029  77.94  5556.4    2016   1.6
+   19683  0.0004197  0.00000032  46.90  3345.0    1208   0.2
+   19845  0.0003936  0.00000031  50.41  3598.6    1288   0.5
+   20000  0.0002395  0.00000030  83.52  5966.4    2117   1.8
+   20160  0.0002311  0.00000029  87.24  6237.5    2194   3.8
+   20250  0.0002452  0.00000030  82.59  5907.8    2068   1.3
+   20412  0.0003009  0.00000032  67.84  4856.4    1685   1.2
+   20480  0.0002183  0.00000028  93.80  6717.3    2322   1.8
+   20580  0.0002904  0.00000030  70.87  5077.2    1746   1.0
+   20736  0.0002400  0.00000029  86.41  6195.7    2113   2.8
+   21000  0.0002531  0.00000030  82.96  5955.8    2003   2.4
+   21168  0.0002619  0.00000031  80.83  5807.3    1936   1.8
+   21504  0.0002227  0.00000031  96.57  6949.6    2277   2.3
+   21600  0.0002597  0.00000028  83.16  5986.9    1952   4.0
+   21609  0.0004584  0.00000032  47.14  3393.9    1106   0.2
+   21870  0.0003111  0.00000031  70.30  5067.8    1630   1.0
+   21875  0.0004359  0.00000033  50.18  3617.2    1163   0.3
+   21952  0.0002853  0.00000032  76.93  5547.6    1777   1.0
+   22050  0.0002864  0.00000030  76.99  5553.9    1770   1.3
+   22400  0.0002685  0.00000029  83.42  6027.3    1888   2.6
+   22500  0.0002609  0.00000031  86.23  6233.4    1943   2.1
+   22680  0.0002906  0.00000030  78.06  5647.1    1745   3.0
+   23040  0.0002484  0.00000029  92.75  6720.4    2041   4.1
+   23328  0.0003207  0.00000031  72.74  5277.3    1581   2.4
+   23520  0.0002970  0.00000030  79.19  5749.9    1707   2.5
+   23625  0.0004593  0.00000032  51.44  3736.7    1104   1.0
+   23814  0.0003604  0.00000032  66.08  4804.2    1407   0.7
+   24000  0.0002823  0.00000029  85.01  6184.8    1796   3.6
+   24010  0.0003693  0.00000031  65.01  4730.3    1373   0.4
+   24192  0.0003004  0.00000030  80.54  5864.3    1688   3.5
+   24300  0.0003097  0.00000030  78.47  5715.7    1637   2.5
+   24500  0.0003410  0.00000031  71.85  5238.4    1487   1.2
+   24576  0.0002509  0.00000030  97.96  7143.8    2021   2.1
+   24696  0.0003501  0.00000031  70.53  5146.1    1448   1.2
+   25000  0.0003461  0.00000033  72.24  5276.7    1465   1.5
+   25088  0.0002975  0.00000031  84.32  6161.3    1704   1.8
+   25200  0.0003093  0.00000029  81.46  5955.3    1639   4.4
+   25515  0.0005178  0.00000032  49.27  3606.5     979   0.8
+   25600  0.0002707  0.00000028  94.57  6924.3    1873   2.8
+   25725  0.0005221  0.00000031  49.27  3609.4     971   0.5
+   25920  0.0002946  0.00000028  87.97  6449.1    1721   4.7
+   26244  0.0004046  0.00000032  64.86  4760.4    1253   1.2
+   26250  0.0003909  0.00000032  67.15  4928.8    1297   1.4
+   26460  0.0003701  0.00000031  71.50  5252.0    1370   2.0
+   26880  0.0002958  0.00000029  90.86  6684.5    1714   4.5
+   27000  0.0003578  0.00000029  75.47  5554.7    1417   3.8
+   27216  0.0003817  0.00000031  71.29  5251.5    1328   2.9
+   27440  0.0003900  0.00000031  70.36  5186.7    1300   1.5
+   27648  0.0003262  0.00000030  84.75  6252.4    1554   3.6
+   27783  0.0006450  0.00000032  43.08  3179.4     786   0.3
+   28000  0.0003593  0.00000030  77.93  5756.5    1411   3.0
+   28125  0.0005578  0.00000034  50.42  3725.7     909   0.8
+   28224  0.0003692  0.00000030  76.44  5650.6    1373   3.3
+   28350  0.0003719  0.00000030  76.22  5637.0    1363   2.2
+   28672  0.0003376  0.00000031  84.94  6288.6    1502   2.0
+   28800  0.0003568  0.00000029  80.73  5979.3    1421   5.9
+   28812  0.0004552  0.00000032  63.30  4688.5    1114   0.7
+   29160  0.0004109  0.00000030  70.96  5262.4    1234   3.4
+   29400  0.0003829  0.00000030  76.77  5697.9    1324   2.9
+   30000  0.0003690  0.00000031  81.30  6045.6    1374   3.6
+   30240  0.0004076  0.00000030  74.20  5521.7    1244   5.6
+   30375  0.0006305  0.00000032  48.17  3586.6     804   1.0
+   30618  0.0005015  0.00000032  61.05  4549.1    1011   1.1
+   30625  0.0006244  0.00000033  49.05  3654.6     812   0.4
+   30720  0.0003567  0.00000030  86.12  6418.8    1421   4.3
+   30870  0.0004375  0.00000031  70.57  5262.1    1159   1.2
+   31104  0.0004232  0.00000030  73.50  5485.0    1198   4.0
+   31250  0.0004945  0.00000035  63.19  4717.7    1025   0.8
+   31360  0.0003864  0.00000030  81.15  6060.5    1312   2.8
+   31500  0.0004079  0.00000030  77.22  5769.9    1243   3.6
+   31752  0.0004560  0.00000032  69.63  5206.5    1112   2.2
+   32000  0.0003844  0.00000029  83.26  6230.1    1319   3.5
+   32256  0.0003853  0.00000031  83.72  6269.7    1316   4.5
+   32400  0.0003998  0.00000029  81.04  6071.3    1268   5.3
+   32768  0.0003706  0.00000029  88.41  6630.9    1368   0.0
+   32805  0.0006688  0.00000032  49.05  3679.1     758   0.7
+   32928  0.0004467  0.00000031  73.71  5531.0    1135   1.8
+   33075  0.0006459  0.00000032  51.21  3844.1     785   1.1
+   33600  0.0004089  0.00000029  82.17  6177.9    1240   5.7
+   33614  0.0004995  0.00000032  67.29  5059.3    1015   0.2
+   33750  0.0004639  0.00000031  72.75  5471.5    1093   2.1
+   34020  0.0004775  0.00000031  71.24  5362.3    1062   3.4
+   34300  0.0005031  0.00000031  68.18  5135.6    1008   1.4
+   34560  0.0004030  0.00000030  85.75  6464.1    1258   6.4
+   34992  0.0004917  0.00000031  71.16  5370.9    1031   2.9
+   35000  0.0004941  0.00000032  70.83  5346.2    1026   2.4
+   35280  0.0005085  0.00000030  69.37  5240.0     997   4.3
+   35721  0.0007456  0.00000033  47.91  3622.9     680   0.5
+   35840  0.0004371  0.00000029  82.00  6202.8    1160   3.9
+   36000  0.0004355  0.00000029  82.66  6255.4    1164   6.1
+   36015  0.0007203  0.00000032  50.00  3784.2     704   0.4
+   36288  0.0005101  0.00000031  71.13  5387.4     994   5.0
+   36450  0.0005016  0.00000031  72.67  5506.3    1011   2.4
+   36750  0.0005452  0.00000031  67.41  5111.4     930   1.6
+   36864  0.0004394  0.00000030  83.90  6364.1    1154   4.1
+   37044  0.0005728  0.00000032  64.67  4907.3     885   1.4
+   37500  0.0005464  0.00000033  68.64  5214.5     928   2.6
+   37632  0.0004577  0.00000031  82.23  6249.2    1108   3.5
+   37800  0.0005014  0.00000030  75.38  5731.4    1011   5.7
+   38400  0.0004389  0.00000029  87.49  6661.6    1155   6.1
+   38416  0.0005232  0.00000032  73.43  5591.4     969   1.0
+   38880  0.0005365  0.00000030  72.47  5525.0     945   6.1
+   39200  0.0004942  0.00000030  79.32  6051.2    1026   3.7
+   39366  0.0006361  0.00000033  61.89  4723.5     797   1.0
+   39375  0.0008380  0.00000034  46.98  3586.1     605   1.4
+   39690  0.0005808  0.00000032  68.34  5219.9     873   1.9
+   40000  0.0004824  0.00000031  82.92  6338.0    1051   3.9
+   40320  0.0004893  0.00000031  82.40  6303.0    1036   7.8
+   40500  0.0005019  0.00000030  80.69  6174.8    1010   4.3
+   40824  0.0006283  0.00000032  64.98  4976.4     807   3.2
+   40960  0.0004774  0.00000029  85.79  6572.7    1062   3.4
+   41160  0.0005762  0.00000031  71.44  5475.4     880   2.6
+   41472  0.0004856  0.00000031  85.41  6550.5    1044   5.4
+   42000  0.0005458  0.00000030  76.95  5908.8     929   5.9
+   42336  0.0005665  0.00000031  74.73  5743.0     895   4.1
+   42525  0.0008098  0.00000032  52.51  4037.0     626   1.7
+   42875  0.0008942  0.00000032  47.95  3689.0     567   0.5
+   43008  0.0004861  0.00000031  88.48  6809.8    1043   4.5
+   43200  0.0005348  0.00000029  80.78  6219.8     948   8.6
+   43218  0.0007338  0.00000033  58.89  4534.6     691   0.8
+   43740  0.0006716  0.00000031  65.13  5020.1     755   3.6
+   43750  0.0007500  0.00000034  58.33  4496.5     676   1.4
+   43904  0.0005493  0.00000032  79.93  6163.8     923   2.2
+   44100  0.0006117  0.00000031  72.10  5561.7     829   4.2
+   44800  0.0005800  0.00000029  77.24  5966.9     874   5.6
+   45000  0.0006759  0.00000032  66.57  5145.3     750   5.5
+   45360  0.0007080  0.00000031  64.06  4955.1     716   7.4
+   45927  0.0010453  0.00000033  43.94  3402.3     485   0.8
+   46080  0.0005216  0.00000029  88.34  6842.7     972   8.0
+   46305  0.0010741  0.00000033  43.11  3340.9     472   0.9
+   46656  0.0006044  0.00000031  77.20  5986.4     839   5.5
+   46875  0.0009772  0.00000035  47.97  3721.7     519   0.9
+   47040  0.0006680  0.00000031  70.42  5465.0     759   5.6
+   47250  0.0006094  0.00000031  77.54  6019.9     832   3.7
+   47628  0.0007151  0.00000033  66.60  5174.8     709   2.4
+   48000  0.0006029  0.00000029  79.62  6190.6     841   7.5
+   48020  0.0007885  0.00000032  60.90  4735.3     643   1.4
+   48384  0.0005915  0.00000032  81.80  6365.1     857   7.1
+   48600  0.0006458  0.00000031  75.25  5858.1     785   6.5
+   49000  0.0007072  0.00000032  69.28  5397.5     717   3.1
+   49152  0.0005677  0.00000031  86.58  6746.8     893   4.0
+   49392  0.0007489  0.00000032  65.95  5141.5     677   3.2
+   50000  0.0007041  0.00000033  71.01  5542.3     720   3.6
+   50176  0.0006198  0.00000032  80.95  6320.2     818   3.5
+   50400  0.0006064  0.00000030  83.11  6491.5     836   9.6
+   50421  0.0011419  0.00000034  44.15  3448.8     444   0.2
+   50625  0.0010741  0.00000034  47.13  3683.0     472   1.7
+   51030  0.0007578  0.00000032  67.34  5265.8     669   3.0
+   51200  0.0006243  0.00000029  82.01  6414.6     812   5.4
+   51450  0.0007824  0.00000032  65.76  5145.7     648   1.9
+   51840  0.0006993  0.00000031  74.14  5805.5     725   9.5
+   52488  0.0008060  0.00000032  65.12  5105.6     629   3.3
+   52500  0.0007567  0.00000032  69.38  5439.8     670   4.5
+   52920  0.0007294  0.00000031  72.55  5692.0     695   5.2
+   53760  0.0006510  0.00000030  82.58  6488.3     779   8.7
+   54000  0.0006815  0.00000030  79.24  6228.5     744   8.5
+   54432  0.0007523  0.00000032  72.36  5691.8     674   6.5
+   54675  0.0011471  0.00000033  47.66  3750.8     442   1.7
+   54880  0.0007730  0.00000031  71.00  5588.9     656   3.4
+   55125  0.0011392  0.00000033  48.39  3810.6     445   1.7
+   55296  0.0006388  0.00000031  86.56  6819.0     794   6.7
+   55566  0.0009219  0.00000033  60.28  4750.4     550   1.3
+   56000  0.0007498  0.00000030  74.68  5889.8     676   6.5
+   56250  0.0008311  0.00000033  67.68  5340.1     610   3.2
+   56448  0.0007959  0.00000032  70.93  5597.8     637   6.7
+   56700  0.0007886  0.00000031  71.90  5676.7     643   6.9
+   57344  0.0006788  0.00000031  84.48  6676.7     747   3.7
+   57600  0.0007122  0.00000030  80.88  6394.9     712  11.4
+   57624  0.0008817  0.00000032  65.36  5168.0     575   2.0
+   58320  0.0008366  0.00000031  69.71  5518.4     606   7.9
+   58800  0.0008639  0.00000031  68.07  5392.1     587   6.8
+   59049  0.0014244  0.00000034  41.46  3285.3     356   0.6
+   59535  0.0013306  0.00000033  44.74  3548.4     381   1.4
+   60000  0.0007799  0.00000031  76.93  6105.4     650   7.9
+   60025  0.0013480  0.00000033  44.53  3534.2     376   0.6
+   60480  0.0009601  0.00000030  62.99  5002.7     528  12.2
+   60750  0.0009463  0.00000031  64.20  5100.8     536   4.1
+   61236  0.0012580  0.00000033  48.68  3870.5     403   3.7
+   61250  0.0009904  0.00000034  61.84  4917.4     512   1.9
+   61440  0.0007811  0.00000029  78.65  6255.7     649   8.1
+   61740  0.0009388  0.00000032  65.76  5232.8     540   4.0
+   62208  0.0008482  0.00000031  73.34  5840.0     598   8.0
+   62500  0.0010562  0.00000036  59.18  4713.9     480   2.6
+   62720  0.0008801  0.00000031  71.26  5678.4     576   5.9
+   63000  0.0008959  0.00000031  70.32  5605.6     566   9.0
+   63504  0.0009529  0.00000033  66.64  5316.1     532   5.7
+   64000  0.0008595  0.00000030  74.47  5944.5     590   7.0
+   64512  0.0008009  0.00000031  80.55  6434.9     633   8.6
+   64800  0.0011291  0.00000031  57.39  4586.7     449  12.1
+   64827  0.0018707  0.00000034  34.65  2769.6     271   0.7
+   65536  0.0009882  0.00000030  66.32  5305.4     513   0.0
+   65610  0.0013702  0.00000032  47.89  3831.2     370   0.4
+   65625  0.0017073  0.00000033  38.44  3075.3     297   0.2
+   65856  0.0012248  0.00000032  53.77  4303.3     414   1.2
+   66150  0.0013271  0.00000033  49.84  3990.9     382   0.7
+   67200  0.0011762  0.00000030  57.13  4580.8     431   3.7
+   67228  0.0018106  0.00000034  37.13  2977.3     280   0.2
+   67500  0.0011069  0.00000032  60.98  4891.5     458   2.0
+   68040  0.0012520  0.00000032  54.34  4362.1     405   2.4
+   68600  0.0013705  0.00000032  50.06  4020.9     370   0.8
+   69120  0.0011266  0.00000031  61.35  4931.9     450   5.0
+   69984  0.0014655  0.00000033  47.75  3842.8     346   2.5
+   70000  0.0013168  0.00000033  53.16  4278.1     385   1.8
+   70560  0.0012517  0.00000031  56.37  4539.6     405   2.6
+   70875  0.0018992  0.00000033  37.32  3006.6     267   0.6
+   71442  0.0016517  0.00000033  43.25  3487.2     307   0.3
+   71680  0.0011574  0.00000030  61.93  4994.4     438   2.6
+   72000  0.0012611  0.00000031  57.09  4606.2     402   5.0
+   72030  0.0021946  0.00000033  32.82  2648.1     231  10.3
+   72576  0.0012933  0.00000032  56.12  4530.8     392   4.1
+   72900  0.0014784  0.00000033  49.31  3982.8     343   2.3
+   73500  0.0014244  0.00000032  51.60  4170.8     356   0.9
+   73728  0.0011519  0.00000031  64.01  5174.8     440   3.3
+   74088  0.0014958  0.00000033  49.53  4006.2     339   1.0
+   75000  0.0012368  0.00000033  60.64  4910.3     410   1.5
+   75264  0.0012939  0.00000033  58.17  4711.6     392   2.2
+   75600  0.0012963  0.00000031  58.32  4725.8     391   4.8
+   76545  0.0020442  0.00000033  37.45  3037.6     248   0.4
+   76800  0.0012305  0.00000030  62.41  5064.6     412   4.2
+   76832  0.0015651  0.00000033  49.09  3983.7     324   0.7
+   77175  0.0022047  0.00000033  35.00  2841.7     230   0.3
+   77760  0.0013519  0.00000031  57.52  4672.5     375   5.1
+   78125  0.0022632  0.00000036  34.52  2805.3     224   0.2
+   78400  0.0014568  0.00000032  53.82  4375.0     348   2.9
+   78732  0.0017248  0.00000033  45.65  3712.2     294   1.1
+   78750  0.0014402  0.00000033  54.68  4446.8     352   0.9
+   79380  0.0015595  0.00000032  50.90  4142.5     325   1.5
+   80000  0.0013776  0.00000031  58.07  4729.3     368   3.0
+   80640  0.0014086  0.00000031  57.25  4665.7     360   5.9
+   81000  0.0013927  0.00000032  58.16  4741.6     364   3.6
+   81648  0.0016517  0.00000033  49.43  4032.9     307   3.0
+   81920  0.0012614  0.00000030  64.94  5300.1     402   2.4
+   82320  0.0016622  0.00000032  49.53  4043.5     305   1.4
+   82944  0.0014324  0.00000031  57.90  4730.7     354   4.7
+   83349  0.0025475  0.00000035  32.72  2674.2     199   0.2
+   84000  0.0014958  0.00000031  56.16  4593.1     339   3.6
+   84035  0.0029481  0.00000034  28.50  2331.5     172   1.6
+   84375  0.0023255  0.00000034  36.28  2968.7     218   0.6
+   84672  0.0015551  0.00000033  54.45  4456.5     326   3.3
+   85050  0.0017918  0.00000033  47.47  3886.5     283   1.3
+   85750  0.0016731  0.00000033  51.25  4199.5     303   0.3
+   86016  0.0014491  0.00000032  59.36  4864.9     350   3.1
+   86400  0.0014694  0.00000030  58.80  4821.0     345   6.9
+   86436  0.0020442  0.00000034  42.28  3467.1     248   0.8
+   87480  0.0018306  0.00000033  47.79  3922.5     277   2.4
+   87500  0.0016098  0.00000034  54.36  4461.8     315   0.9
+   87808  0.0015992  0.00000033  54.91  4508.4     317   1.6
+   88200  0.0016149  0.00000032  54.62  4486.3     314   2.8
+   89600  0.0014698  0.00000032  60.96  5014.4     345   4.1
+   90000  0.0015842  0.00000032  56.81  4674.7     320   4.7
+   90720  0.0015266  0.00000032  59.43  4893.4     332   5.3
+   91125  0.0025348  0.00000033  35.95  2961.5     200   0.7
+   91854  0.0021306  0.00000034  43.11  3554.0     238   0.5
+   91875  0.0026830  0.00000033  34.24  2823.0     189   0.2
+   92160  0.0014406  0.00000031  63.97  5275.3     352   5.9
+   92610  0.0020525  0.00000033  45.12  3722.3     247   0.3
+   93312  0.0016787  0.00000032  55.59  4588.6     302   4.8
+   93750  0.0018707  0.00000035  50.12  4138.6     271   0.4
+   94080  0.0016847  0.00000031  55.85  4613.3     301   3.2
+   94500  0.0018435  0.00000033  51.26  4236.3     275   3.2
+   95256  0.0020038  0.00000034  47.54  3931.3     253   1.8
+   96000  0.0016676  0.00000031  57.57  4763.9     304   5.2
+   96040  0.0019803  0.00000033  48.50  4013.5     256   0.6
+   96768  0.0018106  0.00000031  53.45  4426.0     280   5.8
+   97200  0.0017302  0.00000032  56.18  4653.9     293   5.7
+   98000  0.0018851  0.00000032  51.99  4309.9     269   2.2
+   98304  0.0015224  0.00000032  64.57  5354.6     333   2.7
+   98415  0.0027256  0.00000033  36.11  2994.5     186   0.3
+   98784  0.0019350  0.00000033  51.05  4235.3     262   2.3
+   99225  0.0027559  0.00000033  36.00  2988.1     184   0.7
+  100000  0.0017914  0.00000034  55.82  4636.0     283   2.6
+  100352  0.0016513  0.00000032  60.77  5048.4     307   2.8
+  100800  0.0018368  0.00000031  54.88  4560.7     276   7.8
+  100842  0.0030920  0.00000035  32.61  2710.5     164   4.7
+  101250  0.0019424  0.00000033  52.13  4333.7     261   1.5
+  102060  0.0021946  0.00000032  46.50  3869.0     231   2.3
+  102400  0.0017127  0.00000030  59.79  4975.6     296   4.3
+  102900  0.0021573  0.00000033  47.70  3971.2     235   1.1
+  103680  0.0019140  0.00000031  54.17  4512.9     265   7.7
+  104976  0.0023362  0.00000034  44.93  3747.5     217   3.2
+  105000  0.0020360  0.00000033  51.57  4301.1     249   2.4
+  105840  0.0021946  0.00000032  48.23  4024.9     231   3.9
+  107163  0.0033573  0.00000035  31.92  2666.7     151   0.3
+  107520  0.0017546  0.00000032  61.28  5121.1     289   5.6
+  108000  0.0019574  0.00000031  55.18  4612.9     259   7.1
+  108045  0.0033142  0.00000034  32.60  2725.6     153   0.2
+  108864  0.0021941  0.00000033  49.62  4151.0     231   5.7
+  109350  0.0022338  0.00000034  48.95  4096.9     227   1.3
+  109375  0.0031884  0.00000035  34.30  2871.0     159   0.3
+  109760  0.0021758  0.00000032  50.45  4223.4     233   2.0
+  110250  0.0022235  0.00000033  49.58  4152.8     228   1.1
+  110592  0.0018570  0.00000032  59.55  4989.1     273   5.8
+  111132  0.0025740  0.00000035  43.17  3618.4     197   1.4
+  112000  0.0020782  0.00000032  53.89  4519.8     244   4.7
+  112500  0.0019574  0.00000034  57.48  4822.0     259   2.8
+  112896  0.0021573  0.00000032  52.33  4391.9     235   5.8
+  113400  0.0021852  0.00000032  51.90  4356.9     232   5.2
+  114688  0.0019654  0.00000032  58.35  4903.8     258   2.8
+  115200  0.0019498  0.00000031  59.08  4966.9     260   9.4
+  115248  0.0024373  0.00000034  47.29  3975.4     208   1.3
+  116640  0.0023690  0.00000033  49.24  4143.7     214   6.0
+  117600  0.0021578  0.00000032  54.50  4589.9     235   3.7
+  117649  0.0042247  0.00000035  27.85  2345.4     120   1.2
+  118098  0.0028171  0.00000035  41.92  3531.8     180   0.6
+  118125  0.0032927  0.00000033  35.87  3022.4     154   0.9
+  119070  0.0026542  0.00000033  44.86  3782.1     191   0.8
+  120000  0.0020692  0.00000032  57.99  4892.5     245   5.5
+  120050  0.0024491  0.00000033  49.02  4135.5     207   0.3
+  120960  0.0022235  0.00000031  54.40  4592.6     228   8.9
+  121500  0.0024256  0.00000033  50.09  4230.2     209   3.9
+  122472  0.0028009  0.00000034  43.73  3695.3     181   2.8
+  122500  0.0026138  0.00000034  46.87  3960.8     194   1.3
+  122880  0.0020365  0.00000031  60.34  5100.8     249   5.2
+  123480  0.0026132  0.00000033  47.25  3996.1     194   2.2
+  124416  0.0023807  0.00000032  52.26  4422.6     213   6.9
+  125000  0.0025481  0.00000036  49.06  4152.9     199   1.7
+  125440  0.0021306  0.00000032  58.88  4985.8     238   3.7
+  126000  0.0023913  0.00000032  52.69  4463.7     212   7.3
+  127008  0.0028009  0.00000033  45.35  3844.1     181   4.7
+  127575  0.0037833  0.00000034  33.72  2859.7     134   1.1
+  128000  0.0021946  0.00000031  58.32  4947.6     231   5.5
+  128625  0.0037276  0.00000032  34.51  2928.3     136   0.3
+  129024  0.0023368  0.00000032  55.21  4687.0     217   7.0
+  129600  0.0024497  0.00000032  52.91  4492.6     207  11.0
+  129654  0.0031488  0.00000035  41.18  3496.7     161   0.4
+  131072  0.0021391  0.00000032  61.28  5208.4     237   0.0
+  131220  0.0032919  0.00000033  39.86  3388.5     154   2.7
+  131250  0.0028164  0.00000035  46.60  3961.6     180   0.6
+  131712  0.0025481  0.00000032  51.69  4395.4     199   2.7
+  132300  0.0028969  0.00000033  45.67  3885.0     175   3.3
+  134400  0.0024616  0.00000032  54.60  4650.8     206   8.1
+  134456  0.0032497  0.00000034  41.37  3524.4     156   0.5
+  135000  0.0025222  0.00000033  53.53  4561.0     201   5.4
+  136080  0.0030912  0.00000032  44.02  3753.7     164   6.9
+  137200  0.0028322  0.00000033  48.44  4133.7     179   2.5
+  137781  0.0040894  0.00000035  33.69  2876.0     124   0.5
+  138240  0.0024985  0.00000031  55.33  4724.2     203   9.9
+  138915  0.0039299  0.00000034  35.35  3019.4     129   0.4
+  139968  0.0027403  0.00000033  51.08  4365.8     185   6.5
+  140000  0.0026542  0.00000033  52.75  4508.5     191   4.1
+  140625  0.0042612  0.00000036  33.00  2821.9     119   0.7
+  141120  0.0027256  0.00000032  51.78  4428.6     186   6.9
+  141750  0.0030364  0.00000034  46.68  3994.5     167   2.2
+  142884  0.0035452  0.00000035  40.30  3450.9     143   2.2
+  143360  0.0024736  0.00000031  57.96  4963.8     205   5.1
+  144000  0.0026966  0.00000032  53.40  4575.3     188  10.8
+  144060  0.0041564  0.00000034  34.66  2969.7     122   0.7
+  145152  0.0029304  0.00000032  49.53  4246.8     173   8.9
+  145800  0.0029304  0.00000033  49.75  4267.3     173   5.9
+  147000  0.0031102  0.00000033  47.26  4056.6     163   2.7
+  147456  0.0026132  0.00000033  56.43  4844.3     194   6.9
+  148176  0.0035205  0.00000034  42.09  3614.8     144   3.3
+  150000  0.0028976  0.00000034  51.77  4450.6     175   4.6
+  150528  0.0027262  0.00000033  55.21  4748.4     186   4.5
+  151200  0.0028178  0.00000033  53.66  4616.3     180  10.6
+  151263  0.0046510  0.00000036  32.52  2798.0     109   0.2
+  151875  0.0046087  0.00000034  32.95  2836.1     110   1.0
+  153090  0.0035460  0.00000034  43.17  3718.0     143   1.3
+  153125  0.0044073  0.00000035  34.74  2992.2     115   0.3
+  153600  0.0025469  0.00000031  60.31  5195.2     199   8.5
+  153664  0.0032086  0.00000033  47.89  4125.7     158   2.3
+  154350  0.0033581  0.00000034  45.96  3961.0     151   1.3
+  155520  0.0032086  0.00000032  48.47  4179.7     158  10.7
+  156250  0.0034740  0.00000038  44.98  3880.1     146   0.6
+  156800  0.0030183  0.00000033  51.95  4482.8     168   6.2
+  157464  0.0039299  0.00000035  40.07  3458.8     129   3.0
+  157500  0.0032919  0.00000034  47.84  4130.1     154   4.5
+  158760  0.0036220  0.00000033  43.83  3786.3     140   4.2
+  160000  0.0029136  0.00000032  54.92  4746.8     174   6.6
+  161280  0.0027262  0.00000032  59.16  5117.0     186  11.8
+  162000  0.0031693  0.00000033  51.12  4423.0     160   9.5
+  163296  0.0035954  0.00000034  45.42  3932.5     141   6.6
+  163840  0.0028976  0.00000031  56.54  4897.2     175   4.7
+  164025  0.0049726  0.00000034  32.99  2857.2     102   1.2
+  164640  0.0034254  0.00000033  48.06  4164.5     148   3.5
+  165375  0.0048282  0.00000034  34.25  2968.9     105   0.9
+  165888  0.0031884  0.00000032  52.03  4510.8     159   9.8
+  166698  0.0044470  0.00000036  37.49  3251.3     114   0.7
+  168000  0.0032927  0.00000032  51.02  4428.2     154   9.4
+  168070  0.0057609  0.00000034  29.17  2532.1      88   8.9
+  168750  0.0035710  0.00000035  47.26  4102.9     142   2.0
+  169344  0.0035954  0.00000034  47.10  4090.5     141   7.3
+  170100  0.0037285  0.00000034  45.62  3963.6     136   6.1
+  171500  0.0039918  0.00000034  42.96  3735.2     127   1.5
+  172032  0.0029481  0.00000033  58.35  5074.4     172   6.2
+  172800  0.0032715  0.00000032  52.82  4595.0     155  14.6
+  172872  0.0043330  0.00000033  39.90  3470.9     117   2.1
+  174960  0.0040235  0.00000032  43.48  3786.8     126   7.4
+  175000  0.0035205  0.00000035  49.71  4328.8     144   2.7
+  175616  0.0036472  0.00000033  48.15  4194.5     139   3.4
+  176400  0.0035963  0.00000033  49.05  4274.4     141   8.8
+  177147  0.0051730  0.00000036  34.24  2985.2      98   0.5
+  178605  0.0054525  0.00000035  32.76  2857.4      93   0.7
+  179200  0.0033135  0.00000033  54.08  4719.0     153   8.4
+  180000  0.0036220  0.00000033  49.70  4337.9     140  10.5
+  180075  0.0058949  0.00000034  30.55  2666.6      86   0.4
+  181440  0.0038997  0.00000033  46.53  4063.9     130  13.0
+  182250  0.0039606  0.00000034  46.02  4020.7     128   2.1
+  183708  0.0047379  0.00000035  38.77  3390.2     107   3.1
+  183750  0.0038708  0.00000035  47.47  4150.7     131   0.8
+  184320  0.0034479  0.00000032  53.46  4675.5     147  11.8
+  185220  0.0046929  0.00000034  39.47  3453.2     108   2.8
+  186624  0.0040547  0.00000033  46.03  4029.6     125  10.2
+  187500  0.0040244  0.00000036  46.59  4080.5     126   2.4
+  188160  0.0038690  0.00000032  48.63  4260.6     131   6.9
+  189000  0.0037842  0.00000034  49.94  4377.2     134   8.5
+  190512  0.0046544  0.00000035  40.93  3589.6     109   5.4
+  192000  0.0035443  0.00000032  54.17  4753.7     143  11.0
+  192080  0.0046076  0.00000034  41.69  3658.4     110   2.3
+  193536  0.0037842  0.00000033  51.14  4491.0     134  11.7
+  194400  0.0040894  0.00000033  47.54  4175.9     124  13.2
+  194481  0.0061094  0.00000036  31.83  2796.4      83   0.4
+  196000  0.0039908  0.00000033  49.11  4317.1     127   5.1
+  196608  0.0033805  0.00000033  58.16  5113.6     150   5.6
+  196830  0.0051743  0.00000035  38.04  3345.0      98   1.4
+  196875  0.0061809  0.00000035  31.85  2800.9      82   1.2
+  197568  0.0045253  0.00000034  43.66  3840.2     112   6.2
+  198450  0.0046098  0.00000035  43.05  3788.0     110   2.6
+  200000  0.0038108  0.00000034  52.48  4621.0     133   6.8
+  200704  0.0039928  0.00000034  50.27  4427.2     127   6.0
+  201600  0.0039309  0.00000032  51.29  4518.6     129  16.2
+  201684  0.0067611  0.00000036  29.83  2628.3      75   0.7
+  202500  0.0040874  0.00000034  49.54  4366.6     124   6.5
+  204120  0.0050206  0.00000033  40.66  3585.7     101   7.0
+  204800  0.0039309  0.00000031  52.10  4596.3     129   8.1
+  205800  0.0039908  0.00000034  51.57  4551.1     127   3.2
+  207360  0.0041544  0.00000032  49.91  4407.8     122  15.8
+  209952  0.0048758  0.00000035  43.06  3806.5     104   7.9
+  210000  0.0044094  0.00000034  47.63  4210.1     115   8.0
+  211680  0.0046929  0.00000033  45.11  3990.0     108   9.3
+  212625  0.0064156  0.00000034  33.14  2932.7      79   1.8
+  214326  0.0055091  0.00000036  38.90  3444.8      92   1.1
+  214375  0.0068524  0.00000034  31.28  2770.2      74   0.4
+  215040  0.0040244  0.00000033  53.43  4732.7     126  11.1
+  216000  0.0041544  0.00000033  51.99  4606.8     122  16.5
+  216090  0.0053377  0.00000035  40.48  3587.1      95   0.7
+  217728  0.0047838  0.00000035  45.51  4035.3     106  12.6
+  218700  0.0049255  0.00000035  44.40  3938.1     103   6.7
+  218750  0.0052821  0.00000037  41.41  3673.2      96   0.8
+  219520  0.0048293  0.00000034  45.46  4032.8     105   4.9
+  220500  0.0049207  0.00000034  44.81  3977.0     103   5.3
+  221184  0.0039908  0.00000033  55.42  4920.1     127  11.4
+  222264  0.0056975  0.00000035  39.01  3464.5      89   3.7
+  224000  0.0044481  0.00000033  50.36  4475.2     114  10.5
+  225000  0.0047391  0.00000035  47.48  4220.7     107   7.7
+  225792  0.0046952  0.00000034  48.09  4276.3     108  11.8
+  226800  0.0051220  0.00000034  44.28  3938.9      99  14.7
+  229376  0.0042994  0.00000033  53.35  4750.2     118   5.6
+  229635  0.0072475  0.00000035  31.68  2821.4      70   1.1
+  230400  0.0051743  0.00000031  44.53  3966.0      98  20.4
+  230496  0.0055696  0.00000035  41.38  3686.2      91   3.3
+  231525  0.0079193  0.00000034  29.24  2605.0      64   1.3
+  233280  0.0056342  0.00000033  41.40  3691.5      90  15.8
+  234375  0.0080450  0.00000037  29.13  2598.4      63   0.6
+  235200  0.0051718  0.00000034  45.48  4057.4      98  10.5
+  235298  0.0088961  0.00000035  26.45  2359.8      57   9.5
+  236196  0.0071420  0.00000036  33.07  2951.6      71   3.5
+  236250  0.0055091  0.00000034  42.88  3827.4      92   3.4
+  238140  0.0066689  0.00000034  35.71  3189.1      76   4.9
+  240000  0.0048270  0.00000033  49.72  4443.2     105  12.5
+  240100  0.0057623  0.00000035  41.67  3723.7      88   2.0
+  241920  0.0048293  0.00000033  50.09  4479.4     105  19.4
+  243000  0.0051743  0.00000034  46.96  4201.0      98  10.7
+  244944  0.0060338  0.00000035  40.60  3633.7      84   9.0
+  245000  0.0053351  0.00000035  45.92  4110.6      95   3.8
+  245760  0.0045275  0.00000032  54.28  4860.1     112  10.5
+  246960  0.0065855  0.00000034  37.50  3358.9      77   7.3
+  248832  0.0053945  0.00000034  46.13  4134.1      94  14.5
+  250000  0.0053919  0.00000037  46.37  4157.1      94   5.8
+  250047  0.0083128  0.00000036  30.08  2696.9      61   0.6
+  250880  0.0052251  0.00000033  48.01  4306.1      97   7.8
+  252000  0.0051743  0.00000033  48.70  4369.3      98  16.7
+  252105  0.0107269  0.00000033  23.50  2108.6      48   1.8
+  253125  0.0080489  0.00000035  31.45  2822.4      63   1.9
+  254016  0.0059656  0.00000035  42.58  3822.5      85  12.7
+  255150  0.0061839  0.00000035  41.26  3705.4      82   3.9
+  256000  0.0047838  0.00000032  53.51  4807.1     106  11.3
+  257250  0.0062602  0.00000035  41.09  3692.7      81   0.9
+  258048  0.0052276  0.00000033  49.36  4437.0      97  14.3
+  259200  0.0053377  0.00000033  48.56  4366.5      95  23.0
+  259308  0.0072440  0.00000036  35.80  3218.9      70   2.9
+  262144  0.0057595  0.00000033  45.52  4096.4      88   0.0
+  262440  0.0071420  0.00000034  36.75  3307.5      71   5.1
+  262500  0.0059656  0.00000036  44.00  3960.6      85   2.5
+  263424  0.0057623  0.00000035  45.72  4116.0      88   3.3
+  264600  0.0058963  0.00000034  44.88  4041.8      86   6.0
+  268800  0.0053945  0.00000032  49.83  4493.6      94   7.5
+  268912  0.0081787  0.00000035  32.88  2965.2      62   1.7
+  270000  0.0051196  0.00000034  52.74  4757.7      99   9.6
+  272160  0.0064979  0.00000034  41.88  3780.9      78   9.3
+  273375  0.0084473  0.00000035  32.36  2922.4      60   2.1
+  274400  0.0063385  0.00000034  43.29  3910.5      80   3.3
+  275562  0.0079231  0.00000036  34.78  3142.7      64   1.6
+  275625  0.0087428  0.00000034  31.53  2848.8      58   1.6
+  276480  0.0053377  0.00000033  51.80  4681.7      95  11.1
+  277830  0.0076830  0.00000035  36.16  3269.7      66   1.7
+  279936  0.0066753  0.00000035  41.94  3794.1      76   9.2
+  280000  0.0059656  0.00000034  46.94  4246.5      85   6.1
+  281250  0.0063385  0.00000036  44.37  4016.0      80   2.9
+  282240  0.0059628  0.00000034  47.33  4285.2      85   8.1
+  283500  0.0064979  0.00000034  43.63  3951.3      78   7.7
+  285768  0.0136983  0.00000036  20.86  1890.5      37   1.5
+  286720  0.0055144  0.00000032  51.99  4713.1      92   4.7
+  288000  0.0058963  0.00000033  48.84  4429.1      86  13.4
+  288120  0.0103486  0.00000036  27.84  2524.7      49  48.9
+  290304  0.0063385  0.00000035  45.80  4155.7      80  10.9
+  291600  0.0135562  0.00000032  21.51  1952.5      38   0.1
+  294000  0.0068491  0.00000034  42.93  3898.8      74   4.2
+  294912  0.0097468  0.00000034  30.26  2748.9      52   2.9
+  295245  0.0101416  0.00000035  29.11  2645.1      50   1.1
+  296352  0.0071454  0.00000035  41.47  3769.4      71   5.1
+  297675  0.0095629  0.00000035  31.13  2830.1      53   2.1
+  300000  0.0064218  0.00000035  46.72  4249.9      79   5.3
+  300125  0.0103486  0.00000034  29.00  2638.4      49   0.6
+  301056  0.0061094  0.00000034  49.28  4484.2      83   4.4
+  302400  0.0067611  0.00000033  44.73  4071.5      75  15.4
+  302526  0.0090506  0.00000036  33.43  3042.9      56   0.7
+  303750  0.0065823  0.00000035  46.15  4202.2      77   4.5
+  306180  0.0085946  0.00000035  35.62  3246.1      59   5.5
+  306250  0.0079231  0.00000037  38.65  3522.1      64   1.2
+  307200  0.0056948  0.00000032  53.94  4916.7      89   8.3
+  307328  0.0117926  0.00000035  26.06  2375.4      43   3.4
+  308700  0.0079231  0.00000035  38.96  3552.5      64   4.8
+  311040  0.0069463  0.00000034  44.78  4085.2      73  13.7
+  312500  0.0075647  0.00000039  41.31  3770.3      67   2.3
+  313600  0.0149069  0.00000031  21.04  1920.5      34   0.5
+  314928  0.0088919  0.00000035  35.42  3234.4      57   6.8
+  315000  0.0078012  0.00000035  40.38  3687.5      65   7.5
+  317520  0.0087386  0.00000033  36.34  3320.4      58   7.8
+  320000  0.0117021  0.00000032  27.35  2500.4      44   3.2
+  321489  0.0110235  0.00000037  29.16  2667.7      46   0.9
+  322560  0.0070428  0.00000033  45.80  4190.5      72  12.4
+  324000  0.0073490  0.00000033  44.09  4035.3      69  14.2
+  324135  0.0109552  0.00000035  29.59  2708.2      47   0.8
+  326592  0.0084513  0.00000035  38.64  3539.2      60  11.1
+  327680  0.0063385  0.00000033  51.70  4735.9      80   4.8
+  328050  0.0088961  0.00000036  36.88  3378.5      57   4.6
+  328125  0.0110235  0.00000036  29.77  2727.1      46   1.0
+  329280  0.0083047  0.00000034  39.65  3633.7      62   4.1
+  330750  0.0084554  0.00000035  39.12  3586.1      60   3.8
+  331776  0.0136983  0.00000034  24.22  2221.0      37   0.8
+  333396  0.0097468  0.00000036  34.21  3137.8      52   3.5
+  336000  0.0079231  0.00000034  42.41  3892.6      64   9.1
+  336140  0.0144880  0.00000036  23.20  2129.7      35  12.9
+  337500  0.0076793  0.00000035  43.95  4035.5      66   7.5
+  338688  0.0080489  0.00000035  42.08  3864.9      63   9.9
+  340200  0.0087229  0.00000035  39.00  3583.4      59  10.6
+  343000  0.0084409  0.00000035  40.64  3736.0      61   2.6
+  344064  0.0074535  0.00000034  46.16  4245.1      68   5.8
+  345600  0.0074535  0.00000033  46.37  4265.5      68  18.1
+  345744  0.0163574  0.00000036  21.14  1944.5      31   3.3
+  349920  0.0093617  0.00000034  37.38  3441.9      55  11.1
+  350000  0.0083128  0.00000036  42.10  3877.1      61   5.2
+  351232  0.0079269  0.00000035  44.31  4081.3      64   4.4
+  352800  0.0144810  0.00000032  24.36  2244.9      35   3.5
+  352947  0.0166016  0.00000037  21.26  1959.0      31  12.0
+  354294  0.0110288  0.00000037  32.12  2961.0      46   1.7
+  354375  0.0122652  0.00000035  28.89  2663.2      42   3.1
+  357210  0.0109552  0.00000035  32.61  3007.4      47   2.6
+  358400  0.0077975  0.00000032  45.96  4240.4      65   8.6
+  360000  0.0158463  0.00000034  22.72  2096.6      32   0.4
+  360150  0.0097515  0.00000036  36.93  3408.6      52   1.3
+  362880  0.0087428  0.00000034  41.51  3832.9      58  16.3
+  364500  0.0092196  0.00000035  39.54  3652.2      55   9.5
+  367416  0.0112684  0.00000035  32.61  3013.9      45   5.8
+  367500  0.0092241  0.00000035  39.84  3682.8      55   3.2
+  368640  0.0081748  0.00000033  45.09  4169.4      62  12.9
+  370440  0.0109552  0.00000034  33.81  3127.6      47   5.0
+  373248  0.0143094  0.00000034  26.08  2414.1      36   4.3
+  375000  0.0090289  0.00000037  41.53  3845.3      57   3.8
+  376320  0.0087428  0.00000034  43.04  3986.2      58   6.2
+  378000  0.0093859  0.00000034  40.27  3730.9      54  15.1
+  381024  0.0103486  0.00000035  36.82  3413.0      49   8.7
+  382725  0.0133378  0.00000035  28.69  2660.9      38   3.3
+  384000  0.0087270  0.00000033  44.00  4081.3      59  11.1
+  384160  0.0102930  0.00000035  37.32  3461.9      50   2.7
+  385875  0.0133378  0.00000034  28.93  2684.5      38   1.9
+  387072  0.0084409  0.00000034  45.86  4256.0      61  14.0
+  388800  0.0092196  0.00000034  42.17  3915.3      55  20.5
+  388962  0.0117869  0.00000036  33.00  3063.9      43   1.6
+  390625  0.0137049  0.00000040  28.50  2647.2      37   0.9
+  392000  0.0095675  0.00000034  40.97  3806.4      53   7.7
+  393216  0.0083128  0.00000034  47.30  4395.6      61   5.9
+  393660  0.0116966  0.00000035  33.66  3127.8      44   6.3
+  393750  0.0101514  0.00000036  38.79  3604.7      50   4.7
+  395136  0.0099475  0.00000035  39.72  3692.6      51   8.9
+  396900  0.0266884  0.00000033  14.87  1382.9      19   0.8
+  400000  0.0095629  0.00000035  41.83  3892.0      53   8.8
+  401408  0.0156028  0.00000034  25.73  2394.5      33   4.4
+  403200  0.0097103  0.00000033  41.52  3866.0      53  20.2
+  403368  0.0190701  0.00000036  21.15  1969.4      27  14.7
+  405000  0.0193594  0.00000035  20.92  1948.4      27   2.2
+  408240  0.0117869  0.00000033  34.64  3227.8      43  12.9
+  409600  0.0147042  0.00000031  27.86  2596.7      35   0.7
+  411600  0.0112684  0.00000035  36.53  3406.3      45   5.3
+  413343  0.0156102  0.00000037  26.48  2470.1      33   1.3
+  414720  0.0095675  0.00000033  43.35  4044.6      53  19.0
+  416745  0.0151439  0.00000036  27.52  2568.7      34   1.4
+  419904  0.0209082  0.00000034  20.08  1875.7      25   0.4
+  420000  0.0105693  0.00000035  39.74  3711.5      48   8.3
+  420175  0.0158386  0.00000035  26.53  2477.8      32   0.8
+  421875  0.0131961  0.00000037  31.97  2987.0      39   2.8
+  423360  0.0112684  0.00000034  37.57  3511.2      45  13.6
+  425250  0.0117926  0.00000036  36.06  3371.3      43   7.1
+  428652  0.0144810  0.00000036  29.60  2769.1      35   5.5
+  428750  0.0123619  0.00000036  34.68  3244.6      41   1.9
+  430080  0.0101367  0.00000034  42.43  3970.0      50   9.0
+  432000  0.0105642  0.00000034  40.89  3827.7      48  22.9
+  432180  0.0135498  0.00000035  31.90  2985.6      38   4.3
+  435456  0.0109552  0.00000035  39.75  3722.9      47  17.3
+  437400  0.0120733  0.00000035  36.23  3394.4      42  12.8
+  437500  0.0122535  0.00000038  35.70  3345.3      42   3.6
+  439040  0.0114366  0.00000034  38.39  3597.8      45   5.9
+  441000  0.0119742  0.00000035  36.83  3452.8      43   9.4
+  442368  0.0103486  0.00000034  42.75  4008.6      49  14.3
+  444528  0.0133442  0.00000036  33.31  3125.0      38   8.5
+  448000  0.0105642  0.00000033  42.41  3980.6      48  11.4
+  450000  0.0112630  0.00000035  39.95  3751.6      45  14.4
+  451584  0.0211182  0.00000035  21.38  2008.4      24   0.9
+  453600  0.0120733  0.00000035  37.57  3529.9      42  21.2
+  453789  0.0181100  0.00000038  25.06  2354.3      28   0.8
+  455625  0.0160828  0.00000035  28.33  2662.7      32   3.8
+  458752  0.0111933  0.00000034  40.98  3854.0      46   6.7
+  459270  0.0147042  0.00000036  31.23  2937.4      35   4.1
+  459375  0.0163574  0.00000036  28.08  2641.2      31   1.2
+  460800  0.0174855  0.00000032  26.35  2479.0      29   5.4
+  460992  0.0126770  0.00000035  36.36  3420.9      40   5.5
+  463050  0.0133378  0.00000036  34.72  3267.0      38   4.9
+  466560  0.0122593  0.00000035  38.06  3583.4      42  20.3
+  468750  0.0132086  0.00000039  35.49  3342.7      39   2.5
+  470400  0.0120675  0.00000035  38.98  3672.7      42  10.9
+  470596  0.0270996  0.00000036  17.37  1636.2      19   1.0
+  472392  0.0230380  0.00000036  20.50  1932.5      22   2.7
+  472500  0.0119742  0.00000035  39.46  3719.1      43  12.2
+  476280  0.0155954  0.00000034  30.54  2880.1      33   8.6
+  480000  0.0116966  0.00000034  41.04  3872.5      44  13.7
+  480200  0.0253418  0.00000035  18.95  1788.1      20   2.6
+  483840  0.0122593  0.00000034  39.47  3726.5      42  22.4
+  486000  0.0125584  0.00000034  38.70  3655.3      41  20.2
+  489888  0.0155954  0.00000036  31.41  2968.8      33  14.0
+  490000  0.0249023  0.00000035  19.68  1859.7      21   0.1
+  491520  0.0116966  0.00000033  42.02  3972.6      44   9.6
+  492075  0.0190701  0.00000036  25.80  2439.5      27   3.8
+  493920  0.0140856  0.00000035  35.07  3316.1      36  10.2
+  496125  0.0181013  0.00000035  27.41  2592.9      28   3.7
+  497664  0.0120733  0.00000034  41.22  3900.4      42  19.0
+  500000  0.0230380  0.00000037  21.70  2054.4      22   4.8
+  500094  0.0174855  0.00000037  28.60  2707.3      29   2.4
+  501760  0.0128662  0.00000034  39.00  3692.5      40   8.0
+  504000  0.0130021  0.00000034  38.76  3671.5      39  24.3
+  504210  0.0237482  0.00000036  21.23  2011.0      22  20.3
+  506250  0.0136983  0.00000036  36.96  3501.6      37   7.6
+  508032  0.0233931  0.00000035  21.72  2058.2      22   5.6
+  510300  0.0147112  0.00000036  34.69  3288.6      35  14.4
+  512000  0.0123619  0.00000033  41.42  3927.6      41  12.8
+  514500  0.0144810  0.00000036  35.53  3370.4      35   4.1
+  516096  0.0126709  0.00000036  40.73  3864.8      40  16.6
+  518400  0.0234042  0.00000031  22.15  2102.4      22   0.8
+  518616  0.0160904  0.00000036  32.23  3059.5      32   5.7
+  524288  0.0187807  0.00000034  27.92  2652.0      27   0.0
+  524880  0.0158463  0.00000034  33.12  3147.0      32  15.5
+  525000  0.0133442  0.00000036  39.34  3738.0      38   6.0
+  526848  0.0133378  0.00000035  39.50  3753.9      38   7.5
+  529200  0.0155954  0.00000035  33.93  3225.9      33  18.0
+  531441  0.0223760  0.00000037  23.75  2258.6      23   1.4
+  535815  0.0208984  0.00000036  25.64  2439.7      25   2.2
+  537600  0.0137115  0.00000033  39.21  3731.9      37  16.4
+  537824  0.0163495  0.00000036  32.90  3131.1      31   3.8
+  540000  0.0153587  0.00000034  35.16  3347.6      33  22.6
+  540225  0.0211182  0.00000035  25.58  2435.7      24   2.5
+  544320  0.0160828  0.00000034  33.84  3224.4      32  25.1
+  546750  0.0169108  0.00000036  32.33  3081.3      30   8.5
+  546875  0.0206055  0.00000039  26.54  2529.4      25   1.4
+  548800  0.0147042  0.00000035  37.32  3557.9      35  10.3
+  551124  0.0181013  0.00000037  30.45  2903.4      28   8.2
+  551250  0.0153735  0.00000035  35.86  3419.4      33   6.6
+  552960  0.0133378  0.00000033  41.46  3954.4      38  23.6
+  555660  0.0220363  0.00000036  25.22  2406.1      23   8.1
+  559872  0.0168536  0.00000035  33.22  3171.6      31  22.3
+  560000  0.0155954  0.00000035  35.91  3428.3      33  14.1
+  562500  0.0326843  0.00000035  17.21  1643.7      16   1.0
+  564480  0.0149213  0.00000034  37.83  3614.1      34  20.1
+  567000  0.0158386  0.00000035  35.80  3421.1      32  19.3
+  571536  0.0317078  0.00000035  18.03  1723.6      16   0.1
+  573440  0.0156102  0.00000033  36.73  3513.6      33  10.2
+  576000  0.0149069  0.00000034  38.64  3697.0      34  29.2
+  576240  0.0205859  0.00000035  27.99  2678.3      25   4.4
+  580608  0.0153587  0.00000035  37.80  3619.1      33  24.3
+  583200  0.0281576  0.00000032  20.71  1983.6      18   6.6
+  583443  0.0253418  0.00000039  23.02  2204.9      20   1.5
+  588000  0.0166173  0.00000035  35.38  3390.8      31  10.3
+  588245  0.0298139  0.00000037  19.73  1890.8      17  23.1
+  589824  0.0230380  0.00000034  25.60  2454.0      22   1.1
+  590490  0.0203125  0.00000036  29.07  2786.6      25   1.6
+  590625  0.0206055  0.00000036  28.66  2747.7      25   2.9
+  592704  0.0186593  0.00000036  31.76  3045.7      28  11.7
+  595350  0.0177465  0.00000036  33.55  3217.8      29   4.6
+  600000  0.0163495  0.00000035  36.70  3522.0      31  15.4
+  600250  0.0177465  0.00000036  33.82  3246.3      29   2.5
+  602112  0.0153735  0.00000036  39.17  3759.8      33  10.1
+  604800  0.0160980  0.00000034  37.57  3607.8      32  24.2
+  605052  0.0230602  0.00000036  26.24  2519.7      22   4.6
+  607500  0.0169108  0.00000035  35.92  3450.9      30  10.8
+  612360  0.0198130  0.00000034  30.91  2970.8      26   6.7
+  612500  0.0180159  0.00000037  34.00  3267.9      29   5.0
+  614400  0.0149069  0.00000033  41.22  3962.6      34  17.7
+  614656  0.0307617  0.00000035  19.98  1921.1      17   0.9
+  617400  0.0174939  0.00000036  35.29  3394.4      29   8.9
+  622080  0.0158386  0.00000034  39.28  3779.7      32  20.6
+  625000  0.0183977  0.00000040  33.97  3270.4      28   5.9
+  627200  0.0241350  0.00000033  25.99  2502.4      21   8.6
+  629856  0.0202930  0.00000035  31.04  2989.7      25  11.2
+  630000  0.0177465  0.00000035  35.50  3419.5      29  17.5
+  635040  0.0194937  0.00000034  32.58  3139.8      26  11.7
+  637875  0.0233931  0.00000035  27.27  2629.0      22   3.2
+  640000  0.0267013  0.00000033  23.97  2311.5      19   1.0
+  642978  0.0233931  0.00000037  27.49  2651.6      22   1.7
+  643125  0.0241350  0.00000035  26.65  2570.7      21   1.7
+  645120  0.0166173  0.00000034  38.82  3746.2      31  20.8
+  648000  0.0194937  0.00000033  33.24  3208.7      26  26.0
+  648270  0.0311926  0.00000037  20.78  2006.2      17 126.6
+  653184  0.0183803  0.00000036  35.54  3432.4      28  17.6
+  655360  0.0163495  0.00000033  40.08  3872.5      31  10.9
+  656100  0.0429281  0.00000035  15.28  1476.7      12   1.4
+  656250  0.0205859  0.00000038  31.88  3080.1      25   3.9
+  658560  0.0177633  0.00000035  37.07  3583.0      29  10.0
+  661500  0.0205859  0.00000036  32.13  3106.6      25  10.1
+  663552  0.0257568  0.00000034  25.76  2491.2      20   8.3
+  666792  0.0194937  0.00000036  34.21  3308.9      26   5.9
+  672000  0.0174154  0.00000034  38.59  3734.8      30  21.6
+  672280  0.0321655  0.00000037  20.90  2023.0      16  43.9
+  675000  0.0202734  0.00000036  33.29  3223.7      25  12.8
+  677376  0.0193685  0.00000036  34.97  3387.1      27  17.3
+  680400  0.0211385  0.00000034  32.19  3118.3      24  20.5
+  686000  0.0205859  0.00000036  33.32  3230.4      25   9.9
+  688128  0.0171549  0.00000035  40.11  3889.4      30  12.8
+  688905  0.0285916  0.00000036  24.09  2336.5      18   1.1
+  691200  0.0174939  0.00000034  39.51  3832.3      29  30.0
+  691488  0.0337891  0.00000038  20.46  1985.0      15  11.1
+  694575  0.0286187  0.00000036  24.27  2354.9      18   2.8
+  699840  0.0220576  0.00000033  31.73  3080.2      23  19.7
+  700000  0.0202734  0.00000036  34.53  3352.1      25  12.8
+  702464  0.0190611  0.00000036  36.85  3578.8      27  10.4
+  703125  0.0298139  0.00000038  23.58  2290.4      17   3.3
+  705600  0.0422363  0.00000030  16.71  1622.9      12   0.8
+  705894  0.0343099  0.00000038  20.57  1998.7      15  92.9
+  708588  0.0271382  0.00000037  26.11  2537.2      19   6.4
+  708750  0.0233931  0.00000036  30.30  2944.1      22   7.0
+  714420  0.0270868  0.00000035  26.38  2564.5      19   6.7
+  716800  0.0197942  0.00000033  36.21  3521.9      26  19.6
+  720000  0.0307330  0.00000034  23.43  2279.2      17   8.5
+  720300  0.0230380  0.00000036  31.27  3041.9      22   5.6
+  725760  0.0205859  0.00000034  35.26  3431.9      25  25.1
+  729000  0.0230554  0.00000036  31.62  3079.0      23  15.0
+  734832  0.0245071  0.00000036  29.98  2921.5      21  12.8
+  735000  0.0227157  0.00000036  32.36  3152.7      23   8.1
+  737280  0.0202734  0.00000034  36.37  3544.3      25  22.5
+  740880  0.0248791  0.00000034  29.78  2903.3      21  11.4
+  746496  0.0353841  0.00000034  21.10  2058.0      15   1.4
+  750000  0.0234153  0.00000037  32.03  3125.6      22  13.5
+  750141  0.0338216  0.00000038  22.18  2164.3      15   1.2
+  752640  0.0211385  0.00000034  35.61  3475.3      24  14.8
+  756000  0.0233931  0.00000035  32.32  3155.5      22  24.9
+  756315  0.0401893  0.00000037  18.82  1837.5      13  29.3
+  759375  0.0298139  0.00000037  25.47  2487.8      17   3.9
+  762048  0.0249023  0.00000036  30.60  2989.7      21  18.4
+  765450  0.0265137  0.00000037  28.87  2821.5      20   6.9
+  765625  0.0307617  0.00000038  24.89  2432.4      17   2.0
+  768000  0.0205859  0.00000034  37.31  3646.9      25  24.9
+  768320  0.0261475  0.00000035  29.38  2872.5      20  10.6
+  771750  0.0241583  0.00000036  31.95  3123.9      21   5.9
+  774144  0.0217692  0.00000035  35.56  3478.3      24  23.6
+  777600  0.0211182  0.00000035  36.82  3602.7      24  33.1
+  777924  0.0506836  0.00000037  15.35  1501.8      10   1.6
+  781250  0.0261230  0.00000042  29.91  2927.2      20   3.9
+  784000  0.0233931  0.00000035  33.51  3281.1      22  18.5
+  786432  0.0233931  0.00000035  33.62  3292.0      22  13.8
+  787320  0.0275236  0.00000035  28.61  2801.4      19   8.6
+  787500  0.0241583  0.00000037  32.60  3192.4      21  13.8
+  790272  0.0230380  0.00000037  34.30  3360.3      22  18.3
+  793800  0.0482067  0.00000034  16.47  1613.6      11   5.4
+  800000  0.0233931  0.00000035  34.20  3353.1      22  21.1
+  802816  0.0326538  0.00000035  24.59  2411.2      16   1.6
+  806400  0.0227157  0.00000034  35.50  3482.7      23  35.7
+  806736  0.0353516  0.00000037  22.82  2238.9      15   7.4
+  810000  0.0390249  0.00000034  20.76  2036.9      13   0.2
+  816480  0.0266756  0.00000034  30.61  3005.5      19  18.8
+  819200  0.0331421  0.00000033  24.72  2427.8      16  10.2
+  820125  0.0348307  0.00000036  23.55  2312.9      15   4.0
+  823200  0.0253418  0.00000036  32.48  3191.7      20  14.0
+  823543  0.0563151  0.00000038  14.62  1436.9       9   5.8
+  826686  0.0348307  0.00000038  23.73  2332.7      15   2.5
+  826875  0.0326538  0.00000036  25.32  2488.9      16   3.9
+  829440  0.0223972  0.00000034  37.03  3640.7      23  29.9
+  833490  0.0343099  0.00000036  24.29  2389.1      15   2.4
+  839808  0.0379116  0.00000038  22.15  2179.7      14  11.1
+  840000  0.0261475  0.00000035  32.13  3161.2      20  25.0
+  840350  0.0311926  0.00000037  26.94  2651.1      17   3.5
+  843750  0.0279091  0.00000037  30.23  2975.8      19   7.8
+  846720  0.0257324  0.00000035  32.90  3239.7      20  23.3
+  850500  0.0285916  0.00000036  29.75  2929.7      18  17.0
+  857304  0.0321655  0.00000037  26.65  2626.6      16   9.2
+  857500  0.0311926  0.00000037  27.49  2709.2      17   7.8
+  860160  0.0257324  0.00000035  33.43  3294.9      20  22.0
+  864000  0.0266756  0.00000035  32.39  3193.7      19  39.7
+  864360  0.0321655  0.00000035  26.87  2649.8      16   7.8
+  870912  0.0271125  0.00000036  32.12  3169.2      19  29.5
+  874800  0.0316772  0.00000034  27.62  2725.5      16  28.9
+  875000  0.0302734  0.00000039  28.90  2852.6      17  10.1
+  878080  0.0261475  0.00000035  33.58  3315.2      20  15.9
+  882000  0.0298139  0.00000036  29.58  2921.4      17  24.6
+  884736  0.0257568  0.00000036  34.35  3392.9      20  26.1
+  885735  0.0422770  0.00000036  20.95  2069.6      12   1.6
+  889056  0.0286187  0.00000036  31.07  3069.6      18  15.6
+  893025  0.0384347  0.00000036  23.23  2296.6      14   4.5
+  896000  0.0248791  0.00000034  36.01  3560.6      21  27.2
+  900000  0.0274979  0.00000036  32.73  3236.9      19  28.3
+  900375  0.0395883  0.00000035  22.74  2249.3      13   2.3
+  903168  0.0379116  0.00000035  23.82  2356.6      14  13.3
+  907200  0.0237482  0.00000034  38.20  3780.2      22  39.9
+  907578  0.0454915  0.00000038  19.95  1974.3      12  46.0
+  911250  0.0311926  0.00000036  29.21  2891.8      17   9.5
+  917504  0.0245071  0.00000036  37.44  3707.8      21  15.6
+  918540  0.0367606  0.00000036  24.99  2474.8      14   9.5
+  918750  0.0316772  0.00000037  29.00  2872.7      16   5.2
+  921600  0.0396259  0.00000032  23.26  2304.1      13   1.8
+  921984  0.0281576  0.00000037  32.74  3244.0      18  13.6
+  926100  0.0321655  0.00000037  28.79  2853.4      16  13.7
+  933120  0.0274979  0.00000036  33.93  3364.9      19  33.0
+  937500  0.0311926  0.00000040  30.06  2981.2      17   9.6
+  940800  0.0274979  0.00000035  34.21  3394.6      19  27.2
+  941192  0.0530762  0.00000038  17.73  1759.5      10   3.2
+  944784  0.0514648  0.00000036  18.36  1822.0      10   0.1
+  945000  0.0302734  0.00000036  31.22  3098.1      17  20.2
+  952560  0.0353841  0.00000035  26.92  2673.4      15  18.2
+  960000  0.0281847  0.00000035  34.06  3384.4      18  31.9
+  960400  0.0496271  0.00000035  19.35  1923.0      11  10.5
+  964467  0.0522461  0.00000039  18.46  1834.9      10   1.7
+  967680  0.0274979  0.00000034  35.19  3498.7      19  35.9
+  972000  0.0307330  0.00000033  31.63  3145.4      17  34.6
+  972405  0.0506836  0.00000038  19.19  1908.1      10   1.6
+  979776  0.0336304  0.00000036  29.13  2899.1      16  27.8
+  980000  0.0460760  0.00000036  21.27  2116.5      11  10.6
+  983040  0.0274979  0.00000034  35.75  3558.3      19  21.6
+  984150  0.0363932  0.00000037  27.04  2691.8      15   9.1
+  984375  0.0435384  0.00000037  22.61  2250.6      12   5.2
+  987840  0.0353516  0.00000035  27.94  2782.3      15  24.4
+  992250  0.0353516  0.00000037  28.07  2795.6      15   9.2
+  995328  0.0238095  0.00000035  41.80  4164.7      21  32.8
+ 1000000  0.0474964  0.00000038  21.05  2098.2      11   0.9
+ 1000188  0.0435384  0.00000037  22.97  2289.4      12   9.7
+ 1003520  0.0294596  0.00000034  34.06  3395.6      18  19.5
+ 1008000  0.0303022  0.00000035  33.26  3317.0      17  45.5
+ 1008420  0.0496715  0.00000037  20.30  2024.5      11 109.5
+ 1012500  0.0326538  0.00000036  31.01  3092.9      16  19.5
+ 1016064  0.0545898  0.00000035  18.61  1857.0      10   1.4
+ 1020600  0.0353516  0.00000034  28.87  2881.4      15  22.1
+ 1024000  0.0298139  0.00000034  34.35  3428.8      17  29.9
+ 1029000  0.0379116  0.00000036  27.14  2710.5      14  11.2
+ 1032192  0.0298426  0.00000035  34.59  3454.9      17  31.9
+ 1036800  0.0422363  0.00000033  24.55  2452.8      12  13.2
+ 1037232  0.0378767  0.00000037  27.38  2736.3      14  17.2
+ 1048576  0.0468306  0.00000035  22.39  2239.1      11   0.0
+ 1049760  0.0379116  0.00000035  27.69  2769.2      14  24.2
+ 1050000  0.0362374  0.00000037  28.98  2897.8      14  22.5
+ 1053696  0.0307330  0.00000036  34.29  3429.8      17  18.8
+ 1058400  0.0384347  0.00000035  27.54  2755.6      14  32.4
+ 1058841  0.0580512  0.00000038  18.24  1825.3       9  23.8
+ 1062882  0.0538086  0.00000039  19.75  1977.2      10   3.5
+ 1063125  0.0467862  0.00000036  22.72  2274.6      11   6.3
+ 1071630  0.0515137  0.00000037  20.80  2083.5      10   3.7
+ 1071875  0.0467862  0.00000037  22.91  2294.6      11   2.9
+ 1075200  0.0316772  0.00000034  33.94  3400.4      16  32.7
+ 1075648  0.0435384  0.00000036  24.71  2475.1      12  18.7
+ 1080000  0.0348307  0.00000035  31.01  3107.3      15  46.1
+ 1080450  0.0395883  0.00000037  27.29  2735.1      13   8.6
+ 1088640  0.0337891  0.00000036  32.22  3230.6      15  34.9
+ 1093500  0.0402269  0.00000036  27.18  2726.6      13  23.3
+ 1093750  0.0419922  0.00000041  26.05  2612.6      13   6.2
+ 1097600  0.0367606  0.00000036  29.86  2995.6      14  26.9
+ 1102248  0.0413912  0.00000037  26.63  2672.6      13  14.1
+ 1102500  0.0844727  0.00000034  13.05  1309.9       6   2.8
+ 1105920  0.0311926  0.00000035  35.45  3559.1      17  35.5
+ 1111320  0.0413912  0.00000035  26.85  2696.2      13  13.7
+ 1119744  0.0331726  0.00000037  33.76  3391.5      16  37.5
+ 1120000  0.0348633  0.00000036  32.13  3227.8      15  34.1
+ 1125000  0.0624457  0.00000035  18.02  1810.7       9   6.9
+ 1128960  0.0353516  0.00000035  31.94  3210.5      15  33.7
+ 1134000  0.0407903  0.00000034  27.80  2795.8      13  41.7
+ 1143072  0.0625000  0.00000037  18.29  1840.3       8  14.7
+ 1146880  0.0316772  0.00000034  36.21  3643.9      16  21.4
+ 1148175  0.0538086  0.00000036  21.34  2147.8      10   6.3
+ 1152000  0.0337891  0.00000034  34.09  3432.5      15  52.4
+ 1152480  0.0545898  0.00000036  21.11  2125.6      10 517.3
+ 1157625  0.0514648  0.00000036  22.49  2265.4      10   5.4
+ 1161216  0.0389874  0.00000036  29.78  3000.4      13  38.8
+ 1166400  0.0615234  0.00000033  18.96  1910.4       9   1.3
+ 1166886  0.0581597  0.00000038  20.06  2021.8       9   3.7
+ 1171875  0.0538086  0.00000040  21.78  2195.3      10   3.8
+ 1176000  0.0419922  0.00000036  28.01  2823.7      13  32.6
+ 1176490  0.0633545  0.00000037  18.57  1872.4       8  15.1
+ 1179648  0.0489169  0.00000037  24.12  2432.0      11  15.8
+ 1180980  0.0496271  0.00000036  23.80  2400.1      11  13.8
+ 1181250  0.0413912  0.00000037  28.54  2878.4      13  12.6
+ 1185408  0.0384615  0.00000037  30.82  3109.3      13  31.8
+ 1190700  0.0441895  0.00000037  26.95  2719.2      12  23.9
+ 1200000  0.0384347  0.00000037  31.22  3152.6      14  36.1
+ 1200500  0.0454915  0.00000037  26.39  2664.7      12  12.1
+ 1204224  0.0367606  0.00000036  32.76  3308.6      14  23.2
+ 1209600  0.0395883  0.00000035  30.55  3086.9      13  58.0
+ 1210104  0.0489169  0.00000037  24.74  2499.4      11  13.8
+ 1215000  0.0413912  0.00000034  29.35  2966.6      13  32.4
+ 1224720  0.0468750  0.00000035  26.13  2642.0      11  29.5
+ 1225000  0.0467862  0.00000038  26.18  2647.7      11  15.9
+ 1228800  0.0343099  0.00000034  35.81  3622.4      15  37.4
+ 1229312  0.0571832  0.00000037  21.50  2174.4       9  18.5
+ 1234800  0.0474964  0.00000036  26.00  2630.4      11  36.8
+ 1240029  0.0757533  0.00000038  16.37  1656.7       7   2.5
+ 1244160  0.0379464  0.00000035  32.79  3319.2      14  45.4
+ 1250000  0.0454545  0.00000040  27.50  2784.9      11  25.1
+ 1250235  0.0779855  0.00000037  16.03  1623.5       7   2.4
+ 1254400  0.0653076  0.00000033  19.21  1945.6       8   2.5
+ 1259712  0.0507812  0.00000036  24.81  2513.5      10  39.0
+ 1260000  0.0467862  0.00000036  26.93  2728.8      11  45.8
+ 1260525  0.0633545  0.00000037  19.90  2016.1       8   3.3
+ 1265625  0.0606554  0.00000037  20.87  2114.9       9   7.6
+ 1270080  0.0474964  0.00000035  26.74  2711.0      11  39.1
+ 1275750  0.0489169  0.00000037  26.08  2644.9      11  14.8
+ 1280000  0.0514648  0.00000033  24.87  2522.9      10  16.0
+ 1285956  0.0935872  0.00000038  13.74  1394.3       6   2.8
+ 1286250  0.0474964  0.00000037  27.08  2748.0      11   8.1
+ 1290240  0.0395883  0.00000035  32.59  3307.9      13  43.1
+ 1296000  0.0401893  0.00000035  32.25  3274.0      13  62.4
+ 1296540  0.0555556  0.00000036  23.34  2369.5       9  13.8
+ 1306368  0.0460760  0.00000037  28.35  2880.2      11  46.4
+ 1310720  0.0407903  0.00000034  32.13  3265.0      13  25.4
+ 1312200  0.0802176  0.00000035  16.36  1662.3       7   8.7
+ 1312500  0.0496271  0.00000039  26.45  2687.6      11  17.1
+ 1317120  0.0467862  0.00000036  28.15  2861.5      11  26.8
+ 1323000  0.0474964  0.00000036  27.85  2832.2      11  30.8
+ 1327104  0.0580512  0.00000035  22.86  2324.9       9   2.8
+ 1333584  0.0538086  0.00000036  24.78  2521.4      10  29.2
+ 1344000  0.0428874  0.00000035  31.34  3189.9      12  47.1
+ 1344560  0.0692139  0.00000036  19.43  1977.5       8 159.4
+ 1350000  0.0475852  0.00000037  28.37  2888.7      11  47.9
+ 1354752  0.0441895  0.00000036  30.66  3122.4      12  43.5
+ 1360800  0.0553711  0.00000036  24.58  2503.8      10  55.2
+ 1361367  0.0909831  0.00000038  14.96  1524.5       6   2.8
+ 1366875  0.0768694  0.00000036  17.78  1812.2       7   9.3
+ 1372000  0.0530273  0.00000037  25.87  2637.5      10  30.0
+ 1376256  0.0422363  0.00000036  32.58  3322.4      12  27.9
+ 1377810  0.0779855  0.00000038  17.67  1801.6       7   5.6
+ 1378125  0.0701904  0.00000037  19.63  2002.1       8   7.8
+ 1382400  0.0435384  0.00000035  31.75  3238.4      12  67.5
+ 1382976  0.0701904  0.00000039  19.70  2009.7       8  28.4
+ 1389150  0.0580512  0.00000037  23.93  2441.5       9  13.5
+ 1399680  0.0489169  0.00000037  28.61  2921.0      11  48.5
+ 1400000  0.0514648  0.00000038  27.20  2777.0      10  42.4
+ 1404928  0.0460760  0.00000037  30.49  3113.5      11  28.0
+ 1406250  0.0572917  0.00000040  24.55  2506.5       9  15.2
+ 1411200  0.0625000  0.00000035  22.58  2306.3       8  21.4
+ 1411788  0.0791016  0.00000036  17.85  1823.1       7  19.1
+ 1417176  0.0653076  0.00000038  21.70  2217.2       8  19.6
+ 1417500  0.0563151  0.00000036  25.17  2571.8       9  35.1
+ 1428840  0.0571832  0.00000036  24.99  2554.5       9  20.1
+ 1433600  0.0461648  0.00000034  31.05  3175.5      11  44.9
+ 1440000  0.0682373  0.00000035  21.10  2158.6       8   1.9
+ 1440600  0.0597873  0.00000036  24.10  2464.7       9  18.2
+ 1451520  0.0482067  0.00000036  30.11  3081.7      11  55.8
+ 1458000  0.0555556  0.00000034  26.24  2686.8       9  57.4
+ 1469664  0.0615234  0.00000037  23.89  2447.0       9  36.4
+ 1470000  0.0633545  0.00000037  23.20  2376.8       8  34.2
+ 1474560  0.0467862  0.00000034  31.52  3229.2      11  49.9
+ 1476225  0.0844727  0.00000036  17.48  1790.7       6   8.4
+ 1481760  0.0606554  0.00000035  24.43  2503.9       9  33.3
+ 1488375  0.0779855  0.00000036  19.09  1956.7       7   8.8
+ 1492992  0.0662842  0.00000037  22.52  2309.8       8  21.0
+ 1500000  0.0563151  0.00000038  26.64  2732.4       9  37.1
+ 1500282  0.0911458  0.00000038  16.46  1688.6       6   5.7
+ 1500625  0.0802176  0.00000037  18.71  1919.1       7   4.6
+ 1505280  0.0496271  0.00000035  30.33  3112.3      11  32.2
+ 1512000  0.0580512  0.00000034  26.05  2673.4       9  75.1
+ 1512630  0.0779855  0.00000038  19.40  1990.9       7 169.3
+ 1518750  0.0662842  0.00000037  22.91  2352.5       8  19.2
+ 1524096  0.0530273  0.00000038  28.74  2951.7      10  49.8
+ 1530900  0.0701904  0.00000037  21.81  2240.6       8  36.5
+ 1531250  0.0724051  0.00000040  21.15  2172.6       7  10.3
+ 1536000  0.0497159  0.00000034  30.90  3174.6      11  55.0
+ 1536640  0.0563151  0.00000037  27.29  2803.9       9  29.7
+ 1543500  0.0672607  0.00000037  22.95  2358.8       8  32.1
+ 1548288  0.0531250  0.00000036  29.14  2996.4      10  54.4
+ 1555200  0.0538086  0.00000035  28.90  2972.4      10  83.8
+ 1555848  0.0974935  0.00000038  15.96  1641.3       6  10.6
+ 1562500  0.0948893  0.00000040  16.47  1694.0       6   2.9
+ 1568000  0.0563151  0.00000036  27.84  2865.1       9  52.1
+ 1572864  0.0522461  0.00000036  30.10  3098.5      10  33.0
+ 1574640  0.0664062  0.00000036  23.71  2440.8       8  40.1
+ 1575000  0.0653076  0.00000037  24.12  2482.4       8  43.1
+ 1580544  0.0546875  0.00000037  28.90  2975.7      10  51.5
+ 1587600  0.0922852  0.00000034  17.20  1771.8       6   0.2
+ 1594323  0.1125000  0.00000038  14.17  1460.0       5   3.5
+ 1600000  0.0643311  0.00000037  24.87  2562.9       8  55.8
+ 1605632  0.0746373  0.00000038  21.51  2217.4       7  22.8
+ 1607445  0.1169922  0.00000037  13.74  1416.3       5   3.9
+ 1612800  0.0563151  0.00000035  28.64  2952.8       9  86.6
+ 1613472  0.0813337  0.00000039  19.84  2045.4       7 200.8
+ 1620000  0.0844727  0.00000034  19.18  1978.0       6  19.2
+ 1620675  0.0974935  0.00000037  16.62  1714.6       6   8.7
+ 1632960  0.0711670  0.00000035  22.95  2367.9       8  61.1
+ 1638400  0.0724051  0.00000033  22.63  2335.7       7   3.3
+ 1640250  0.0844727  0.00000036  19.42  2004.4       6  17.0
+ 1640625  0.0948893  0.00000038  17.29  1784.8       6   4.4
+ 1646400  0.0701904  0.00000035  23.46  2422.0       8  45.1
+ 1647086  0.0896810  0.00000038  18.37  1896.4       6 101.0
+ 1653372  0.0859375  0.00000037  19.24  1987.1       6  21.7
+ 1653750  0.0802176  0.00000038  20.62  2129.3       7  15.2
+ 1658880  0.0580512  0.00000034  28.58  2952.2       9  66.1
+ 1666980  0.0833333  0.00000036  20.00  2067.3       6  21.3
+ 1679616  0.0885417  0.00000035  18.97  1961.4       6   2.4
+ 1680000  0.0623915  0.00000037  26.93  2784.2       9  49.3
+ 1680700  0.1029297  0.00000035  16.33  1688.4       5  19.4
+ 1687500  0.0768694  0.00000039  21.95  2270.6       7  33.2
+ 1693440  0.0623915  0.00000036  27.14  2808.1       9  60.9
+ 1701000  0.0724051  0.00000034  23.49  2431.3       7  43.2
+ 1714608  0.0791016  0.00000037  21.68  2244.5       7  43.6
+ 1715000  0.0883789  0.00000038  19.41  2009.4       6  21.2
+ 1720320  0.0607639  0.00000034  28.31  2932.3       9  40.8
+ 1728000  0.0606554  0.00000035  28.49  2951.5       9  85.2
+ 1728720  0.0813337  0.00000036  21.25  2202.1       7  41.1
+ 1741824  0.0662842  0.00000037  26.28  2724.0       8  69.6
+ 1749600  0.0779855  0.00000035  22.43  2326.3       7  69.3
+ 1750000  0.0857747  0.00000039  20.40  2115.6       6  36.3
+ 1750329  0.1248047  0.00000040  14.02  1454.3       5   3.8
+ 1756160  0.0644531  0.00000037  27.25  2826.1       8  39.5
+ 1764000  0.0802176  0.00000035  21.99  2281.5       7  60.3
+ 1764735  0.1060547  0.00000036  16.64  1726.5       5  19.2
+ 1769472  0.0623915  0.00000036  28.36  2943.1       9  64.2
+ 1771470  0.1169922  0.00000038  15.14  1571.5       5   7.9
+ 1771875  0.1232422  0.00000036  14.38  1492.1       5   9.6
+ 1778112  0.0779855  0.00000036  22.80  2366.9       7  60.5
+ 1786050  0.0935872  0.00000037  19.08  1981.7       6  19.1
+ 1792000  0.0633545  0.00000035  28.29  2937.9       8  58.1
+ 1800000  0.0791016  0.00000037  22.76  2364.3       7  79.4
+ 1800750  0.0896810  0.00000037  20.08  2086.3       6 367.2
+ 1806336  0.0935872  0.00000036  19.30  2005.8       6   4.2
+ 1814400  0.0643311  0.00000036  28.20  2932.0       8  89.3
+ 1815156  0.1044922  0.00000039  17.37  1805.9       5  23.5
+ 1822500  0.1232422  0.00000035  14.79  1537.8       5   4.1
+ 1835008  0.0693359  0.00000037  26.47  2753.4       8  40.3
+ 1837080  0.0857747  0.00000036  21.42  2228.4       6  30.6
+ 1837500  0.0935872  0.00000037  19.63  2042.9       6  20.1
+ 1843200  0.0746373  0.00000033  24.70  2570.0       7  25.0
+ 1843968  0.0735212  0.00000037  25.08  2610.2       7  43.7
+ 1852200  0.0883789  0.00000036  20.96  2181.8       6  42.6
+ 1866240  0.0692139  0.00000036  26.96  2808.5       8  79.6
+ 1875000  0.1015625  0.00000039  18.46  1923.6       5  24.1
+ 1881600  0.0653076  0.00000036  28.81  3002.6       8  61.0
+ 1882384  0.1091797  0.00000037  17.24  1796.9       5  11.2
+ 1889568  0.1125000  0.00000038  16.80  1751.0       5  24.2
+ 1890000  0.0922852  0.00000036  20.48  2135.0       6  68.1
+ 1905120  0.0883789  0.00000036  21.56  2248.5       6  53.4
+ 1913625  0.1201172  0.00000035  15.93  1662.3       5  10.9
+ 1920000  0.0721436  0.00000036  26.61  2777.5       8  66.7
+ 1920800  0.1000000  0.00000037  19.21  2004.7       5  32.2
+ 1928934  0.1325684  0.00000039  14.55  1519.0       4   8.3
+ 1929375  0.1267090  0.00000035  15.23  1589.7       4  10.0
+ 1935360  0.0724051  0.00000036  26.73  2791.1       7  79.8
+ 1944000  0.0857747  0.00000036  22.66  2367.3       6  97.2
+ 1944810  0.1345215  0.00000038  14.46  1510.1       4   8.2
+ 1953125  0.1286621  0.00000041  15.18  1586.1       4   5.9
+ 1959552  0.0779855  0.00000038  25.13  2626.0       7  74.8
+ 1960000  0.0987956  0.00000037  19.84  2073.4       6   1.9
+ 1966080  0.0714286  0.00000036  27.53  2877.3       7  47.1
+ 1968300  0.1107422  0.00000036  17.77  1858.1       5  46.7
+ 1968750  0.1107422  0.00000038  17.78  1858.6       5  20.2
+ 1975680  0.0757533  0.00000037  26.08  2727.2       7  66.5
+ 1984500  0.1107422  0.00000037  17.92  1874.5       5  45.3
+ 1990656  0.0757533  0.00000037  26.28  2749.3       7  81.6
+ 2000000  0.0987956  0.00000037  20.24  2118.7       6  25.8
+ 2000376  0.1013672  0.00000037  19.73  2065.3       5  30.7
+ 2007040  0.0757533  0.00000036  26.49  2773.5       7  47.3
+ 2016000  0.0844727  0.00000036  23.87  2499.1       6 106.1
+ 2016840  0.1076172  0.00000037  18.74  1962.5       5 430.3
+ 2025000  0.1044922  0.00000036  19.38  2029.9       5  54.0
+ 2032128  0.0935872  0.00000039  21.71  2275.0       6  28.4
+ 2041200  0.1000000  0.00000036  20.41  2139.3       5  84.9
+ 2048000  0.0711670  0.00000035  28.78  3016.7       8  69.3
+ 2058000  0.1185547  0.00000036  17.36  1820.3       5  46.5
+ 2064384  0.0835658  0.00000036  24.70  2591.1       7  78.7
+ 2066715  0.1520996  0.00000037  13.59  1425.3       4   5.3
+ 2073600  0.1015625  0.00000034  20.42  2142.1       5   4.0
+ 2074464  0.1093750  0.00000037  18.97  1990.0       5  53.8
+ 2083725  0.1484375  0.00000036  14.04  1473.3       4  12.1
+ 2097152  0.0896810  0.00000035  23.38  2455.4       6   0.0
+ 2099520  0.1013672  0.00000036  20.71  2174.9       5  85.1
+ 2100000  0.1171875  0.00000036  17.92  1881.8       5  50.4
+ 2100875  0.1367188  0.00000035  15.37  1613.7       4  76.5
+ 2107392  0.0859375  0.00000036  24.52  2575.7       6  50.6
+ 2109375  0.1425781  0.00000037  14.79  1554.0       4  11.2
+ 2116800  0.1046875  0.00000036  20.22  2124.5       5 102.6
+ 2117682  0.1109375  0.00000039  19.09  2005.7       5 497.2
+ 2125764  0.1479492  0.00000038  14.37  1510.1       4   4.5
+ 2126250  0.1328125  0.00000035  16.01  1682.6       4  25.3
+ 2143260  0.1250000  0.00000037  17.15  1803.0       4  31.4
+ 2143750  0.1342773  0.00000037  15.97  1678.9       4  14.5
+ 2150400  0.0859375  0.00000035  25.02  2631.9       6  83.0
+ 2151296  0.0924479  0.00000038  23.27  2447.7       6  50.6
+ 2160000  0.0898438  0.00000034  24.04  2529.5       6 124.3
+ 2160900  0.1440430  0.00000035  15.00  1578.4       4   7.0
+ 2177280  0.0924479  0.00000037  23.55  2479.3       6 100.2
+ 2187000  0.1121094  0.00000035  19.51  2054.2       5  62.7
+ 2187500  0.1406250  0.00000040  15.56  1638.1       4  26.6
+ 2195200  0.0947266  0.00000036  23.17  2440.9       6  76.8
+ 2204496  0.1171875  0.00000037  18.81  1982.0       5  63.9
+ 2205000  0.1347656  0.00000036  16.36  1723.9       4  15.9
+ 2211840  0.0856120  0.00000035  25.84  2722.7       6  93.3
+ 2222640  0.1171875  0.00000036  18.97  1999.4       5  63.4
+ 2239488  0.0973307  0.00000037  23.01  2426.8       6  98.6
+ 2240000  0.0986328  0.00000037  22.71  2395.4       6  82.6
+ 2250000  0.1199219  0.00000038  18.76  1979.6       5   0.3
+ 2250423  0.1816406  0.00000039  12.39  1307.2       3   5.4
+ 2257920  0.1000000  0.00000037  22.58  2382.8       5  91.7
+ 2268000  0.1152344  0.00000035  19.68  2077.7       5  99.2
+ 2268945  0.1401367  0.00000037  16.19  1709.2       4  96.2
+ 2278125  0.1523438  0.00000036  14.95  1579.1       4  14.2
+ 2286144  0.1284180  0.00000037  17.80  1880.3       4   2.4
+ 2293760  0.0898438  0.00000036  25.53  2697.2       6  57.3
+ 2296350  0.1484375  0.00000037  15.47  1634.5       4  29.9
+ 2296875  0.1596680  0.00000036  14.39  1519.9       4   7.5
+ 2304000  0.0973307  0.00000035  23.67  2501.6       6 126.2
+ 2304960  0.1214844  0.00000036  18.97  2005.1       5  57.8
+ 2315250  0.1459961  0.00000035  15.86  1676.4       4  26.2
+ 2322432  0.1011719  0.00000037  22.96  2427.2       5 103.2
+ 2332800  0.1167969  0.00000034  19.97  2112.5       5  34.9
+ 2333772  0.1518555  0.00000039  15.37  1625.5       4  34.7
+ 2343750  0.1542969  0.00000041  15.19  1607.1       4  16.6
+ 2352000  0.1058594  0.00000037  22.22  2351.3       5  79.9
+ 2352980  0.1542969  0.00000036  15.25  1613.9       4  35.3
+ 2359296  0.1214844  0.00000036  19.42  2055.7       5   5.9
+ 2361960  0.1538086  0.00000036  15.36  1625.6       4  50.2
+ 2362500  0.1503906  0.00000036  15.71  1663.0       4  60.0
+ 2370816  0.1093750  0.00000038  21.68  2295.2       5  97.9
+ 2381400  0.1542969  0.00000036  15.43  1634.7       4  74.0
+ 2400000  0.1078125  0.00000038  22.26  2359.1       5  91.5
+ 2401000  0.1464844  0.00000037  16.39  1737.0       4  36.7
+ 2408448  0.1093750  0.00000038  22.02  2334.1       5  62.7
+ 2419200  0.1078125  0.00000035  22.44  2379.2       5 140.4
+ 2420208  0.1518555  0.00000038  15.94  1689.9       4  74.2
+ 2430000  0.1386719  0.00000036  17.52  1858.6       4 111.4
+ 2449440  0.1323242  0.00000035  18.51  1964.4       4  83.1
+ 2450000  0.1479492  0.00000038  16.56  1757.3       4  59.3
+ 2457600  0.1089844  0.00000035  22.55  2393.6       5  94.5
+ 2458624  0.1347656  0.00000036  18.24  1936.5       4   4.9
+ 2460375  0.1712240  0.00000035  14.37  1525.3       3  19.4
+ 2469600  0.1381836  0.00000036  17.87  1897.6       4 103.2
+ 2470629  0.1640625  0.00000040  15.06  1599.0       4 144.2
+ 2480058  0.1920573  0.00000040  12.91  1371.5       3  14.4
+ 2480625  0.1744792  0.00000035  14.22  1510.0       3  19.3
+ 2488320  0.1167969  0.00000036  21.30  2263.3       5 122.6
+ 2500000  0.1503906  0.00000040  16.62  1766.5       4  64.2
+ 2500470  0.1894531  0.00000038  13.20  1402.6       3  14.5
+ 2508800  0.1303711  0.00000034  19.24  2045.4       4  41.1
+ 2519424  0.1284180  0.00000039  19.62  2086.0       4 114.5
+ 2520000  0.1445312  0.00000035  17.44  1853.8       4 144.1
+ 2521050  0.1328125  0.00000038  18.98  2018.3       4 270.5
+ 2531250  0.1640625  0.00000037  15.43  1640.9       4  37.3
+ 2540160  0.1214844  0.00000037  20.91  2224.4       5 111.2
+ 2551500  0.1770833  0.00000036  14.41  1533.3       3  82.1
+ 2560000  0.1125000  0.00000035  22.76  2422.1       5   5.2
+ 2571912  0.1692708  0.00000038  15.19  1617.7       3  17.7
+ 2572500  0.1738281  0.00000035  14.80  1575.7       3  35.2
+ 2580480  0.1187500  0.00000036  21.73  2314.2       5 119.7
+ 2592000  0.1214844  0.00000036  21.34  2272.9       5 165.2
+ 2593080  0.1425781  0.00000039  18.19  1937.5       41015.2
+ 2612736  0.1289062  0.00000038  20.27  2160.3       4 126.9
+ 2621440  0.1246094  0.00000035  21.04  2242.8       5  69.6
+ 2624400  0.1518555  0.00000035  17.28  1842.6       4   0.3
+ 2625000  0.1616211  0.00000038  16.24  1731.7       4  40.8
+ 2634240  0.1289062  0.00000037  20.44  2179.3       4  70.8
+ 2646000  0.1601562  0.00000036  16.52  1762.4       4 111.9
+ 2654208  0.1308594  0.00000039  20.28  2164.2       4  39.3
+ 2657205  0.2187500  0.00000038  12.15  1296.2       3   8.8
+ 2667168  0.1523438  0.00000037  17.51  1868.7       4  88.4
+ 2679075  0.1953125  0.00000036  13.72  1464.5       3  22.4
+ 2688000  0.1289062  0.00000036  20.85  2226.8       4 109.4
+ 2689120  0.1386719  0.00000039  19.39  2070.9       4 434.2
+ 2700000  0.1518555  0.00000037  17.78  1899.3       4 120.8
+ 2701125  0.1979167  0.00000035  13.65  1457.9       3  18.8
+ 2709504  0.1323242  0.00000037  20.48  2187.8       4 121.2
+ 2721600  0.1479492  0.00000034  18.40  1966.1       4 168.2
+ 2722734  0.2128906  0.00000040  12.79  1367.0       3  15.0
+ 2733750  0.1764323  0.00000035  15.49  1656.6       3  43.4
+ 2734375  0.2233073  0.00000040  12.24  1309.1       3  10.1
+ 2744000  0.1616211  0.00000037  16.98  1815.6       4  98.1
+ 2752512  0.1484375  0.00000038  18.54  1983.4       4  77.0
+ 2755620  0.1894531  0.00000037  14.55  1555.9       3  58.1
+ 2756250  0.1868490  0.00000037  14.75  1578.0       3  37.3
+ 2764800  0.1289062  0.00000035  21.45  2294.8       4 171.1
+ 2765952  0.1406250  0.00000040  19.67  2104.5       4  58.2
+ 2778300  0.1842448  0.00000037  15.08  1613.9       3  85.2
+ 2799360  0.1445312  0.00000037  19.37  2074.0       4 142.9
+ 2800000  0.1484375  0.00000039  18.86  2020.0       4 104.0
+ 2809856  0.1459961  0.00000038  19.25  2061.5       4  76.3
+ 2812500  0.1875000  0.00000038  15.00  1606.8       3  76.6
+ 2822400  0.1582031  0.00000033  17.84  1911.5       4   4.5
+ 2823576  0.1503906  0.00000039  18.77  2011.7       4 892.3
+ 2834352  0.1848958  0.00000037  15.33  1642.9       3  99.2
+ 2835000  0.1920573  0.00000035  14.76  1582.0       3 102.6
+ 2857680  0.1796875  0.00000036  15.90  1705.4       3 100.1
+ 2867200  0.1406250  0.00000036  20.39  2186.8       4 115.7
+ 2880000  0.1323242  0.00000035  21.76  2335.1       4  40.2
+ 2881200  0.1875000  0.00000036  15.37  1648.7       3  76.8
+ 2893401  0.2617188  0.00000039  11.06  1186.5       2   9.9
+ 2903040  0.1499023  0.00000034  19.37  2078.9       4 152.1
+ 2916000  0.1640625  0.00000034  17.77  1908.5       4 148.5
+ 2917215  0.2441406  0.00000038  11.95  1283.1       3   9.5
+ 2939328  0.1686198  0.00000037  17.43  1872.8       3 140.2
+ 2940000  0.1822917  0.00000036  16.13  1732.7       3  80.3
+ 2941225  0.1946615  0.00000036  15.11  1623.4       3  75.8
+ 2949120  0.1503906  0.00000036  19.61  2107.2       4 139.0
+ 2952450  0.2050781  0.00000037  14.40  1547.2       3  49.9
+ 2953125  0.2187500  0.00000037  13.50  1450.8       3  21.0
+ 2963520  0.1744792  0.00000035  16.98  1825.8       3 128.9
+ 2976750  0.2005208  0.00000035  14.85  1596.2       3  48.0
+ 2985984  0.1464844  0.00000036  20.38  2192.3       4   6.7
+ 3000000  0.1875000  0.00000038  16.00  1721.3       3 114.3
+ 3000564  0.2180990  0.00000039  13.76  1480.1       3  59.1
+ 3001250  0.2337240  0.00000037  12.84  1381.5       3  24.6
+ 3010560  0.1557617  0.00000033  19.33  2079.8       4  87.4
+ 3024000  0.1764323  0.00000036  17.14  1844.9       3 185.1
+ 3025260  0.1946615  0.00000037  15.54  1672.9       3 553.5
+ 3037500  0.1979167  0.00000036  15.35  1652.5       3  97.7
+ 3048192  0.1744792  0.00000037  17.47  1881.5       3 155.7
+ 3061800  0.1979167  0.00000035  15.47  1666.6       3 112.0
+ 3062500  0.2213542  0.00000038  13.84  1490.5       3   7.4
+ 3072000  0.1596680  0.00000035  19.24  2073.2       4 133.6
+ 3073280  0.1686198  0.00000038  18.23  1964.0       3  90.7
+ 3087000  0.2050781  0.00000036  15.05  1622.5       3  96.9
+ 3096576  0.1655273  0.00000036  18.71  2016.9       4 149.9
+ 3110400  0.1616211  0.00000034  19.25  2075.4       4 218.0
+ 3111696  0.1842448  0.00000039  16.89  1821.4       3   0.3
+ 3125000  0.1848958  0.00000040  16.90  1823.3       3  19.5
+ 3136000  0.1744792  0.00000036  17.97  1939.4       3 129.7
+ 3145728  0.1744792  0.00000036  18.03  1945.8       3  93.4
+ 3149280  0.1901042  0.00000036  16.57  1788.0       3 118.2
+ 3150000  0.1998698  0.00000038  15.76  1701.1       3 146.7
+ 3161088  0.1718750  0.00000036  18.39  1985.6       3 148.9
+ 3175200  0.1868490  0.00000036  16.99  1835.2       3  44.1
+ 3176523  0.2109375  0.00000041  15.06  1626.3       3 328.8
+ 3188646  0.2773438  0.00000039  11.50  1241.9       2  19.7
+ 3189375  0.2317708  0.00000036  13.76  1486.5       3  27.1
+ 3200000  0.1744792  0.00000037  18.34  1981.6       3 137.3
+ 3211264  0.1744792  0.00000036  18.40  1989.1       3   8.2
+ 3214890  0.2646484  0.00000039  12.15  1313.0       2  20.2
+ 3215625  0.2724609  0.00000035  11.80  1275.6       2  11.7
+ 3225600  0.1712240  0.00000034  18.84  2036.5       3 213.3
+ 3226944  0.2285156  0.00000039  14.12  1526.6       3  90.7
+ 3240000  0.1666667  0.00000036  19.44  2102.2       3   3.2
+ 3241350  0.2265625  0.00000037  14.31  1547.1       3  44.7
+ 3265920  0.1875000  0.00000036  17.42  1884.6       3 165.4
+ 3276800  0.1440430  0.00000034  22.75  2461.9       4  48.8
+ 3280500  0.2239583  0.00000036  14.65  1585.3       3 107.4
+ 3281250  0.2617188  0.00000039  12.54  1356.9       2  27.2
+ 3292800  0.2083333  0.00000037  15.81  1711.0       3 133.5
+ 3294172  0.3779297  0.00000039   8.72   943.6       2  77.7
+ 3306744  0.2207031  0.00000037  14.98  1622.4       3  72.8
+ 3307500  0.2207031  0.00000036  14.99  1622.8       3  94.2
+ 3317760  0.1848958  0.00000035  17.94  1943.5       3 180.8
+ 3333960  0.2180990  0.00000036  15.29  1656.2       3  72.0
+ 3359232  0.1718750  0.00000038  19.54  2118.6       3  52.3
+ 3360000  0.1979167  0.00000035  16.98  1840.3       3 150.5
+ 3361400  0.2369792  0.00000037  14.18  1537.6       3  55.7
+ 3375000  0.2291667  0.00000037  14.73  1596.9       3 107.5
+ 3386880  0.1822917  0.00000035  18.58  2015.1       3 166.2
+ 3402000  0.2187500  0.00000036  15.55  1687.2       3 177.1
+ 3429216  0.2109375  0.00000037  16.26  1764.7       3 124.8
+ 3430000  0.2597656  0.00000037  13.20  1433.3       2  91.7
+ 3440640  0.1875000  0.00000035  18.35  1992.3       3 110.8
+ 3444525  0.2656250  0.00000036  12.97  1408.0       2  28.3
+ 3456000  0.1875000  0.00000033  18.43  2001.8       3 231.7
+ 3457440  0.2239583  0.00000036  15.44  1676.7       3 113.6
+ 3472875  0.2695312  0.00000036  12.88  1399.8       2  26.9
+ 3483648  0.1888021  0.00000035  18.45  2004.9       3 193.5
+ 3499200  0.2031250  0.00000035  17.23  1872.4       3 232.4
+ 3500000  0.2421875  0.00000039  14.45  1570.8       3  99.1
+ 3500658  0.3066406  0.00000040  11.42  1240.9       2  20.0
+ 3512320  0.1901042  0.00000034  18.48  2008.7       3 103.7
+ 3515625  0.2656250  0.00000039  13.24  1439.0       2  23.2
+ 3528000  0.2096354  0.00000036  16.83  1830.2       3 213.1
+ 3529470  0.1875000  0.00000039  18.82  2047.2       31078.1
+ 3538944  0.1875000  0.00000037  18.87  2053.0       3 174.1
+ 3542940  0.2500000  0.00000037  14.17  1541.6       2  68.6
+ 3543750  0.2434896  0.00000036  14.55  1583.2       3  56.3
+ 3556224  0.2083333  0.00000037  17.07  1857.4       3 171.4
+ 3572100  0.2539062  0.00000035  14.07  1531.2       2   8.0
+ 3584000  0.2044271  0.00000033  17.53  1908.6       3 160.5
+ 3600000  0.2500000  0.00000036  14.40  1568.1       2 250.4
+ 3601500  0.3320312  0.00000036  10.85  1181.2       2  51.5
+ 3612672  0.2239583  0.00000039  16.13  1757.0       3  65.3
+ 3628800  0.2018229  0.00000035  17.98  1959.0       3 262.4
+ 3630312  0.2500000  0.00000039  14.52  1582.2       2 262.8
+ 3645000  0.2135417  0.00000036  17.07  1860.3       3  24.1
+ 3670016  0.1953125  0.00000037  18.79  2048.9       3 108.8
+ 3674160  0.2447917  0.00000036  15.01  1636.7       3 134.6
+ 3675000  0.2656250  0.00000038  13.84  1508.7       2  61.4
+ 3686400  0.1901042  0.00000034  19.39  2115.0       3   8.3
+ 3687936  0.2109375  0.00000036  17.48  1907.0       3 107.9
+ 3704400  0.2408854  0.00000037  15.38  1677.8       3 163.9
+ 3720087  0.3554688  0.00000040  10.47  1142.1       2  11.7
+ 3732480  0.2031250  0.00000035  18.38  2005.8       3 211.4
+ 3750000  0.2812500  0.00000040  13.33  1455.9       2  98.3
+ 3750705  0.3457031  0.00000039  10.85  1184.7       2  12.1
+ 3763200  0.2031250  0.00000033  18.53  2023.4       3 166.8
+ 3764768  0.2239583  0.00000038  16.81  1836.0       3  41.0
+ 3779136  0.2083333  0.00000038  18.14  1981.7       3   3.9
+ 3780000  0.2265625  0.00000037  16.68  1822.7       3 179.8
+ 3781575  0.2968750  0.00000037  12.74  1391.7       2  23.2
+ 3796875  0.2832031  0.00000037  13.41  1465.1       2  29.5
+ 3810240  0.2792969  0.00000036  13.64  1491.2       2 192.7
+ 3827250  0.2929688  0.00000037  13.06  1428.4       2  63.3
+ 3828125  0.3828125  0.00000038  10.00  1093.4       2  11.9
+ 3840000  0.2278646  0.00000035  16.85  1843.0       3 190.5
+ 3841600  0.1979167  0.00000037  19.41  2122.8       3  82.9
+ 3857868  0.3164062  0.00000039  12.19  1333.9       2  71.4
+ 3858750  0.2773438  0.00000036  13.91  1522.1       2  50.0
+ 3870720  0.2109375  0.00000034  18.35  2007.9       3 201.5
+ 3888000  0.2291667  0.00000036  16.97  1857.0       3 264.5
+ 3889620  0.2871094  0.00000038  13.55  1482.9       2  70.8
+ 3906250  0.3242188  0.00000044  12.05  1319.1       2  27.5
+ 3919104  0.2447917  0.00000036  16.01  1753.3       3 214.4
+ 3920000  0.1888021  0.00000037  20.76  2273.7       3  55.7
+ 3932160  0.2031250  0.00000034  19.36  2120.4       3 123.8
+ 3936600  0.2656250  0.00000035  14.82  1623.4       2 141.8
+ 3937500  0.2812500  0.00000038  14.00  1533.6       2 106.9
+ 3951360  0.2500000  0.00000035  15.81  1731.8       2 193.4
+ 3969000  0.2734375  0.00000037  14.52  1590.9       2 137.8
+ 3981312  0.2161458  0.00000035  18.42  2019.2       3 217.9
+ 4000000  0.2161458  0.00000038  18.51  2029.3       3   5.6
+ 4000752  0.2773438  0.00000038  14.43  1581.9       2 140.6
+ 4014080  0.2213542  0.00000036  18.13  1989.0       3 122.6
+ 4032000  0.2265625  0.00000034  17.80  1952.5       3 270.2
+ 4033680  0.2369792  0.00000037  17.02  1867.5       3 713.1
+ 4050000  0.2773438  0.00000037  14.60  1602.6       2 201.6
+ 4064256  0.2109375  0.00000037  19.27  2115.1       3   7.5
+ 4082400  0.2539062  0.00000035  16.08  1765.5       2 211.9
+ 4084101  0.4101562  0.00000041   9.96  1093.4       2  11.4
+ 4096000  0.2317708  0.00000034  17.67  1941.0       3 177.7
+ 4100625  0.3281250  0.00000036  12.50  1372.6       2  32.1
+ 4116000  0.3125000  0.00000037  13.17  1447.0       2 107.0
+ 4117715  0.2851562  0.00000040  14.44  1586.5       2 258.5
+ 4128768  0.2278646  0.00000036  18.12  1991.1       3 208.1
+ 4133430  0.3828125  0.00000038  10.80  1186.6       2  25.4
+ 4134375  0.3164062  0.00000036  13.07  1436.0       2  25.1
+ 4147200  0.1979167  0.00000034  20.95  2303.3       3  62.7
+ 4148928  0.2695312  0.00000037  15.39  1692.0       2 180.7
+ 4167450  0.3164062  0.00000038  13.17  1448.2       2  60.1
+ 4194304  0.2018229  0.00000038  20.78  2286.0       3   0.0
+ 4199040  0.2734375  0.00000036  15.36  1689.3       2 237.6
+ 4200000  0.3203125  0.00000037  13.11  1442.5       2 178.0
+ 4201750  0.2447917  0.00000040  17.16  1888.3       3 327.3
+ 4214784  0.2539062  0.00000035  16.60  1826.6       2 147.6
+ 4218750  0.3164062  0.00000038  13.33  1467.2       2  53.5
+ 4233600  0.2734375  0.00000036  15.48  1704.2       2 284.1
+ 4235364  0.4023438  0.00000040  10.53  1158.7       2  16.3
+ 4251528  0.2812500  0.00000039  15.12  1664.3       2  31.7
+ 4252500  0.3046875  0.00000036  13.96  1536.6       2 132.3
+ 4286520  0.2968750  0.00000036  14.44  1590.5       2  90.3
+ 4287500  0.3671875  0.00000039  11.68  1286.3       2  54.4
+ 4300800  0.2447917  0.00000036  17.57  1935.8       3 213.2
+ 4302592  0.2851562  0.00000037  15.09  1662.5       2 149.2
+ 4320000  0.2792969  0.00000036  15.47  1704.7       2 316.8
+ 4321800  0.2851562  0.00000036  15.16  1670.4       2  19.2
+ 4354560  0.2578125  0.00000035  16.89  1862.5       2 264.7
+ 4374000  0.3007812  0.00000035  14.54  1604.0       2 225.5
+ 4375000  0.3574219  0.00000040  12.24  1350.2       2  69.3
+ 4390400  0.2558594  0.00000036  17.16  1893.2       2 204.6
+ 4408992  0.2968750  0.00000038  14.85  1639.0       2 162.1
+ 4410000  0.2539062  0.00000036  17.37  1916.8       2   0.6
+ 4423680  0.2434896  0.00000036  18.17  2005.4       3 250.7
+ 4428675  0.3574219  0.00000037  12.39  1367.8       2  32.5
+ 4445280  0.2968750  0.00000036  14.97  1653.4       2 159.3
+ 4465125  0.3554688  0.00000036  12.56  1387.4       2  33.4
+ 4478976  0.2617188  0.00000036  17.11  1890.6       2 276.6
+ 4480000  0.2617188  0.00000036  17.12  1891.1       2 223.8
+ 4500000  0.2617188  0.00000039  17.19  1900.1       2  57.2
+ 4500846  0.4355469  0.00000040  10.33  1142.0       2  24.3
+ 4501875  0.4296875  0.00000036  10.48  1157.8       2  12.4
+ 4515840  0.2617188  0.00000034  17.25  1907.2       2 253.2
+ 4536000  0.2871094  0.00000035  15.80  1746.8       2 325.8
+ 4537890  0.3027344  0.00000039  14.99  1657.4       2 320.1
+ 4556250  0.3437500  0.00000036  13.25  1465.9       2  66.1
+ 4572288  0.2695312  0.00000038  16.96  1876.6       2  74.7
+ 4587520  0.2578125  0.00000036  17.79  1968.8       2 158.1
+ 4592700  0.3437500  0.00000037  13.36  1478.4       2 140.3
+ 4593750  0.3945312  0.00000039  11.64  1288.4       2  28.8
+ 4608000  0.2578125  0.00000034  17.87  1978.2       2 340.9
+ 4609920  0.2395833  0.00000039  19.24  2129.7       32210.2
+ 4630500  0.3632812  0.00000037  12.75  1411.2       2 114.0
+ 4644864  0.2734375  0.00000037  16.99  1881.1       2 285.7
+ 4665600  0.2434896  0.00000034  19.16  2122.5       3   6.7
+ 4667544  0.3300781  0.00000039  14.14  1566.4       2  89.8
+ 4687500  0.3984375  0.00000041  11.76  1303.6       2  56.3
+ 4704000  0.2968750  0.00000035  15.85  1756.1       2 220.9
+ 4705960  0.3691406  0.00000039  12.75  1412.9       2 105.9
+ 4718592  0.2174479  0.00000040  21.70  2405.4       3  72.1
+ 4723920  0.3281250  0.00000038  14.40  1596.0       2 169.1
+ 4725000  0.3515625  0.00000036  13.44  1490.0       2 140.8
+ 4741632  0.2929688  0.00000037  16.18  1794.6       2 253.3
+ 4762800  0.3320312  0.00000036  14.34  1591.0       2 240.0
+ 4782969  0.5156250  0.00000040   9.28  1029.2       1  13.0
+ 4800000  0.2968750  0.00000036  16.17  1794.3       2 229.5
+ 4802000  0.4023438  0.00000037  11.94  1324.5       2 116.1
+ 4816896  0.2812500  0.00000037  17.13  1901.0       2 164.4
+ 4822335  0.4785156  0.00000039  10.08  1118.7       2  15.1
+ 4838400  0.2890625  0.00000034  16.74  1858.5       2 361.3
+ 4840416  0.3789062  0.00000038  12.77  1418.4       2 154.4
+ 4860000  0.3359375  0.00000034  14.47  1606.7       2 265.2
+ 4862025  0.4023438  0.00000037  12.08  1342.1       2  32.2
+ 4898880  0.3359375  0.00000036  14.58  1620.4       2 266.8
+ 4900000  0.3984375  0.00000038  12.30  1366.6       2 129.7
+ 4915200  0.2792969  0.00000035  17.60  1956.0       2 235.8
+ 4917248  0.2851562  0.00000037  17.24  1916.6       2  83.4
+ 4920750  0.3945312  0.00000037  12.47  1386.3       2  69.9
+ 4921875  0.4160156  0.00000039  11.83  1315.1       2  27.0
+ 4939200  0.3515625  0.00000036  14.05  1562.0       2 313.4
+ 4941258  0.2890625  0.00000040  17.09  1900.6       21075.4
+ 4960116  0.3984375  0.00000039  12.45  1384.4       2  86.7
+ 4961250  0.3828125  0.00000036  12.96  1441.3       2  67.9
+ 4976640  0.2968750  0.00000035  16.76  1864.7       2 313.5
+ 5000000  0.3847656  0.00000040  12.99  1445.9       2 196.8
+ 5000940  0.3769531  0.00000038  13.27  1476.2       2  86.5
+ 5017600  0.2636719  0.00000034  19.03  2117.9       2  11.5
+ 5038848  0.3261719  0.00000038  15.45  1719.8       2 302.6
+ 5040000  0.3359375  0.00000035  15.00  1670.2       2 334.0
+ 5042100  0.4882812  0.00000037  10.33  1149.6       2  60.3
+ 5062500  0.3593750  0.00000038  14.09  1568.7       2  11.2
+ 5080320  0.3281250  0.00000036  15.48  1724.5       2 299.5
+ 5103000  0.3593750  0.00000035  14.20  1582.0       2 175.8
+ 5120000  0.2408854  0.00000035  21.25  2368.6       3  71.2
+ 5143824  0.3085938  0.00000040  16.67  1858.1       2   0.5
+ 5145000  0.4433594  0.00000038  11.60  1293.6       2  75.3
+ 5160960  0.3125000  0.00000035  16.52  1841.4       2 297.8
+ 5184000  0.3125000  0.00000034  16.59  1850.1       2 403.2
+ 5186160  0.4394531  0.00000038  11.80  1316.2       2 152.2
+ 5225472  0.3261719  0.00000037  16.02  1787.7       2 321.9
+ 5242880  0.3085938  0.00000036  16.99  1896.2       2 173.9
+ 5248800  0.3125000  0.00000036  16.80  1874.8       2  66.8
+ 5250000  0.4433594  0.00000037  11.84  1321.7       2 129.8
+ 5250987  0.5625000  0.00000042   9.34  1042.0       1  14.6
+ 5268480  0.3281250  0.00000035  16.06  1792.6       2 178.8
+ 5292000  0.4238281  0.00000035  12.49  1394.4       2 248.5
+ 5294205  0.3398438  0.00000040  15.58  1739.8       2 854.9
+ 5308416  0.2714844  0.00000039  19.55  2184.1       2  12.2
+ 5314410  0.7187500  0.00000039   7.39   826.0       1  26.6
+ 5315625  0.4472656  0.00000036  11.88  1327.6       2  36.1
+ 5334336  0.4023438  0.00000038  13.26  1481.4       2 264.8
+ 5358150  0.4257812  0.00000037  12.58  1406.5       2  68.7
+ 5359375  0.5156250  0.00000037  10.39  1161.7       1  12.1
+ 5376000  0.3281250  0.00000034  16.38  1831.6       2   0.1
+ 5378240  0.2968750  0.00000040  18.12  2025.3       2 787.2
+ 5400000  0.3828125  0.00000036  14.11  1577.4       2 347.4
+ 5402250  0.4316406  0.00000037  12.52  1399.6       2  55.7
+ 5419008  0.3359375  0.00000035  16.13  1804.2       2 297.0
+ 5443200  0.3515625  0.00000036  15.48  1732.2       2 379.8
+ 5445468  0.4316406  0.00000039  12.62  1411.5       2  88.1
+ 5467500  0.4179688  0.00000037  13.08  1463.9       2 151.9
+ 5468750  0.4921875  0.00000042  11.11  1243.5       2  29.9
+ 5488000  0.4375000  0.00000036  12.54  1404.2       2 214.7
+ 5505024  0.3437500  0.00000036  16.01  1793.0       2 183.2
+ 5511240  0.4140625  0.00000037  13.31  1490.3       2 101.7
+ 5512500  0.4531250  0.00000037  12.17  1362.2       2 131.3
+ 5529600  0.3515625  0.00000036  15.73  1761.5       2 406.8
+ 5531904  0.2968750  0.00000041  18.63  2086.9       2 146.9
+ 5556600  0.4101562  0.00000037  13.55  1517.7       2 173.0
+ 5598720  0.3671875  0.00000036  15.25  1709.0       2 325.2
+ 5600000  0.3945312  0.00000037  14.19  1590.9       2 255.2
+ 5619712  0.3554688  0.00000037  15.81  1772.4       2 185.3
+ 5625000  0.4921875  0.00000039  11.43  1281.3       2 159.7
+ 5644800  0.3359375  0.00000035  16.80  1884.3       2  97.0
+ 5647152  0.4609375  0.00000040  12.25  1373.9       2  95.8
+ 5668704  0.4179688  0.00000038  13.56  1521.3       2 198.0
+ 5670000  0.4017181  0.00000037  14.11  1583.3       2 273.5
+ 5715360  0.3860931  0.00000036  14.80  1661.4       2 194.0
+ 5734400  0.3470764  0.00000035  16.52  1854.7       2 262.5
+ 5740875  0.4953308  0.00000037  11.59  1301.1       2  37.5
+ 5760000  0.3237000  0.00000036  17.79  1998.1       2   9.6
+ 5762400  0.6240234  0.00000037   9.23  1036.9       1 137.1
+ 5764801  0.6083984  0.00000040   9.48  1064.0       1  38.1
+ 5786802  0.8346558  0.00000039   6.93   778.7       1  29.9
+ 5788125  0.4913940  0.00000035  11.78  1323.1       2  30.0
+ 5806080  0.3510742  0.00000035  16.54  1858.0       2 337.2
+ 5832000  0.4094849  0.00000034  14.24  1600.5       2 386.0
+ 5834430  0.3822021  0.00000040  15.27  1715.5       21338.4
+ 5859375  0.5615234  0.00000041  10.43  1173.0       1  13.2
+ 5878656  0.3822021  0.00000038  15.38  1729.4       2 293.4
+ 5880000  0.4484863  0.00000037  13.11  1474.1       2 214.2
+ 5882450  0.5227051  0.00000039  11.25  1265.4       1  59.4
+ 5898240  0.3548584  0.00000035  16.62  1869.2       2 310.8
+ 5904900  0.4056396  0.00000037  14.56  1637.2       2  12.4
+ 5906250  0.4758301  0.00000038  12.41  1396.0       2  59.8
+ 5927040  0.3781738  0.00000036  15.67  1763.1       2 265.6
+ 5953500  0.4445801  0.00000037  13.39  1506.9       2 155.4
+ 5971968  0.3041992  0.00000037  19.63  2209.5       2  88.3
+ 6000000  0.4562988  0.00000038  13.15  1480.4       2 228.2
+ 6001128  0.4406738  0.00000040  13.62  1533.2       2 102.2
+ 6002500  0.4135742  0.00000038  14.51  1634.0       2  12.7
+ 6021120  0.3745117  0.00000036  16.08  1810.4       2 187.8
+ 6048000  0.3820801  0.00000035  15.83  1783.0       2 418.0
+ 6050520  0.3823242  0.00000039  15.83  1782.6       2 937.1
+ 6075000  0.4484863  0.00000036  13.55  1526.2       2 189.3
+ 6096384  0.3940430  0.00000038  15.47  1743.6       2 331.0
+ 6123600  0.4328613  0.00000036  14.15  1594.8       2 286.7
+ 6125000  0.3898926  0.00000039  15.71  1770.9       2  39.3
+ 6144000  0.3745117  0.00000036  16.41  1849.8       2 280.3
+ 6146560  0.3940430  0.00000036  15.60  1758.9       2 182.6
+ 6174000  0.5029297  0.00000037  12.28  1384.6       2 255.1
+ 6193152  0.3862305  0.00000036  16.03  1808.9       2 326.8
+ 6200145  0.8808594  0.00000039   7.04   794.1       1  18.0
+ 6220800  0.4174805  0.00000034  14.90  1681.5       2 470.0
+ 6223392  0.4013672  0.00000039  15.51  1749.7       2  77.3
+ 6250000  0.3549805  0.00000042  17.61  1987.4       2   0.8
+ 6251175  0.6708984  0.00000037   9.32  1051.8       1  40.9
+ 6272000  0.4018555  0.00000036  15.61  1762.1       2 283.9
+ 6291456  0.4018555  0.00000037  15.66  1768.0       2 193.6
+ 6298560  0.4365234  0.00000036  14.43  1629.5       2 301.4
+ 6300000  0.4912109  0.00000037  12.83  1448.4       2 286.1
+ 6302625  0.4407043  0.00000036  14.30  1615.1       2 136.0
+ 6322176  0.4095001  0.00000037  15.44  1744.0       2 325.8
+ 6328125  0.5538025  0.00000038  11.43  1290.8       1  41.0
+ 6350400  0.3705139  0.00000034  17.14  1936.6       2   5.8
+ 6353046  0.3665771  0.00000041  17.33  1958.3       22314.9
+ 6377292  0.5068359  0.00000039  12.58  1422.1       1  95.6
+ 6378750  0.5070801  0.00000036  12.58  1421.8       1  78.5
+ 6400000  0.4016113  0.00000036  15.94  1801.5       2 286.2
+ 6422528  0.3159180  0.00000038  20.33  2298.8       2  96.1
+ 6429780  0.4914551  0.00000038  13.08  1479.5       2  95.2
+ 6431250  0.5615234  0.00000038  11.45  1295.2       1  31.3
+ 6451200  0.4095459  0.00000035  15.75  1781.6       2 451.0
+ 6453888  0.3781738  0.00000040  17.07  1930.3       21022.9
+ 6480000  0.3393555  0.00000036  19.10  2160.4       2  87.7
+ 6482700  0.5302734  0.00000038  12.23  1383.2       1 137.3
+ 6531840  0.4250488  0.00000036  15.37  1739.5       2 358.8
+ 6553600  0.3510742  0.00000034  18.67  2113.5       2  12.8
+ 6561000  0.4758301  0.00000036  13.79  1561.2       2 217.3
+ 6562500  0.5693359  0.00000040  11.53  1305.1       1  84.2
+ 6585600  0.4562988  0.00000036  14.43  1634.6       2 289.7
+ 6588344  0.3977051  0.00000040  16.57  1876.2       2 935.8
+ 6613488  0.4953613  0.00000040  13.35  1512.4       2 202.4
+ 6615000  0.5385742  0.00000036  12.28  1391.4       1 195.3
+ 6635520  0.4289551  0.00000037  15.47  1752.8       2 379.4
+ 6667920  0.4875488  0.00000038  13.68  1550.1       2 196.6
+ 6718464  0.3706055  0.00000039  18.13  2055.7       2  10.4
+ 6720000  0.4482422  0.00000036  14.99  1700.1       2 305.9
+ 6722800  0.6005859  0.00000036  11.19  1269.4       1 157.9
+ 6750000  0.5380859  0.00000037  12.54  1422.9       1 309.3
+ 6751269  1.0058594  0.00000042   6.71   761.4       1  16.3
+ 6773760  0.4365234  0.00000036  15.52  1760.6       2 349.1
+ 6804000  0.4873047  0.00000036  13.96  1584.6       2 351.9
+ 6806835  0.5068359  0.00000041  13.43  1524.2       1 370.3
+ 6834375  0.6162109  0.00000037  11.09  1259.1       1  51.1
+ 6858432  0.5069885  0.00000038  13.53  1536.0       1 317.7
+ 6860000  0.5849915  0.00000037  11.73  1331.5       1 179.2
+ 6881280  0.4446411  0.00000036  15.48  1757.6       2 207.5
+ 6889050  0.6162109  0.00000039  11.18  1269.8       1  87.6
+ 6890625  0.6630249  0.00000038  10.39  1180.4       1  41.6
+ 6912000  0.4523926  0.00000034  15.28  1735.7       2 504.3
+ 6914880  0.4874878  0.00000037  14.18  1611.5       2 292.6
+ 6945750  0.6083984  0.00000037  11.42  1297.3       1  85.7
+ 6967296  0.4680176  0.00000036  14.89  1692.0       2 384.5
+ 6998400  0.4641113  0.00000036  15.08  1714.4       2 487.5
+ 7000000  0.5695801  0.00000039  12.29  1397.3       1 268.5
+ 7001316  0.4874268  0.00000041  14.36  1633.1       2  21.2
+ 7024640  0.4600830  0.00000036  15.27  1736.3       2 211.8
+ 7031250  0.6315918  0.00000041  11.13  1266.1       1  80.7
+ 7056000  0.4913330  0.00000036  14.36  1633.6       2 447.8
+ 7058940  0.5695801  0.00000039  12.39  1409.8       1 109.7
+ 7077888  0.4758301  0.00000039  14.87  1692.4       2 355.4
+ 7085880  0.5537109  0.00000037  12.80  1456.1       1 117.4
+ 7087500  0.5693359  0.00000038  12.45  1416.5       1 207.9
+ 7112448  0.4797363  0.00000038  14.83  1687.3       2 374.1
+ 7144200  0.4794922  0.00000036  14.90  1696.2       2  46.3
+ 7168000  0.4641113  0.00000036  15.44  1758.6       2 332.2
+ 7200000  0.4758301  0.00000037  15.13  1723.4       2 509.2
+ 7203000  0.4370117  0.00000038  16.48  1877.4       22741.6
+ 7225344  0.4331055  0.00000040  16.68  1900.5       2  12.6
+ 7257600  0.4677734  0.00000034  15.52  1768.0       2 544.6
+ 7260624  0.7324219  0.00000040   9.91  1129.7       1 188.1
+ 7290000  0.4130859  0.00000037  17.65  2011.6       2   1.1
+ 7340032  0.4956055  0.00000038  14.81  1688.9       2 217.9
+ 7348320  0.5546875  0.00000037  13.25  1510.8       1 230.6
+ 7350000  0.6474609  0.00000037  11.35  1294.7       1 171.5
+ 7372800  0.3901367  0.00000036  18.90  2155.7       2 105.4
+ 7375872  0.5460052  0.00000038  13.51  1541.0       1 227.5
+ 7381125  0.6941833  0.00000038  10.63  1213.0       1  50.2
+ 7408800  0.6240234  0.00000037  11.87  1354.7       1 336.3
+ 7411887  0.6707764  0.00000041  11.05  1260.9       1 117.5
+ 7440174  1.0841675  0.00000042   6.86   783.3       1  30.1
+ 7441875  0.7254028  0.00000037  10.26  1170.9       1  54.8
+ 7464960  0.4757690  0.00000036  15.69  1791.2       2 417.9
+ 7500000  0.6318359  0.00000040  11.87  1355.5       1 188.6
+ 7501410  1.0607910  0.00000040   7.07   807.5       1  30.0
+ 7503125  0.7409668  0.00000037  10.13  1156.4       1  19.1
+ 7526400  0.4953003  0.00000034  15.20  1735.6       2 342.9
+ 7529536  0.4445801  0.00000039  16.94  1934.5       2  81.8
+ 7558272  0.4484863  0.00000039  16.85  1925.4       2 104.2
+ 7560000  0.5383301  0.00000036  14.04  1604.5       1 482.3
+ 7563150  0.7019043  0.00000037  10.78  1231.1       1  75.1
+ 7593750  0.6787109  0.00000039  11.19  1278.6       1 101.1
+ 7620480  0.5070801  0.00000036  15.03  1717.8       1 350.3
+ 7654500  0.6240234  0.00000036  12.27  1402.5       1 206.5
+ 7656250  0.6940918  0.00000041  11.03  1261.3       1  38.9
+ 7680000  0.5148926  0.00000035  14.92  1705.8       1 365.4
+ 7683200  0.4056396  0.00000038  18.94  2166.2       2 149.6
+ 7715736  0.6005859  0.00000039  12.85  1469.7       1 121.5
+ 7717500  0.6865234  0.00000038  11.24  1286.0       1 184.5
+ 7741440  0.5458984  0.00000037  14.18  1622.6       1 396.1
+ 7776000  0.5068359  0.00000034  15.34  1756.0       1 575.2
+ 7779240  0.6162109  0.00000038  12.62  1444.9       1 120.9
+ 7812500  0.7021484  0.00000044  11.13  1273.8       1  86.5
+ 7838208  0.5615234  0.00000038  13.96  1598.4       1 423.3
+ 7840000  0.4562988  0.00000037  17.18  1967.5       2   8.2
+ 7864320  0.5458984  0.00000036  14.41  1650.0       1 236.4
+ 7873200  0.6083984  0.00000036  12.94  1482.3       1 367.4
+ 7875000  0.6865234  0.00000038  11.47  1313.9       1 222.0
+ 7902720  0.5224609  0.00000036  15.13  1733.0       1 368.5
+ 7938000  0.6240234  0.00000036  12.72  1457.8       1 364.1
+ 7962624  0.5229492  0.00000039  15.23  1745.3       1 428.4
+ 7971615  1.1934090  0.00000040   6.68   765.7       1  18.5
+ 8000000  0.3900032  0.00000038  20.51  2351.9       2 100.6
+ 8001504  0.6473999  0.00000040  12.36  1417.1       1 238.7
+ 8028160  0.5538330  0.00000036  14.50  1662.4       1 235.0
+ 8037225  0.8346558  0.00000038   9.63  1104.4       1  51.4
+ 8064000  0.5303955  0.00000034  15.20  1744.1       1 566.5
+ 8067360  0.5693359  0.00000039  14.17  1625.5       11110.6
+ 8100000  0.6240234  0.00000036  12.98  1489.5       1 410.8
+ 8103375  0.8269043  0.00000037   9.80  1124.5       1  39.7
+ 8128512  0.4094238  0.00000039  19.85  2278.6       2 108.6
+ 8164800  0.5771484  0.00000036  14.15  1624.1       1 521.5
+ 8168202  0.5615234  0.00000042  14.55  1670.1       1 447.0
+ 8192000  0.6083984  0.00000034  13.46  1546.2       1 358.7
+ 8201250  0.7568359  0.00000038  10.84  1244.4       1 116.2
+ 8203125  0.7958984  0.00000040  10.31  1183.6       1  20.9
+ 8232000  0.6865234  0.00000037  11.99  1377.3       1 275.3
+ 8235430  0.7412109  0.00000040  11.11  1276.3       1  53.7
+ 8257536  0.5385742  0.00000039  15.33  1761.5       1 403.0
+ 8266860  0.6938477  0.00000038  11.91  1368.9       1 105.3
+ 8268750  0.7563477  0.00000038  10.93  1256.1       1  91.4
+ 8294400  0.4448242  0.00000034  18.65  2142.8       2  13.5
+ 8297856  0.5620117  0.00000038  14.76  1696.8       1 324.3
+ 8334900  0.7021484  0.00000038  11.87  1364.6       1 213.0
+ 8388608  0.4135742  0.00000038  20.28  2332.6       2   0.0
diff --git a/lib/options.f90 b/lib/options.f90
new file mode 100644
index 0000000..401d4a6
--- /dev/null
+++ b/lib/options.f90
@@ -0,0 +1,337 @@
+module options
+  !
+  ! Source code copied from:
+  ! http://fortranwiki.org/fortran/show/Command-line+arguments
+  !
+  implicit none
+
+  type option
+     !> Long name.
+     character(len=100) :: name
+     !> Does the option require an argument?
+     logical :: has_arg
+     !> Corresponding short name.
+     character :: chr
+     !> Description.
+     character(len=500) :: descr
+     !> Argument name, if required.
+     character(len=20) :: argname
+   contains
+     procedure :: print => print_opt
+  end type option
+
+contains
+
+  !> Parse command line options. Options and their arguments must come before
+  !> all non-option arguments. Short options have the form "-X", long options
+  !> have the form "--XXXX..." where "X" is any character. Parsing can be
+  !> stopped with the option '--'.
+  !> The following code snippet illustrates the intended use:
+  !> \code
+  !> do
+  !>   call getopt (..., optchar=c, ...)
+  !>   if (stat /= 0) then
+  !>     ! optional error handling
+  !>     exit
+  !>   end if
+  !>   select case (c)
+  !>     ! process options
+  !>   end select
+  !> end do
+  !> \endcode
+  subroutine getopt (options, longopts, optchar, optarg, arglen, stat, &
+       offset, remain, err)
+    use iso_fortran_env, only: error_unit
+
+    !> String containing the characters that are valid short options. If
+    !> present, command line arguments are scanned for those options.
+    !> If a character is followed by a colon (:) its corresponding option
+    !> requires an argument. E.g. "vn:" defines two options -v and -n with -n
+    !> requiring an argument.
+    character(len=*), intent(in), optional :: options
+
+    !> Array of long options. If present, options of the form '--XXXX...' are
+    !> recognised. Each option has an associated option character. This can be
+    !> any character of default kind, it is just an identifier. It can, but
+    !> doesn't have to, match any character in the options argument. In fact it
+    !> is possible to only pass long options and no short options at all.
+    !> Only name, has_arg and chr need to be set.
+    type(option), intent(in), optional :: longopts(:)
+
+    !> If stat is not 1, optchar contains the option character that was parsed.
+    !> Otherwise its value is undefined.
+    character, intent(out), optional :: optchar
+
+    !> If stat is 0 and the parsed option requires an argument, optarg contains
+    !> the first len(optarg) (but at most 500) characters of that argument.
+    !> Otherwise its value is undefined. If the arguments length exceeds 500
+    !> characters and err is .true., a warning is issued.
+    character(len=*), intent(out), optional :: optarg
+
+    !> If stat is 0 and the parsed option requires an argument, arglen contains
+    !> the actual length of that argument. Otherwise its value is undefined.
+    !> This can be used to make sure the argument was not truncated by the
+    !> limited length of optarg.
+    integer, intent(out), optional :: arglen
+
+    !> Status indicator. Can have the following values:
+    !>   -  0: An option was successfully parsed.
+    !>   -  1: Parsing stopped successfully because a non-option or '--' was
+    !>         encountered.
+    !>   - -1: An unrecognised option was encountered.
+    !>   - -2: A required argument was missing.
+    !>   .
+    !> Its value is never undefined.
+    integer, intent(out), optional :: stat
+
+    !> If stat is 1, offset contains the number of the argument before the
+    !> first non-option argument, i.e. offset+n is the nth non-option argument.
+    !> If stat is not 1, offset contains the number of the argument that would
+    !> be parsed in the next call to getopt. This number can be greater than
+    !> the actual number of arguments.
+    integer, intent(out), optional :: offset
+
+    !> If stat is 1, remain contains the number of remaining non-option
+    !> arguments, i.e. the non-option arguments are in the range 
+    !> (offset+1:offset+remain). If stat is not 1, remain is undefined.
+    integer, intent(out), optional :: remain
+
+    !> If err is present and .true., getopt prints messages to the standard
+    !> error unit if an error is encountered (i.e. whenever stat would be set
+    !> to a negative value).
+    logical, intent(in), optional :: err
+
+    integer, save :: pos = 1, cnt = 0
+    character(len=500), save :: arg
+
+    integer :: chrpos, length, st, id = 0
+    character :: chr
+    logical :: long
+
+    if (cnt == 0) cnt = command_argument_count()
+    long = .false.
+
+    ! no more arguments left
+    if (pos > cnt) then
+       pos = pos - 1
+       st = 1
+       goto 10
+    end if
+
+    call get_command_argument (pos, arg, length)
+
+    ! is argument an option?
+    if (arg(1:1) == '-') then
+
+       chr = arg(2:2)
+
+       ! too long ('-xxxx...') for one dash?
+       if (chr /= '-' .and. len_trim(arg) > 2) then
+          st = -1
+          goto 10
+       end if
+
+       ! forced stop ('--')
+       if (chr == '-' .and. arg(3:3) == ' ') then
+          st = 1
+          goto 10
+       end if
+
+       ! long option ('--xxx...')
+       if (chr == '-') then
+
+          long = .true.
+
+          ! check if valid
+          id = lookup(arg(3:))
+
+          ! option is invalid, stop
+          if (id == 0) then
+             st = -1
+             goto 10
+          end if
+
+          chr = longopts(id)%chr
+
+          ! check if option requires an argument
+          if (.not. longopts(id)%has_arg) then
+             st = 0
+             goto 10
+          end if
+
+          ! check if there are still arguments left
+          if (pos == cnt) then
+             st = -2
+             goto 10
+          end if
+
+          ! go to next position
+          pos = pos + 1
+
+          ! get argument
+          call get_command_argument (pos, arg, length)
+
+          ! make sure it is not an option
+          if (arg(1:1) == '-') then
+             st = -2
+             pos = pos - 1
+             goto 10
+          end if
+
+       end if
+
+       ! short option
+       ! check if valid
+       if (present(options)) then
+          chrpos = scan(options, chr)
+       else
+          chrpos = 0
+       end if
+
+       ! option is invalid, stop
+       if (chrpos == 0) then
+          st = -1
+          goto 10
+       end if
+
+       ! look for argument requirement
+       if (chrpos < len_trim(options)) then
+          if (options(chrpos+1:chrpos+1) == ':') then
+
+             ! check if there are still arguments left
+             if (pos == cnt) then
+                st = -2
+                goto 10
+             end if
+
+             ! go to next position
+             pos = pos + 1
+
+             ! get argument
+             call get_command_argument (pos, arg, length)
+
+             ! make sure it is not an option
+             if (arg(1:1) == '-') then
+                st = -2
+                pos = pos - 1
+                goto 10
+             end if
+
+          end if
+       end if
+
+       ! if we get to this point, no error happened
+       ! return option and the argument (if there is one)
+       st = 0
+       goto 10
+    end if
+
+    ! not an option, parsing stops
+    st = 1
+    ! we are already at the first non-option argument
+    ! go one step back to the last option or option argument
+    pos = pos - 1
+
+
+    ! error handling and setting of return values
+10  continue
+
+    if (present(err)) then
+       if (err) then
+
+          select case (st)
+          case (-1)
+             write (error_unit, *) "error: unrecognised option: " // trim(arg) 
+          case (-2)
+             if (.not. long) then
+                write (error_unit, *) "error: option -" // chr &
+                     // " requires an argument"
+             else
+                write (error_unit, *) "error: option --" &
+                     // trim(longopts(id)%name) // " requires an argument"
+             end if
+          end select
+
+       end if
+    end if
+
+    if (present(optchar)) optchar = chr
+    if (present(optarg))  optarg  = arg
+    if (present(arglen))  arglen  = length
+    if (present(stat))    stat    = st
+    if (present(offset))  offset  = pos
+    if (present(remain))  remain  = cnt-pos
+
+    ! setup pos for next call to getopt
+    pos = pos + 1
+
+  contains
+
+    integer function lookup (name)
+      character(len=*), intent(in) :: name
+      integer :: i
+
+      ! if there are no long options, skip the loop
+      if (.not. present(longopts)) goto 10
+
+      do i = 1, size(longopts)
+         if (name == longopts(i)%name) then
+            lookup = i
+            return
+         end if
+      end do
+      ! if we get to this point, the option was not found
+
+10    lookup = 0
+    end function lookup
+
+  end subroutine getopt
+
+  !============================================================================
+
+  !> Print an option in the style of a man page. I.e.
+  !> \code
+  !> -o arg
+  !> --option arg
+  !>    description.................................................................
+  !>    ............................................................................
+  !> \endcode
+  subroutine print_opt (opt, unit)
+    !> the option
+    class(option), intent(in) :: opt
+    !> logical unit number
+    integer, intent(in) :: unit
+
+    integer :: l, c1, c2
+
+    if (opt%has_arg) then
+       write (unit, '(1x,"-",a,1x,a)') opt%chr, trim(opt%argname)
+       write (unit, '(1x,"--",a,1x,a)') trim(opt%name), trim(opt%argname)
+    else
+       write (unit, '(1x,"-",a)') opt%chr
+       write (unit, '(1x,"--",a)') trim(opt%name)
+    end if
+    l = len_trim(opt%descr)
+
+    ! c1 is the first character of the line
+    ! c2 is one past the last character of the line
+    c1 = 1
+    do
+       if (c1 > l) exit
+       ! print at maximum 4+76 = 80 characters
+       c2 = min(c1 + 76, 500)
+       ! if not at the end of the whole string
+       if (c2 /= 500) then
+          ! find the end of a word
+          do
+             if (opt%descr(c2:c2) == ' ') exit
+             c2 = c2-1
+          end do
+       end if
+       write (unit, '(4x,a)') opt%descr(c1:c2-1)
+       c1 = c2+1
+    end do
+
+  end subroutine print_opt
+
+end module options
diff --git a/lib/packmsg.f90 b/lib/packmsg.f90
index 6c7619b..0048508 100644
--- a/lib/packmsg.f90
+++ b/lib/packmsg.f90
@@ -1,4 +1,16 @@
-subroutine packmsg(msg,dat,text)
+subroutine packmsg(msg,dat,itype)
+
+! Packs a JT4/JT9/JT65 message into twelve 6-bit symbols
+
+! itype Message Type
+!--------------------
+!   1   Standardd message
+!   2   Type 1 prefix
+!   3   Type 1 suffix
+!   4   Type 2 prefix
+!   5   Type 2 suffix
+!   6   Free text
+!  -1   Does not decode correctly
 
   parameter (NBASE=37*36*10*27*27*27)
   parameter (NBASE2=262178562)
@@ -7,24 +19,12 @@ subroutine packmsg(msg,dat,text)
   character*12 c1,c2
   character*4 c3
   character*6 grid6
-  logical text1,text2,text3,text
+  logical text1,text2,text3
 
-  text=.false.
-! Convert all letters to upper case
-  iz=22
-  do i=1,22
-     if(msg(i:i).ge.'a' .and. msg(i:i).le.'z')                       &
-          msg(i:i)= char(ichar(msg(i:i))+ichar('A')-ichar('a'))
-     if(msg(i:i).ne.' ') iz=i
-  enddo
-  do iter=1,5                           !Collapse multiple blanks into one
-     ib2=index(msg(1:iz),'  ')
-     if(ib2.lt.1) go to 5
-     msg=msg(1:ib2)//msg(ib2+2:)
-     iz=iz-1
-  enddo
+  itype=1
+  call fmtmsg(msg,iz)
 
-5 if(msg(1:6).eq.'CQ DX ') msg(3:3)='9'
+  if(msg(1:6).eq.'CQ DX ') msg(3:3)='9'
 
 ! See if it's a CQ message
   if(msg(1:3).eq.'CQ ') then
@@ -60,11 +60,14 @@ subroutine packmsg(msg,dat,text)
   c3='    '
   if(ic.ge.ib+1) c3=msg(ib+1:ic)
   if(c3.eq.'OOO ') c3='    '           !Strip out the OOO flag
-  call getpfx1(c1,k1,junk)
+  call getpfx1(c1,k1,nv2a)
+  if(nv2a.ge.4) go to 10
   call packcall(c1,nc1,text1)
-  call getpfx1(c2,k2,nv2)
+  if(text1) go to 10
+  call getpfx1(c2,k2,nv2b)
   call packcall(c2,nc2,text2)
-  if(nv2.eq.0) then
+  if(text2) go to 10
+  if(nv2a.eq.2 .or. nv2a.eq.3 .or. nv2b.eq.2 .or. nv2b.eq.3) then
      if(k1.lt.0 .or. k2.lt.0 .or. k1*k2.ne.0) go to 10
      if(k2.gt.0) k2=k2+450
      k=max(k1,k2)
@@ -74,29 +77,31 @@ subroutine packmsg(msg,dat,text)
      endif
   endif
   call packgrid(c3,ng,text3)
-  if(nv2.eq.0 .and. (.not.text1) .and. (.not.text2) .and.           &
+
+  if(nv2a.lt.4 .and. nv2b.lt.4 .and. (.not.text1) .and. (.not.text2) .and.  &
        (.not.text3)) go to 20
-  if(nv2.gt.0) then
-     if(nv2.eq.1) then
-        if(c1(1:3).eq.'CQ ')  nc1=262178563 + k2
-        if(c1(1:4).eq.'QRZ ') nc1=264002072 + k2 
-        if(c1(1:3).eq.'DE ')  nc1=265825581 + k2
-     endif
-     if(nv2.eq.2) then
-        if(c1(1:3).eq.'CQ ')  nc1=267649090 + k2
-        if(c1(1:4).eq.'QRZ ') nc1=267698375 + k2
-        if(c1(1:3).eq.'DE ')  nc1=267747660 + k2
-     endif
-     go to 20
+
+  nc1=0
+  if(nv2b.eq.4) then
+     if(c1(1:3).eq.'CQ ')  nc1=262178563 + k2
+     if(c1(1:4).eq.'QRZ ') nc1=264002072 + k2 
+     if(c1(1:3).eq.'DE ')  nc1=265825581 + k2
+  else if(nv2b.eq.5) then
+     if(c1(1:3).eq.'CQ ')  nc1=267649090 + k2
+     if(c1(1:4).eq.'QRZ ') nc1=267698375 + k2
+     if(c1(1:3).eq.'DE ')  nc1=267747660 + k2
   endif
+  if(nc1.ne.0) go to 20
 
 ! The message will be treated as plain text.
-10 text=.true.
+10 itype=6
   call packtext(msg,nc1,nc2,ng)
   ng=ng+32768
 
 ! Encode data into 6-bit words
-20 dat(1)=iand(ishft(nc1,-22),63)               !6 bits
+20 continue
+  if(itype.ne.6) itype=max(nv2a,nv2b)
+  dat(1)=iand(ishft(nc1,-22),63)                !6 bits
   dat(2)=iand(ishft(nc1,-16),63)                !6 bits
   dat(3)=iand(ishft(nc1,-10),63)                !6 bits
   dat(4)=iand(ishft(nc1, -4),63)                !6 bits
@@ -111,3 +116,4 @@ subroutine packmsg(msg,dat,text)
 
   return
 end subroutine packmsg
+
diff --git a/lib/polfit.f90 b/lib/polfit.f90
new file mode 100644
index 0000000..ea7ffc9
--- /dev/null
+++ b/lib/polfit.f90
@@ -0,0 +1,72 @@
+subroutine polfit(x,y,sigmay,npts,nterms,mode,a,chisqr)
+  implicit real*8 (a-h,o-z)
+  real*8 x(npts), y(npts), sigmay(npts), a(nterms)
+  real*8 sumx(19), sumy(10), array(10,10)
+
+! Accumulate weighted sums
+  nmax = 2*nterms-1
+  sumx=0.
+  sumy=0.
+  chisq=0.
+  do i=1,npts
+     xi=x(i)
+     yi=y(i)
+     if(mode.lt.0) then
+        weight=1./abs(yi)
+     else if(mode.eq.0) then
+        weight=1
+     else
+        weight=1./sigmay(i)**2
+     end if
+     xterm=weight
+     do n=1,nmax
+        sumx(n)=sumx(n)+xterm
+        xterm=xterm*xi
+     enddo
+     yterm=weight*yi
+     do n=1,nterms
+        sumy(n)=sumy(n)+yterm
+        yterm=yterm*xi
+     enddo
+     chisq=chisq+weight*yi**2
+  enddo
+
+! Construct matrices and calculate coefficients
+  do j=1,nterms
+     do k=1,nterms
+        n=j+k-1
+        array(j,k)=sumx(n)
+     enddo
+  enddo
+
+  delta=determ(array,nterms)
+  if(delta.eq.0) then
+     chisqr=0.
+     a=0.
+  else
+     do l=1,nterms
+        do j=1,nterms
+           do k=1,nterms
+              n=j+k-1
+              array(j,k)=sumx(n)
+           enddo
+           array(j,l)=sumy(j)
+        enddo
+        a(l)=determ(array,nterms)/delta
+     enddo
+
+! Calculate chi square
+
+     do j=1,nterms
+        chisq=chisq-2*a(j)*sumy(j)
+        do k=1,nterms
+           n=j+k-1
+           chisq=chisq+a(j)*a(k)*sumx(n)
+        enddo
+     enddo
+     free=npts-nterms
+     chisqr=chisq/free
+  end if
+  
+  return
+end subroutine polfit
diff --git a/lib/prog_args.f90 b/lib/prog_args.f90
new file mode 100644
index 0000000..63cdb79
--- /dev/null
+++ b/lib/prog_args.f90
@@ -0,0 +1,4 @@
+MODULE prog_args
+  CHARACTER(len=80) :: shm_key
+  CHARACTER(len=500) :: exe_dir = '.', data_dir = '.', temp_dir = '.'
+END MODULE prog_args
diff --git a/lib/smo.f90 b/lib/smo.f90
new file mode 100644
index 0000000..94a3378
--- /dev/null
+++ b/lib/smo.f90
@@ -0,0 +1,23 @@
+subroutine smo(x,npts,y,nadd)
+
+  real x(npts)
+  real y(npts)
+
+  nh=nadd/2
+  do i=1+nh,npts-nh
+     sum=0.
+     do j=-nh,nh
+        sum=sum + x(i+j)
+     enddo
+     y(i)=sum
+  enddo
+  y(:nh)=0.
+  y(npts-nh+1:)=0.
+
+  fac=1.0/nadd
+  do i=1,npts
+     x(i)=fac*y(i)
+  enddo
+
+  return
+end subroutine smo
diff --git a/lib/softsym.f90 b/lib/softsym.f90
index 8eda5e7..5bb6265 100644
--- a/lib/softsym.f90
+++ b/lib/softsym.f90
@@ -1,11 +1,11 @@
 subroutine softsym(id2,npts8,nsps8,newdat,fpk,syncpk,snrdb,xdt,        &
-     freq,drift,schk,i1SoftSymbols)
+     freq,drift,a3,schk,i1SoftSymbols)
 
 ! Compute the soft symbols
 
-  complex c2(0:4096-1)
-  complex c3(0:4096-1)
-  complex c5(0:4096-1)
+  complex c2(0:1440-1)
+  complex c3(0:1440-1)
+  complex c5(0:1440-1)
   real a(3)
   integer*1 i1SoftSymbolsScrambled(207)
   integer*1 i1SoftSymbols(207)
@@ -19,9 +19,7 @@ subroutine softsym(id2,npts8,nsps8,newdat,fpk,syncpk,snrdb,xdt,        &
   call downsam9(id2,npts8,nsps8,newdat,nspsd,fpk,c2,nz2)
   call timer('downsam9',1)
 
-  call timer('peakdt9 ',0)
   call peakdt9(c2,nz2,nsps8,nspsd,c3,nz3,xdt)  !Find DT
-  call timer('peakdt9 ',1)
 
   fsample=1500.0/ndown
   a=0.
@@ -30,6 +28,8 @@ subroutine softsym(id2,npts8,nsps8,newdat,fpk,syncpk,snrdb,xdt,        &
   call timer('afc9    ',1)
   freq=fpk - a(1)
   drift=-2.0*a(2)
+  a3=a(3)
+  a(3)=0.
 
   call timer('twkfreq ',0)
   call twkfreq(c3,c5,nz3,fsample,a)   !Correct for delta f, f1, f2 ==> a(1:3)
@@ -42,9 +42,7 @@ subroutine softsym(id2,npts8,nsps8,newdat,fpk,syncpk,snrdb,xdt,        &
   call timer('symspec2',1)
 
 ! Remove interleaving
-  call timer('interlv9',0)
   call interleave9(i1SoftSymbolsScrambled,-1,i1SoftSymbols)
-  call timer('interlv9',1)
 
   return
 end subroutine softsym
diff --git a/lib/sort.f90 b/lib/sort.f90
index 281ce02..993dafd 100644
--- a/lib/sort.f90
+++ b/lib/sort.f90
@@ -1,4 +1,87 @@
 subroutine sort(n,arr)
-  call ssort(arr,tmp,n,1)
-  return
+
+  integer n,m,nstack
+  real arr(n)
+  parameter (m=7,nstack=50)
+  integer i,ir,j,jstack,k,l,istack(nstack)
+  real a,temp
+
+  jstack=0
+  l=1
+  ir=n
+
+1 if(ir-l.lt.m) then
+     do j=l+1,ir
+        a=arr(j)
+        do i=j-1,1,-1
+           if(arr(i).le.a) goto 2
+           arr(i+1)=arr(i)
+        enddo
+        i=0
+2       arr(i+1)=a
+     enddo
+
+     if(jstack.eq.0) return
+
+     ir=istack(jstack)
+     l=istack(jstack-1)
+     jstack=jstack-2
+
+  else
+     k=(l+ir)/2
+     temp=arr(k)
+     arr(k)=arr(l+1)
+     arr(l+1)=temp
+
+     if(arr(l+1).gt.arr(ir)) then
+        temp=arr(l+1)
+        arr(l+1)=arr(ir)
+        arr(ir)=temp
+     endif
+
+     if(arr(l).gt.arr(ir)) then
+        temp=arr(l)
+        arr(l)=arr(ir)
+        arr(ir)=temp
+     endif
+
+     if(arr(l+1).gt.arr(l)) then
+        temp=arr(l+1)
+        arr(l+1)=arr(l)
+        arr(l)=temp
+     endif
+
+     i=l+1
+     j=ir
+     a=arr(l)
+3    i=i+1
+     if(arr(i).lt.a) goto 3
+
+4    j=j-1
+     if(arr(j).gt.a) goto 4
+
+     if(j.lt.i) goto 5
+     temp=arr(i)
+     arr(i)=arr(j)
+     arr(j)=temp
+     goto 3
+
+5    arr(l)=arr(j)
+     arr(j)=a
+     jstack=jstack+2
+     if(jstack.gt.nstack) stop 'nstack too small in sort'
+
+     if(ir-i+1.ge.j-l) then
+        istack(jstack)=ir
+        istack(jstack-1)=i
+        ir=j-1
+     else
+        istack(jstack)=j-1
+        istack(jstack-1)=l
+        l=i
+     endif
+
+  endif
+  goto 1
+
 end subroutine sort
diff --git a/lib/ss.bat b/lib/ss.bat
index 37f669a..d8483ff 100644
--- a/lib/ss.bat
+++ b/lib/ss.bat
@@ -1 +1 @@
-svn status | grep -v '?'
+svn status | grep -v "?"
diff --git a/lib/ssort.f90 b/lib/ssort.f90
deleted file mode 100644
index 7d71238..0000000
--- a/lib/ssort.f90
+++ /dev/null
@@ -1,264 +0,0 @@
-subroutine ssort (x,y,n,kflag)
-! Sort an array and optionally make the same interchanges in
-!          an auxiliary array.  the array may be sorted in increasing
-!          or decreasing order.  a slightly modified quicksort
-!          algorithm is used.
-
-! ssort sorts array x and optionally makes the same interchanges in
-! array y.  the array x may be sorted in increasing order or
-! decreasing order.  a slightly modified quicksort algorithm is used.
-
-! Description of parameters
-!    x - array of values to be sorted
-!    y - array to be (optionally) carried along
-!    n - number of values in array x to be sorted
-!    kflag - control parameter
-!          =  2  means sort x in increasing order and carry y along.
-!          =  1  means sort x in increasing order (ignoring y)
-!          = -1  means sort x in decreasing order (ignoring y)
-!          = -2  means sort x in decreasing order and carry y along.
-
-  integer kflag, n
-  integer x(n), y(n)
-  real r
-  integer t, tt, tty, ty
-  integer i, ij, j, k, kk, l, m, nn
-  integer il(21), iu(21)
-
-  nn = n
-  if (nn .lt. 1) then
-!         print*,'ssort: The number of sort elements is not positive.'
-!         print*,'ssort: n = ',nn,'   kflag = ',kflag
-     return
-  endif
-
-  kk = abs(kflag)
-  if (kk.ne.1 .and. kk.ne.2) then
-     print *,'the sort control parameter, k, is not 2, 1, -1, or -2.'
-     return
-  endif
-
-! Alter array x to get decreasing order if needed
-
-  if (kflag .le. -1) then
-     do i=1,nn
-        x(i) = -x(i)
-     enddo
-  endif
-
-  if (kk .eq. 2) go to 100
-
-! Sort x only
-
-  m = 1
-  i = 1
-  j = nn
-  r = 0.375e0
-
-20 if (i .eq. j) go to 60
-  if (r .le. 0.5898437e0) then
-     r = r+3.90625e-2
-  else
-     r = r-0.21875e0
-  endif
-
-30 k = i
-
-! Select a central element of the array and save it in location t
-
-  ij = i + int((j-i)*r)
-  t = x(ij)
-
-! If first element of array is greater than t, interchange with t
-
-  if (x(i) .gt. t) then
-     x(ij) = x(i)
-     x(i) = t
-     t = x(ij)
-  endif
-  l = j
-
-! If last element of array is less than than t, interchange with t
-  if (x(j) .lt. t) then
-     x(ij) = x(j)
-     x(j) = t
-     t = x(ij)
-
-! If first element of array is greater than t, interchange with t
-     if (x(i) .gt. t) then
-        x(ij) = x(i)
-        x(i) = t
-        t = x(ij)
-     endif
-  endif
-
-! Find an element in the second half of the array which is smaller than t
-40 l = l-1
-  if (x(l) .gt. t) go to 40
-
-! Find an element in the first half of the array which is greater than t
-50 k = k+1
-  if (x(k) .lt. t) go to 50
-
-! Interchange these elements
-  if (k .le. l) then
-     tt = x(l)
-     x(l) = x(k)
-     x(k) = tt
-     go to 40
-  endif
-
-! Save upper and lower subscripts of the array yet to be sorted
-  if (l-i .gt. j-k) then
-     il(m) = i
-     iu(m) = l
-     i = k
-     m = m+1
-  else
-     il(m) = k
-     iu(m) = j
-     j = l
-     m = m+1
-  endif
-  go to 70
-
-! Begin again on another portion of the unsorted array
-60 m = m-1
-  if (m .eq. 0) go to 190
-  i = il(m)
-  j = iu(m)
-
-70 if (j-i .ge. 1) go to 30
-  if (i .eq. 1) go to 20
-  i = i-1
-
-80 i = i+1
-  if (i .eq. j) go to 60
-  t = x(i+1)
-  if (x(i) .le. t) go to 80
-  k = i
-
-90 x(k+1) = x(k)
-  k = k-1
-  if (t .lt. x(k)) go to 90
-  x(k+1) = t
-  go to 80
-
-! Sort x and carry y along
-
-100 m = 1
-  i = 1
-  j = nn
-  r = 0.375e0
-
-110 if (i .eq. j) go to 150
-  if (r .le. 0.5898437e0) then
-     r = r+3.90625e-2
-  else
-     r = r-0.21875e0
-  endif
-
-  120 k = i
-! Select a central element of the array and save it in location t
-  ij = i + int((j-i)*r)
-  t = x(ij)
-  ty = y(ij)
-
-! If first element of array is greater than t, interchange with t
-  if (x(i) .gt. t) then
-     x(ij) = x(i)
-     x(i) = t
-     t = x(ij)
-     y(ij) = y(i)
-     y(i) = ty
-     ty = y(ij)
-  endif
-  l = j
-
-! If last element of array is less than t, interchange with t
-  if (x(j) .lt. t) then
-     x(ij) = x(j)
-     x(j) = t
-     t = x(ij)
-     y(ij) = y(j)
-     y(j) = ty
-     ty = y(ij)
-
-! If first element of array is greater than t, interchange with t
-     if (x(i) .gt. t) then
-        x(ij) = x(i)
-        x(i) = t
-        t = x(ij)
-        y(ij) = y(i)
-        y(i) = ty
-        ty = y(ij)
-     endif
-  endif
-
-! Find an element in the second half of the array which is smaller than t
-130 l = l-1
-  if (x(l) .gt. t) go to 130
-
-! Find an element in the first half of the array which is greater than t
-140 k = k+1
-  if (x(k) .lt. t) go to 140
-
-! Interchange these elements
-  if (k .le. l) then
-     tt = x(l)
-     x(l) = x(k)
-     x(k) = tt
-     tty = y(l)
-     y(l) = y(k)
-     y(k) = tty
-     go to 130
-  endif
-
-! Save upper and lower subscripts of the array yet to be sorted
-  if (l-i .gt. j-k) then
-     il(m) = i
-     iu(m) = l
-     i = k
-     m = m+1
-  else
-     il(m) = k
-     iu(m) = j
-     j = l
-     m = m+1
-  endif
-  go to 160
-
-! Begin again on another portion of the unsorted array
-150 m = m-1
-  if (m .eq. 0) go to 190
-  i = il(m)
-  j = iu(m)
-
-160 if (j-i .ge. 1) go to 120
-  if (i .eq. 1) go to 110
-  i = i-1
-
-170 i = i+1
-  if (i .eq. j) go to 150
-  t = x(i+1)
-  ty = y(i+1)
-  if (x(i) .le. t) go to 170
-  k = i
-
-180 x(k+1) = x(k)
-  y(k+1) = y(k)
-  k = k-1
-  if (t .lt. x(k)) go to 180
-  x(k+1) = t
-  y(k+1) = ty
-  go to 170
-
-! Clean up
-190 if (kflag .le. -1) then
-     do i=1,nn
-        x(i) = -x(i)
-     enddo
-  endif
-
-  return
-end subroutine ssort
diff --git a/lib/stdmsg.f90 b/lib/stdmsg.f90
index bc8d489..7670ff0 100644
--- a/lib/stdmsg.f90
+++ b/lib/stdmsg.f90
@@ -2,11 +2,10 @@ logical*1 function stdmsg(msg0)
 
   character*22 msg0,msg
   integer dat(12)
-  logical text
 
-  call packmsg(msg0,dat,text)
+  call packmsg(msg0,dat,itype)
   call unpackmsg(dat,msg)
-  stdmsg=msg.eq.msg0 .and. (.not.text)
+  stdmsg=(msg.eq.msg0) .and. (itype.ge.0)
 
   return
 end function stdmsg
diff --git a/lib/sun.f90 b/lib/sun.f90
new file mode 100644
index 0000000..db258bb
--- /dev/null
+++ b/lib/sun.f90
@@ -0,0 +1,88 @@
+subroutine sun(y,m,DD,UT,lon,lat,RA,Dec,LST,Az,El,mjd,day)
+
+  implicit none
+
+  integer y                         !Year
+  integer m                         !Month
+  integer DD                        !Day
+  integer mjd                       !Modified Julian Date
+  real UT                           !UT!in hours
+  real RA,Dec                       !RA and Dec of sun
+
+! NB: Double caps here are single caps in the writeup.
+
+! Orbital elements of the Sun (also N=0, i=0, a=1):
+  real w                            !Argument of perihelion
+  real e                            !Eccentricity
+  real MM                           !Mean anomaly
+  real Ls                           !Mean longitude
+
+! Other standard variables:
+  real v                            !True anomaly
+  real EE                           !Eccentric anomaly
+  real ecl                          !Obliquity of the ecliptic
+  real d                            !Ephemeris time argument in days
+  real r                            !Distance to sun, AU
+  real xv,yv                        !x and y coords in ecliptic
+  real lonsun                       !Ecliptic long and lat of sun
+!Ecliptic coords of sun (geocentric)
+  real xs,ys
+!Equatorial coords of sun (geocentric)
+  real xe,ye,ze
+  real lon,lat
+  real GMST0,LST,HA
+  real xx,yy,zz
+  real xhor,yhor,zhor
+  real Az,El
+
+  real day
+  real rad
+  data rad/57.2957795/
+
+! Time in days, with Jan 0, 2000 equal to 0.0:
+  d=367*y - 7*(y+(m+9)/12)/4 + 275*m/9 + DD - 730530 + UT/24.0
+  mjd=d + 51543
+  ecl = 23.4393 - 3.563e-7 * d
+
+! Compute updated orbital elements for Sun:
+  w = 282.9404 + 4.70935e-5 * d
+  e = 0.016709 - 1.151e-9 * d
+  MM = mod(356.0470d0 + 0.9856002585d0 * d + 360000.d0,360.d0)
+  Ls = mod(w+MM+720.0,360.0)
+
+  EE = MM + e*rad*sin(MM/rad) * (1.0 + e*cos(M/rad))
+  EE = EE - (EE - e*rad*sin(EE/rad)-MM) / (1.0 - e*cos(EE/rad))
+
+  xv = cos(EE/rad) - e
+  yv = sqrt(1.0-e*e) * sin(EE/rad)
+  v = rad*atan2(yv,xv)
+  r = sqrt(xv*xv + yv*yv)
+  lonsun = mod(v + w + 720.0,360.0)
+! Ecliptic coordinates of sun (rectangular):
+  xs = r * cos(lonsun/rad)
+  ys = r * sin(lonsun/rad)
+
+! Equatorial coordinates of sun (rectangular):
+  xe = xs
+  ye = ys * cos(ecl/rad)
+  ze = ys * sin(ecl/rad)
+
+! RA and Dec in degrees:
+  RA = rad*atan2(ye,xe)
+  Dec = rad*atan2(ze,sqrt(xe*xe + ye*ye))
+
+  GMST0 = (Ls + 180.0)/15.0
+  LST = mod(GMST0+UT+lon/15.0+48.0,24.0)    !LST in hours
+  HA = 15.0*LST - RA                        !HA in degrees
+  xx = cos(HA/rad)*cos(Dec/rad)
+  yy = sin(HA/rad)*cos(Dec/rad)
+  zz =             sin(Dec/rad)
+  xhor = xx*sin(lat/rad) - zz*cos(lat/rad)
+  yhor = yy
+  zhor = xx*cos(lat/rad) + zz*sin(lat/rad)
+  Az = mod(rad*atan2(yhor,xhor) + 180.0 + 360.0,360.0)
+  El = rad*asin(zhor)
+  day=d-1.5
+  
+  return
+end subroutine sun
diff --git a/lib/symspec.f90 b/lib/symspec.f90
index 2facb49..8a9c1d7 100644
--- a/lib/symspec.f90
+++ b/lib/symspec.f90
@@ -1,4 +1,4 @@
-subroutine symspec(k,ntrperiod,nsps,ingain,slope,pxdb,s,df3,ihsym,npts8)
+subroutine symspec(k,ntrperiod,nsps,ingain,nflatten,pxdb,s,df3,ihsym,npts8)
 
 ! Input:
 !  k         pointer to the most recent new data
@@ -20,14 +20,16 @@ subroutine symspec(k,ntrperiod,nsps,ingain,slope,pxdb,s,df3,ihsym,npts8)
   include 'constants.f90'
   real*4 w3(MAXFFT3)
   real*4 s(NSMAX)
-  real*4 scale(NSMAX)
   real*4 ssum(NSMAX)
   real*4 xc(0:MAXFFT3-1)
+  real*4 tmp(NSMAX)
   complex cx(0:MAXFFT3/2)
   integer*2 id2
   common/jt9com/ss(184,NSMAX),savg(NSMAX),id2(NMAX),nutc,ndiskdat,         &
-       ntr,mousefqso,newdat,nfa,nfb,ntol,kin,nzhsym,nsynced,ndecoded
-  data rms/999.0/,k0/99999999/,nfft3z/0/,slope0/0.0/
+       ntr,mousefqso,newdat,npts8a,nfa,nfsplit,nfb,ntol,kin,nzhsym,         &
+       nsave,nagain,ndepth,ntxmode,nmode,junk(5)
+  common/jt9w/syellow(NSMAX)
+  data rms/999.0/,k0/99999999/,nfft3z/0/
   equivalence (xc,cx)
   save
 
@@ -40,18 +42,15 @@ subroutine symspec(k,ntrperiod,nsps,ingain,slope,pxdb,s,df3,ihsym,npts8)
      go to 900                                 !Wait for enough samples to start
   endif
 
-  if(nfft3.ne.nfft3z .or. slope.ne.slope0) then    !New nfft3, compute window
+  if(nfft3.ne.nfft3z) then
+! Compute new window
      pi=4.0*atan(1.0)
+     width=0.25*nsps
      do i=1,nfft3
-        w3(i)=2.0*(sin(i*pi/nfft3))**2         !Window for nfft3 spectrum
+        z=(i-nfft3/2)/width
+        w3(i)=exp(-z*z)
      enddo
      nfft3z=nfft3
-     nh=NSMAX/2
-     do i=1,NSMAX
-        x=slope*float(i)/nh - 1.0 + 2.6
-        scale(i)=10.0**x
-     enddo
-     slope0=slope
   endif
 
   if(k.lt.k0) then                             !Start a new data block
@@ -60,19 +59,18 @@ subroutine symspec(k,ntrperiod,nsps,ingain,slope,pxdb,s,df3,ihsym,npts8)
      ihsym=0
      if(ndiskdat.eq.0) id2(k+1:)=0   !Needed to prevent "ghosts". Not sure why.
   endif
-  gain=10.0**(0.05*ingain)
+  gain=10.0**(0.1*ingain)
   sq=0.
   do i=k0+1,k
      x1=id2(i)
      sq=sq + x1*x1
   enddo
-  sq=sq * gain**2
+  sq=sq * gain
   rms=sqrt(sq/(k-k0))
   pxdb=0.
   if(rms.gt.0.0) pxdb=20.0*log10(rms)
   if(pxdb.gt.60.0) pxdb=60.0
 
-
   k0=k
   ja=ja+jstep                         !Index of first sample
 
@@ -100,12 +98,24 @@ subroutine symspec(k,ntrperiod,nsps,ingain,slope,pxdb,s,df3,ihsym,npts8)
      sx=fac*(real(cx(j))**2 + aimag(cx(j))**2)
      ss(n,i)=sx
      ssum(i)=ssum(i) + sx
-     s(i)=gain*sx
+     s(i)=1000.0*gain*sx
   enddo
 
-!  s=0.05*s/ref
-  s=scale*s
-  savg=scale*ssum/ihsym
+  savg=ssum/ihsym
+
+  if(mod(n,10).eq.0) then
+     mode4=36
+     nsmo=min(10*mode4,150)
+     nsmo=4*nsmo
+     call flat1(savg,iz,nsmo,syellow)
+     if(mode4.ge.9) call smo(syellow,iz,tmp,mode4)
+     ia=500./df3
+     ib=2700.0/df3
+     smin=minval(syellow(ia:ib))
+     smax=maxval(syellow(1:iz))
+     syellow=(50.0/(smax-smin))*(syellow-smin)
+     where(syellow<0) syellow=0.
+  endif
 
 900 npts8=k/8
 
diff --git a/lib/symspec2.f90 b/lib/symspec2.f90
index 92dc571..2f4dc9e 100644
--- a/lib/symspec2.f90
+++ b/lib/symspec2.f90
@@ -34,7 +34,6 @@ subroutine symspec2(c5,nz3,nsps8,nspsd,fsample,freq,drift,snrdb,schk,    &
   enddo
 
   call chkss2(ss2,freq,drift,schk)
-  if(schk.lt.2.0) go to 900
 
   ss=0.
   sig=0.
@@ -78,11 +77,12 @@ subroutine symspec2(c5,nz3,nsps8,nspsd,fsample,freq,drift,snrdb,schk,    &
         i4=nint(scale*(r1-r0))
         if(i4.lt.-127) i4=-127
         if(i4.gt.127) i4=127
-        i4=i4+128
-        if(i4.le.127) i1SoftSymbolsScrambled(k)=i4
-        if(i4.ge.128) i1SoftSymbolsScrambled(k)=i4-256
+!        i4=i4+128
+!        if(i4.le.127) i1SoftSymbolsScrambled(k)=i4
+!        if(i4.ge.128) i1SoftSymbolsScrambled(k)=i4-256
+        i1SoftSymbolsScrambled(k)=i4
      enddo
   enddo
 
-900 return
+  return
 end subroutine symspec2
diff --git a/lib/symspec65.f90 b/lib/symspec65.f90
index 5f6da88..e9879ed 100644
--- a/lib/symspec65.f90
+++ b/lib/symspec65.f90
@@ -10,22 +10,35 @@ subroutine symspec65(dd,npts,ss,nhsym,savg)
   real*4 ss(MAXHSYM,NSZ)
   real*4 savg(NSZ)
   real*4 x(NFFT)
+  real*4 w(NFFT)
   complex c(0:NFFT/2)
+  logical first
   common/refspec/dfref,ref(NSZ)
   equivalence (x,c)
-  save /refspec/
+  data first/.true./
+  save /refspec/,first,w
 
   hstep=2048.d0*12000.d0/11025.d0              !half-symbol = 2229.116 samples
   nsps=nint(2*hstep)
   df=12000.0/NFFT
-  nhsym=npts/hstep - 1.0
+  nhsym=(npts-NFFT)/hstep
   savg=0.
   fac1=1.e-3
 
+  if(first) then
+! Compute the FFT window
+     pi=4.0*atan(1.0)
+     width=0.25*nsps
+     do i=1,NFFT
+        z=(i-NFFT/2)/width
+        w(i)=exp(-z*z)
+      enddo
+     first=.false.
+  endif
+
   do j=1,nhsym
      i0=(j-1)*hstep
-     x(1:nsps)=fac1*dd(i0+1:i0+nsps)
-     x(nsps+1:)=0.
+     x=fac1*w*dd(i0+1:i0+NFFT)
      call four2a(c,NFFT,1,-1,0)                !r2c forward FFT
      do i=1,NSZ
         s=real(c(i))**2 + aimag(c(i))**2
diff --git a/lib/sync9.f90 b/lib/sync9.f90
index 433e11f..a757d8c 100644
--- a/lib/sync9.f90
+++ b/lib/sync9.f90
@@ -1,7 +1,6 @@
 subroutine sync9(ss,nzhsym,lag1,lag2,ia,ib,ccfred,red2,ipkbest)
 
   include 'constants.f90'
-!  parameter (NSMAX=1365)             !Max length of saved spectra
   real ss(184,NSMAX)
   real ss1(184)
   real ccfred(NSMAX)
@@ -20,7 +19,6 @@ subroutine sync9(ss,nzhsym,lag1,lag2,ia,ib,ccfred,red2,ipkbest)
   do i=ia,ib                         !Loop over freq range
      ss1=ss(1:184,i)
      call pctile(ss1,nzhsym,40,xmed)
-!     xmed=sum(ss1(1:nzhsym))/nzhsym
 
      ss1=ss1/xmed - 1.0
      do j=1,nzhsym
@@ -66,8 +64,6 @@ subroutine sync9(ss,nzhsym,lag1,lag2,ia,ib,ccfred,red2,ipkbest)
   do j=1,nzhsym
      savg(ia:ib)=savg(ia:ib) + ss(j,ia:ib)
   enddo
-!  df=1500.0/2048.0                          ! 0.732422
-!  df9=12000.0/6912.0                        ! 1.736111
   savg(ia:ib)=savg(ia:ib)/nzhsym
   smo(0:20)=1.0/21.0
   smo(-5:-1)=-(1.0/21.0)*(21.0/10.0)
@@ -92,10 +88,7 @@ subroutine sync9(ss,nzhsym,lag1,lag2,ia,ib,ccfred,red2,ipkbest)
      red2(i)=savg2(i)-ref
      if(red2(i).lt.-99.0) red2(i)=-99.0
      if(red2(i).gt.99.0) red2(i)=99.0
-!     write(30,3001) i,i*df+1000.0,savg2(i),red2(i),ccfred(i)
-!3001 format(i8,4f10.3)
   enddo
-!  call flush(30)
 
   return
 end subroutine sync9
diff --git a/lib/timefft.f90 b/lib/timefft.f90
new file mode 100644
index 0000000..4e00838
--- /dev/null
+++ b/lib/timefft.f90
@@ -0,0 +1,139 @@
+program timefft
+
+! Tests and times one-dimensional FFTs computed by FFTW3
+
+  use, intrinsic :: iso_c_binding
+  use FFTW3
+
+  complex(C_FLOAT_COMPLEX),pointer :: a(:),b(:),c(:)
+  real(C_FLOAT),pointer :: ar(:),br(:)
+  type(C_PTR) :: plan1,plan2              !Pointers to FFTW plans
+  type(C_PTR) :: pa,pb,pc
+  integer(C_INT) iret
+  integer*8 count0,count1,clkfreq
+  character problem*9
+  logical linplace,lcomplex,lthreading
+
+! Get command-line parameters
+  call timefft_opts(npatience,maxthreads,linplace,lcomplex,nfft,problem,nflags)
+  lthreading=maxthreads.ge.1
+  maxthreads=max(1,maxthreads)
+
+! Allocate data arrays
+  pa=fftwf_alloc_complex(int(nfft,C_SIZE_T))
+  call c_f_pointer(pa,a,[nfft])
+  call c_f_pointer(pa,ar,[nfft])
+
+  pb=fftwf_alloc_complex(int(nfft,C_SIZE_T))
+  call c_f_pointer(pb,b,[nfft])
+  call c_f_pointer(pb,br,[nfft])
+
+  pc=fftwf_alloc_complex(int(nfft,C_SIZE_T))
+  call c_f_pointer(pc,c,[nfft])
+
+! Initialize FFTW threading
+  if(lthreading) iret=fftwf_init_threads()
+
+! Import FFTW wisdom, if available
+  iret=fftwf_import_wisdom_from_filename(C_CHAR_'wis.dat' // C_NULL_CHAR)
+
+  do i=1,nfft                           !Generate random data
+     x=gran()
+     y=gran()
+     b(i)=cmplx(x,y)
+  enddo
+  iters=100
+
+  write(*,1000) 
+1000 format(/'Problem  Threads Plan    Time    Gflops     RMS   iters'/    &
+             '--------------------------------------------------------')
+
+! Try nthreads = 1,maxthreads
+  do nthreads=1,maxthreads
+     a(1:nfft)=b(1:nfft)                             !Copy test data into a()
+     call system_clock(count0,clkfreq)
+! Make the plans
+     if(lthreading) call fftwf_plan_with_nthreads(nthreads)
+     if(lcomplex) then
+        if(linplace) then
+           plan1=fftwf_plan_dft_1d(nfft,a,a,-1,nflags)
+           plan2=fftwf_plan_dft_1d(nfft,a,a,+1,nflags)
+        else
+           plan1=fftwf_plan_dft_1d(nfft,a,c,-1,nflags)
+           plan2=fftwf_plan_dft_1d(nfft,c,a,+1,nflags)
+        endif
+     else
+        if(linplace) then
+           plan1=fftwf_plan_dft_r2c_1d(nfft,ar,a,nflags)
+           plan2=fftwf_plan_dft_c2r_1d(nfft,a,ar,nflags)
+        else
+           plan1=fftwf_plan_dft_r2c_1d(nfft,ar,c,nflags)
+           plan2=fftwf_plan_dft_c2r_1d(nfft,c,ar,nflags)
+        endif
+     endif
+     call system_clock(count1,clkfreq)
+     tplan=0.5*float(count1-count0)/float(clkfreq)    !Plan time for one transform
+
+     total=0.
+     do iter=1,iters                             !Do many iterations
+        a=b                                      !Copy test data into a()
+        call system_clock(count0,clkfreq)
+! Compute the transforms
+        if(lcomplex) then
+           if(linplace) then
+              call fftwf_execute_dft(plan1,a,a)
+              call fftwf_execute_dft(plan2,a,a)
+           else
+              call fftwf_execute_dft(plan1,a,c)
+              call fftwf_execute_dft(plan2,c,a)
+           endif
+        else
+           if(linplace) then
+              call fftwf_execute_dft_r2c(plan1,ar,a)
+              call fftwf_execute_dft_c2r(plan2,a,ar)
+           else
+              call fftwf_execute_dft_r2c(plan1,ar,c)
+              call fftwf_execute_dft_c2r(plan2,c,ar)
+           endif
+        endif
+        call system_clock(count1,clkfreq)
+        total=total + float(count1-count0)/float(clkfreq) 
+        if(total>=1.0 .and. iter>=10) go to 40     !Cut iterations short ?
+     enddo
+     iter=iters
+
+40   time=0.5*total/iter                         !Time for one FFT 
+     gflops=5.0/(1.e9*time/(nfft*log(float(nfft))/log(2.0)))
+     a(1:nfft)=a(1:nfft)/nfft              !Normalize the back-transformed data
+
+! Compute RMS difference between original data and back-transformed data.
+     sq=0.
+     if(lcomplex) then
+        do i=1,nfft
+           sq=sq + real(a(i)-b(i))**2 + aimag(a(i)-b(i))**2
+        enddo
+     else
+        do i=1,nfft
+           sq=sq + (ar(i)-br(i))**2
+        enddo
+     endif
+     rms=sqrt(sq/nfft)
+
+! Display results
+     write(*,1050) problem,nthreads,tplan,time,gflops,rms,iter
+1050 format(a9,i4,f8.3,f10.6,f7.2,f11.7,i5)
+  enddo
+
+! Export accumulated FFTW wisdom
+  iret=fftwf_export_wisdom_to_filename(C_CHAR_'wis.dat' // C_NULL_CHAR)
+
+! Clean up
+  call fftwf_destroy_plan(plan1)
+  call fftwf_destroy_plan(plan2)
+  call fftwf_free(pa)
+  call fftwf_free(pb)
+  call fftwf_free(pc)
+  call fftwf_cleanup_threads()
+  call fftwf_cleanup()
+
+end program timefft
diff --git a/lib/timefft_opts.f90 b/lib/timefft_opts.f90
new file mode 100644
index 0000000..cd58132
--- /dev/null
+++ b/lib/timefft_opts.f90
@@ -0,0 +1,48 @@
+subroutine timefft_opts(npatience,nthreads,linplace,lcomplex,nfft,    &
+     problem,nflags)
+
+  use FFTW3
+
+  logical linplace,lcomplex
+  character problem*9,arg*12
+
+  nargs=iargc()
+  if(nargs.lt.3) then
+     print*,'Usage: timefft npatience maxthreads [[o|i][r|c]]nfft'
+     print*,'       npatience  - 0 to 4'
+     print*,'       maxthreads - suggest #CPUs or #CPUs-1'
+     print*,'       o,i        - out-of-place or in-place (default=in-place)'
+     print*,'       r,c        - real or complex (default=complex)'
+     print*,' '
+     print*,'Examples:'
+     print*,'       timefft 1 1 32768     (1 thread, in-place, complex)'
+     print*,'       timefft 2 3 or32768   (more patient, 3 threads,'
+     print*,'                              out-of-place, real)'
+     stop
+  endif
+
+  call getarg(1,arg)
+  read(arg,*) npatience
+  call getarg(2,arg)
+  read(arg,*) nthreads
+  call getarg(3,arg)
+  linplace=arg(1:1).ne.'o' .and. arg(2:2).ne.'o'
+  lcomplex=arg(1:1).ne.'r' .and. arg(2:2).ne.'r'
+  k=3
+  if(ichar(arg(2:2)).ge.48 .and. ichar(arg(2:2)).le.57) k=2
+  if(ichar(arg(1:1)).ge.48 .and. ichar(arg(1:1)).le.57) k=1
+  read(arg(k:),*) nfft
+
+  write(problem,'(i9)') nfft
+  problem='ic'//adjustl(problem)
+  if(.not.linplace) problem(1:1)='o'
+  if(.not.lcomplex) problem(2:2)='r'
+
+  nflags=FFTW_ESTIMATE
+  if(npatience.eq.1) nflags=FFTW_ESTIMATE_PATIENT
+  if(npatience.eq.2) nflags=FFTW_MEASURE
+  if(npatience.eq.3) nflags=FFTW_PATIENT
+  if(npatience.eq.4) nflags=FFTW_EXHAUSTIVE
+
+  return
+end subroutine timefft_opts
diff --git a/lib/timer.f90 b/lib/timer.f90
index 1637493..5293a57 100644
--- a/lib/timer.f90
+++ b/lib/timer.f90
@@ -1,112 +1,200 @@
-subroutine timer(dname,k)
-
-! Times procedure number n between a call with k=0 (tstart) and with
-! k=1 (tstop). Accumulates sums of these times in array ut (user time).
-! Also traces all calls (for debugging purposes) if limtrace.gt.0
-
-  character*8 dname,name(50),space,ename
-  character*16 sname
-  logical on(50)
-  real ut(50),ut0(50),dut(50)
-  integer ncall(50),nlevel(50),nparent(50)
-  integer onlevel(0:10)
-  common/tracer/ limtrace,lu
-  data eps/0.000001/,ntrace/0/
-  data level/0/,nmax/0/,space/'        '/
-  data limtrace/0/,lu/-1/
-  save
-
-  if(limtrace.lt.0) go to 999
-  if(lu.lt.1) lu=6
-  if(k.gt.1) go to 40                        !Check for "all done" (k>1)
-  onlevel(0)=0
-
-  do n=1,nmax                                !Check for existing name
-     if(name(n).eq.dname) go to 20
-  enddo
-
-  nmax=nmax+1                                !This is a new one
-  n=nmax
-  ncall(n)=0
-  on(n)=.false.
-  ut(n)=eps
-  name(n)=dname
-
-20 if(k.eq.0) then                                !Get start times (k=0)
-     if(on(n)) print*,'Error in timer: ',dname,' already on.'
-     level=level+1                                !Increment the level
-     on(n)=.true.
-     call system_clock(icount,irate)
-     ut0(n)=float(icount)/irate
-     ncall(n)=ncall(n)+1
-     if(ncall(n).gt.1.and.nlevel(n).ne.level) then
-        nlevel(n)=-1
-     else
-        nlevel(n)=level
-     endif
-     nparent(n)=onlevel(level-1)
-     onlevel(level)=n
-
-  else if(k.eq.1) then        !Get stop times and accumulate sums. (k=1)
-     if(on(n)) then
-        on(n)=.false.
-        call system_clock(icount,irate)
-        ut1=float(icount)/irate
-        ut(n)=ut(n)+ut1-ut0(n)
-     endif
-     level=level-1
-  endif
-
-  ntrace=ntrace+1
-  if(ntrace.lt.limtrace) write(lu,1020) ntrace,dname,k,level,nparent(n)
-1020 format(i8,': ',a8,3i5)
-  go to 998
-
-! Write out the timer statistics
-
-40 write(lu,1040)
-1040 format(/'     name                 time  frac     dtime',       &
-             ' dfrac  calls level parent'/73('-'))
-
-  if(k.gt.100) then
-     ndiv=k-100
-     do i=1,nmax
-        ncall(i)=ncall(i)/ndiv
-        ut(i)=ut(i)/ndiv
-     enddo
-  endif
-
-  total=ut(1)
-  sum=0.
-  sumf=0.
-  do i=1,nmax
-     dut(i)=ut(i)
-     do j=i,nmax
-        if(nparent(j).eq.i) dut(i)=dut(i)-ut(j)
-     enddo
-     utf=ut(i)/total
-     dutf=dut(i)/total
-     sum=sum+dut(i)
-     sumf=sumf+dutf
-     kk=nlevel(i)
-     sname=space(1:kk)//name(i)//space(1:8-kk)
-     ename=space
-     if(i.ge.2) ename=name(nparent(i))
-     write(lu,1060) float(i),sname,ut(i),utf,dut(i),dutf,           &
-          ncall(i),nlevel(i),ename
-1060 format(f4.0,a16,2(f10.2,f6.2),i7,i5,2x,a8)
-  enddo
-
-  write(lu,1070) sum,sumf
-1070 format(/36x,f10.2,f6.2)
-  nmax=0
-  eps=0.000001
-  ntrace=0
-  level=0
-  space='        '
-  onlevel(0)=0
-
-998 flush(lu)
-
-999 return
-end subroutine timer
+subroutine timer(dname,k)
+
+! Times procedure number n between a call with k=0 (tstart) and with
+! k=1 (tstop). Accumulates sums of these times in array ut (user time).
+! Also traces all calls (for debugging purposes) if limtrace.gt.0
+!
+! If this is used with OpenMP than the /tracer_priv/ common block must
+! be copyed into each thread of a thread team by using the copyin()
+! clause on the !$omp parallel directive that creates the team.
+
+  !$ use omp_lib
+
+  character*8 dname
+  !$ integer tid
+  integer onlevel(0:10)
+  common/tracer/ limtrace,lu
+  common/tracer_priv/level,onlevel
+
+  parameter (MAXCALL=100)
+  character*8 name(MAXCALL),space
+  logical on(MAXCALL)
+  real ut(MAXCALL),ut0(MAXCALL)
+  !$ integer ntid(MAXCALL)
+  integer nmax,ncall(MAXCALL),nlevel(MAXCALL),nparent(MAXCALL)
+  common/data/nmax,name,on,ut,ut0,dut, &
+       !$ ntid, &
+       ncall,nlevel,nparent,total,sum,sumf,space
+
+  data eps/0.000001/,ntrace/0/
+  data level/0/,nmax/0/,space/'        '/
+  data limtrace/0/,lu/-1/
+
+  !$omp threadprivate(/tracer_priv/)
+
+  !$omp critical(timer)
+  if(limtrace.lt.0) go to 999
+  if(lu.lt.1) lu=6
+  if(k.gt.1) go to 40                        !Check for "all done" (k>1)
+  onlevel(0)=0
+
+  !$ tid=omp_get_thread_num()
+  do n=1,nmax                                !Check for existing name/parent[/thread]
+     if(name(n).eq.dname &
+          !$ .and.ntid(n).eq.tid &
+          ) then
+        if (on(n)) then
+             if (nparent(n).eq.onlevel(level-1)) goto 20
+        else
+           if (nparent(n).eq.onlevel(level)) goto 20
+        end if
+     end if
+  enddo
+
+  nmax=nmax+1                                !This is a new one
+  n=nmax
+  !$ ntid(n)=tid
+  ncall(n)=0
+  on(n)=.false.
+  ut(n)=eps
+  name(n)=dname
+
+20 if(k.eq.0) then                                !Get start times (k=0)
+     if(on(n)) then
+        print*,'Error in timer: ',dname,' already on.'
+     end if
+     level=level+1                                !Increment the level
+     on(n)=.true.
+!     call system_clock(icount,irate)
+!     ut0(n)=float(icount)/irate
+!     call cpu_time(ut0(n))
+     ut0(n)=secnds(0.0)
+
+     ncall(n)=ncall(n)+1
+     if(ncall(n).gt.1.and.nlevel(n).ne.level) then
+        !recursion is happening
+        !
+        !TODO: somehow need to account for this deeper call at the
+        !shallowest instance in the call chain and this needs to be
+        !done without incrementing anything here other than counters
+        !and timers
+        !
+        nlevel(n)=-1
+     else
+        nlevel(n)=level
+     endif
+     nparent(n)=onlevel(level-1)
+     onlevel(level)=n
+
+  else if(k.eq.1) then        !Get stop times and accumulate sums. (k=1)
+     if(on(n)) then
+        on(n)=.false.
+!        call system_clock(icount,irate)
+!        ut1=float(icount)/irate
+!        call cpu_time(ut1)
+        ut1=secnds(0.0)
+
+        ut(n)=ut(n)+ut1-ut0(n)
+     endif
+     level=level-1
+  endif
+
+  ntrace=ntrace+1
+  if(ntrace.lt.limtrace) write(lu,1020) ntrace,tname,k,level,nparent(n)
+1020 format(i8,': ',a8,3i5)
+  go to 998
+
+! Write out the timer statistics
+
+40 write(lu,1040)
+1040 format(/' Name                 Time  Frac     dTime',       &
+             ' dFrac    Calls'/58('-'))
+
+  !$ !walk backwards through the database rolling up thread data by call chain
+  !$ do i=nmax,1,-1
+  !$    do j=1,i-1
+  !$       l=j
+  !$       m=i
+  !$       do while (name(l).eq.name(m))
+  !$          l=nparent(l)
+  !$          m=nparent(m)
+  !$          if (l.eq.0.or.m.eq.0) exit
+  !$       end do
+  !$       if (l.eq.0.and.m.eq.0) then
+  !$          !same call chain so roll up data
+  !$          ncall(j)=ncall(j)+ncall(i)
+  !$          ut(j)=ut(j)+ut(i)
+  !$          do n=1,nmax
+  !$            if (nparent(n).eq.i) nparent(n)=j
+  !$          end do
+  !$          name(i)=space
+  !$          exit
+  !$       end if
+  !$    end do
+  !$ end do
+
+  if(k.gt.100) then
+     ndiv=k-100
+     do i=1,nmax
+        ncall(i)=ncall(i)/ndiv
+        ut(i)=ut(i)/ndiv
+     enddo
+  endif
+
+  total=ut(1)
+  sum=0.
+  sumf=0.
+  call print_root(1)
+  write(lu,1070) sum,sumf
+1070 format(58('-')/32x,f10.3,f6.2)
+  nmax=0
+  eps=0.000001
+  ntrace=0
+  level=0
+  onlevel(0)=0
+
+998 flush(lu)
+
+999 continue
+
+  !$omp end critical(timer)
+  return
+end subroutine timer
+
+recursive subroutine print_root(i)
+  character*16 sname
+
+  common/tracer/ limtrace,lu
+
+  parameter (MAXCALL=100)
+  character*8 name(MAXCALL),space
+  logical on(MAXCALL)
+  real ut(MAXCALL),ut0(MAXCALL)
+  !$ integer ntid(MAXCALL)
+  integer nmax,ncall(MAXCALL),nlevel(MAXCALL),nparent(MAXCALL)
+  common/data/nmax,name,on,ut,ut0,dut, &
+       !$ ntid, &
+       ncall,nlevel,nparent,total,sum,sumf,space
+
+  if (i.le.nmax) then
+     if (name(i).ne.space) then
+        dut=ut(i)
+        do j=i,nmax
+           if (name(j).ne.space.and.nparent(j).eq.i) dut=dut-ut(j)
+        enddo
+        if(dut.lt.0.0) dut=0.0
+        utf=ut(i)/total
+        dutf=dut/total
+        sum=sum+dut
+        sumf=sumf+dutf
+        kk=nlevel(i)
+        sname=space(1:kk)//name(i)//space(1:8-kk)
+        write(lu,2000) sname,ut(i),utf,dut,dutf,ncall(i)
+2000    format(a16,2(f10.3,f6.2),i9)
+        do j=i,nmax
+           if(nparent(j).eq.i) call print_root(j)
+        enddo
+     end if
+  end if
+  return
+end subroutine print_root
diff --git a/lib/timeval.h b/lib/timeval.h
deleted file mode 100644
index 100dda5..0000000
--- a/lib/timeval.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * timeval.h    1.0 01/12/19
- *
- * Defines gettimeofday, timeval, etc. for Win32
- *
- * By Wu Yongwei
- *
- */
-
-#ifndef _TIMEVAL_H
-#define _TIMEVAL_H
-
-#ifdef _WIN32
-
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#include <time.h>
-
-#ifndef __GNUC__
-#define EPOCHFILETIME (116444736000000000i64)
-#else
-#define EPOCHFILETIME (116444736000000000LL)
-#endif
-
-//struct timeval {
-//    long tv_sec;        /* seconds */
-//    long tv_usec;  /* microseconds */
-//};
-
-struct timezone {
-    int tz_minuteswest; /* minutes W of Greenwich */
-    int tz_dsttime;     /* type of dst correction */
-};
-
-__inline int gettimeofday(struct timeval *tv, struct timezone *tz)
-{
-    FILETIME        ft;
-    LARGE_INTEGER   li;
-    __int64         t;
-    static int      tzflag;
-
-    if (tv)
-    {
-        GetSystemTimeAsFileTime(&ft);
-        li.LowPart  = ft.dwLowDateTime;
-        li.HighPart = ft.dwHighDateTime;
-        t  = li.QuadPart;       /* In 100-nanosecond intervals */
-        t -= EPOCHFILETIME;     /* Offset to the Epoch time */
-        t /= 10;                /* In microseconds */
-        tv->tv_sec  = (long)(t / 1000000);
-        tv->tv_usec = (long)(t % 1000000);
-    }
-
-    if (tz)
-    {
-        if (!tzflag)
-        {
-            _tzset();
-            tzflag++;
-        }
-        tz->tz_minuteswest = _timezone / 60;
-        tz->tz_dsttime = _daylight;
-    }
-
-    return 0;
-}
-
-#else  /* _WIN32 */
-
-#include <sys/time.h>
-
-#endif /* _WIN32 */
-
-#endif /* _TIMEVAL_H */
diff --git a/lib/tm2.f90 b/lib/tm2.f90
new file mode 100644
index 0000000..cf11078
--- /dev/null
+++ b/lib/tm2.f90
@@ -0,0 +1,14 @@
+subroutine tm2(day,xlat4,xlon4,xl4,b4)
+
+  implicit real*8 (a-h,o-z)
+  parameter (RADS=0.0174532925199433d0)
+
+  real*4 xlat4,xlon4,xl4,b4
+
+  glat=xlat4*RADS
+  glong=xlon4*RADS
+  call tmoonsub(day,glat,glong,el,rv,xl,b,pax)
+  xl4=xl
+  b4=b
+
+end subroutine tm2
diff --git a/lib/tmoonsub.c b/lib/tmoonsub.c
new file mode 100644
index 0000000..ec3707e
--- /dev/null
+++ b/lib/tmoonsub.c
@@ -0,0 +1,518 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+#define RADS 0.0174532925199433
+#define DEGS 57.2957795130823
+#define TPI 6.28318530717959
+#define PI 3.1415927
+
+/* ratio of     earth radius to astronomical unit */
+#define ER_OVER_AU 0.0000426352325194252
+
+/* all prototypes here */
+
+double getcoord(int coord);
+void getargs(int argc, char *argv[], int *y, int *m, double *tz, double *glong, double *glat);
+double range(double y);
+double rangerad(double y);
+double days(int y, int m, int dn, double hour);
+double days_(int *y, int *m, int *dn, double *hour);
+void moonpos(double, double *, double *, double *);
+void sunpos(double , double *, double *, double *);
+double moontransit(int y, int m, int d, double timezone, double glat, double glong, int *nt);
+double atan22(double y, double x);
+double epsilon(double d);
+void equatorial(double d, double *lon, double *lat, double *r);
+void ecliptic(double d, double *lon, double *lat, double *r);
+double gst(double d);
+void topo(double lst, double glat, double *alp, double *dec, double *r);
+double alt(double glat, double ha, double dec);
+void libration(double day, double lambda, double beta, double alpha, double *l, double *b, double *p);
+void illumination(double day, double lra, double ldec, double dr, double sra, double sdec, double *pabl, double *ill);
+int daysinmonth(int y, int m);
+int isleap(int y);
+void tmoonsub_(double *day, double *glat, double *glong, double *moonalt, 
+   double *mrv, double *l, double *b, double *paxis);
+
+static const char
+usage[] = "  Usage: tmoon date[yyyymm] timz[+/-h.hh] long[+/-dddmm] lat[+/-ddmm]\n"
+            "example: tmoon 200009 0 -00155 5230\n";
+
+/*
+  getargs() gets the arguments from the command line, does some basic error
+  checking, and converts arguments into numerical form. Arguments are passed
+  back in pointers. Error messages print to stderr so re-direction of output
+  to file won't leave users blind. Error checking prints list of all errors
+  in a command line before quitting.
+*/
+void getargs(int argc, char *argv[], int *y, int *m, double *tz,
+             double *glong, double *glat) {
+
+  int date, latitude, longitude;
+  int mflag = 0, yflag = 0, longflag = 0, latflag = 0, tzflag = 0;
+  int longminflag = 0, latminflag = 0, dflag = 0;
+
+  /* if not right number of arguments, then print example command line */
+
+  if (argc !=5) {
+    fprintf(stderr, usage);
+    exit(EXIT_FAILURE);
+  }
+
+  date = atoi(argv[1]);
+  *y = date / 100;
+  *m = date - *y * 100;
+  *tz = (double) atof(argv[2]);
+  longitude = atoi(argv[3]);
+  latitude = atoi(argv[4]);
+  *glong = RADS * getcoord(longitude);
+  *glat = RADS * getcoord(latitude);
+
+  /* set a flag for each error found */
+
+  if (*m > 12 || *m < 1) mflag = 1;
+  if (*y > 2500) yflag = 1;
+  if (date < 150001) dflag = 1;
+  if (fabs((float) *glong) > 180 * RADS) longflag = 1;
+  if (abs(longitude) % 100 > 59) longminflag = 1;
+  if (fabs((float) *glat) > 90 * RADS) latflag = 1;
+  if (abs(latitude) % 100 > 59) latminflag = 1;
+  if (fabs((float) *tz) > 12) tzflag = 1;
+
+  /* print all the errors found */
+  
+  if (dflag == 1) {
+    fprintf(stderr, "date: dates must be in form yyyymm, gregorian, and later than 1500 AD\n");
+  }
+  if (yflag == 1) {
+    fprintf(stderr, "date: too far in future - accurate from 1500 to 2500\n");
+  }
+  if (mflag == 1) {
+    fprintf(stderr, "date: month must be in range 0 to 12, eg - August 2000 is entered as 200008\n");
+  }
+  if (tzflag == 1) {
+    fprintf(stderr, "timz: must be in range +/- 12 hours, eg -6 for Chicago\n");
+  }
+  if (longflag == 1) {
+    fprintf(stderr, "long: must be in range +/- 180 degrees\n");
+  }
+  if (longminflag == 1) {
+    fprintf(stderr, "long: last two digits are arcmin - max 59\n");
+  }
+  if (latflag == 1) {
+    fprintf(stderr, " lat: must be in range +/- 90 degrees\n");
+  }
+  if (latminflag == 1) {
+    fprintf(stderr, " lat: last two digits are arcmin - max 59\n");
+  }
+
+  /* quits if one or more flags set */
+
+  if (dflag + mflag + yflag + longflag + latflag + tzflag + longminflag + latminflag > 0) {
+    exit(EXIT_FAILURE);
+  }
+  
+}
+
+/*
+   returns coordinates in decimal degrees given the
+   coord as a ddmm value stored in an integer.
+*/
+double getcoord(int coord) {
+  int west = 1;
+  double glg, deg;
+  if (coord < 0) west = -1;
+  glg = fabs((double) coord/100);
+  deg = floor(glg);
+  glg = west* (deg + (glg - deg)*100 / 60);
+  return(glg);
+}
+
+/*
+  days() takes the year, month, day in the month and decimal hours
+  in the day and returns the number of days since J2000.0.
+  Assumes Gregorian calendar.
+*/
+double days(int y, int m, int d, double h) {
+  int a, b;
+  double day;
+  
+  /*
+    The lines below work from 1900 march to feb 2100
+    a = 367 * y - 7 * (y + (m + 9) / 12) / 4 + 275 * m / 9 + d;
+    day = (double)a - 730531.5 + hour / 24;
+  */
+
+  /*  These lines work for any Gregorian date since 0 AD */
+  if (m ==1 || m==2) {
+    m +=12;
+    y -= 1;
+  }
+  a = y / 100;
+  b = 2 - a + a/4;
+  day = floor(365.25*(y + 4716)) + floor(30.6001*(m + 1))
+    + d + b - 1524.5 - 2451545 + h/24;
+  return(day);
+}
+double days_(int *y0, int *m0, int *d0, double *h0) 
+{
+  return days(*y0,*m0,*d0,*h0);
+}
+
+/*
+Returns 1 if y a leap year, and 0 otherwise, according
+to the Gregorian calendar
+*/
+int isleap(int y) {
+  int a = 0;
+  if(y % 4 == 0) a = 1;
+  if(y % 100 == 0) a = 0;
+  if(y % 400 == 0) a = 1;
+  return(a);
+}
+
+/*
+Given the year and the month, function returns the
+number of days in the month. Valid for Gregorian
+calendar.
+*/
+int daysinmonth(int y, int m) {
+  int b = 31;
+  if(m == 2) {
+    if(isleap(y) == 1) b= 29;
+    else b = 28;
+  }
+  if(m == 4 || m == 6 || m == 9 || m == 11) b = 30;
+  return(b);
+}
+
+/*
+moonpos() takes days from J2000.0 and returns ecliptic coordinates
+of moon in the pointers. Note call by reference.
+This function is within a couple of arcminutes most of the time,
+and is truncated from the Meeus Ch45 series, themselves truncations of
+ELP-2000. Returns moon distance in earth radii.
+Terms have been written out explicitly rather than using the
+table based method as only a small number of terms is
+retained.
+*/
+void moonpos(double d, double *lambda, double *beta, double *rvec) {
+  double dl, dB, dR, L, D, M, M1, F, e, lm, bm, rm, t;
+
+  t = d / 36525;
+
+  L = range(218.3164591  + 481267.88134236  * t) * RADS;
+  D = range(297.8502042  + 445267.1115168  * t) * RADS;
+  M = range(357.5291092  + 35999.0502909  * t) * RADS;
+  M1 = range(134.9634114  + 477198.8676313  * t - .008997 * t * t) * RADS;
+  F = range(93.27209929999999  + 483202.0175273  * t - .0034029*t*t)*RADS;
+  e = 1 - .002516 * t;
+
+  dl =      6288774 * sin(M1);
+  dl +=     1274027 * sin(2 * D - M1);
+  dl +=      658314 * sin(2 * D);
+  dl +=      213618 * sin(2 * M1);
+  dl -=  e * 185116 * sin(M);
+  dl -=      114332 * sin(2 * F) ;
+  dl +=       58793 * sin(2 * D - 2 * M1);
+  dl +=   e * 57066 * sin(2 * D - M - M1) ;
+  dl +=       53322 * sin(2 * D + M1);
+  dl +=   e * 45758 * sin(2 * D - M);
+  dl -=   e * 40923 * sin(M - M1);
+  dl -=       34720 * sin(D) ;
+  dl -=   e * 30383 * sin(M + M1) ;
+  dl +=       15327 * sin(2 * D - 2 * F) ;
+  dl -=       12528 * sin(M1 + 2 * F);
+  dl +=       10980 * sin(M1 - 2 * F);
+  lm = rangerad(L + dl / 1000000 * RADS);
+
+  dB =   5128122 * sin(F);
+  dB +=   280602 * sin(M1 + F);
+  dB +=   277693 * sin(M1 - F);
+  dB +=   173237 * sin(2 * D - F);
+  dB +=    55413 * sin(2 * D - M1 + F);
+  dB +=    46271 * sin(2 * D - M1 - F);
+  dB +=    32573 * sin(2 * D + F);
+  dB +=    17198 * sin(2 * M1 + F);
+  dB +=     9266 * sin(2 * D + M1 - F);
+  dB +=     8822 * sin(2 * M1 - F);
+  dB += e * 8216 * sin(2 * D - M - F);
+  dB +=     4324 * sin(2 * D - 2 * M1 - F);
+  bm = dB / 1000000 * RADS;
+
+  dR =    -20905355 * cos(M1);
+  dR -=     3699111 * cos(2 * D - M1);
+  dR -=     2955968 * cos(2 * D);
+  dR -=      569925 * cos(2 * M1);
+  dR +=   e * 48888 * cos(M);
+  dR -=        3149 * cos(2 * F);
+  dR +=      246158 * cos(2 * D - 2 * M1);
+  dR -=  e * 152138 * cos(2 * D - M - M1) ;
+  dR -=      170733 * cos(2 * D + M1);
+  dR -=  e * 204586 * cos(2 * D - M);
+  dR -=  e * 129620 * cos(M - M1);
+  dR +=      108743 * cos(D);
+  dR +=  e * 104755 * cos(M + M1);
+  dR +=       79661 * cos(M1 - 2 * F);
+  rm = 385000.56  + dR / 1000;
+
+  *lambda = lm;
+  *beta = bm;
+  /* distance to Moon must be in Earth radii */
+  *rvec = rm / 6378.14;
+}
+
+/*
+topomoon() takes the local siderial time, the geographical
+latitude of the observer, and pointers to the geocentric
+equatorial coordinates. The function overwrites the geocentric
+coordinates with topocentric coordinates on a simple spherical
+earth model (no polar flattening). Expects Moon-Earth distance in
+Earth radii.    Formulas scavenged from Astronomical Almanac 'low
+precision formulae for Moon position' page D46.
+*/
+
+void topo(double lst, double glat, double *alp, double *dec, double *r) {
+  double x, y, z, r1;
+  x = *r * cos(*dec) * cos(*alp) - cos(glat) * cos(lst);
+  y = *r * cos(*dec) * sin(*alp) - cos(glat) * sin(lst);
+  z = *r * sin(*dec)  - sin(glat);
+  r1 = sqrt(x*x + y*y + z*z);
+  *alp = atan22(y, x);
+  *dec = asin(z / r1);
+  *r = r1;
+}
+
+/*
+moontransit() takes date, the time zone and geographic longitude
+of observer and returns the time (decimal hours) of lunar transit
+on that day if there is one, and sets the notransit flag if there
+isn't. See Explanatory Supplement to Astronomical Almanac
+section 9.32 and 9.31 for the method.
+*/
+
+double moontransit(int y, int m, int d, double tz, double glat, double glong, int *notransit) {
+  double hm, ht, ht1, lon, lat, rv, dnew, lst;
+  int itcount;
+
+  ht1 = 180 * RADS;
+  ht = 0;
+  itcount = 0;
+  *notransit = 0;
+  do {
+    ht = ht1;
+    itcount++;
+    dnew = days(y, m, d, ht * DEGS/15) - tz/24;
+    lst = gst(dnew) + glong;
+    /* find the topocentric Moon ra (hence hour angle) and dec */
+    moonpos(dnew, &lon, &lat, &rv);
+    equatorial(dnew, &lon, &lat, &rv);
+    topo(lst, glat, &lon, &lat, &rv);
+    hm = rangerad(lst -  lon);
+    ht1 = rangerad(ht - hm);
+    /* if no convergence, then no transit on that day */
+    if (itcount > 30) {
+      *notransit = 1;
+      break;
+    }
+  }
+  while (fabs(ht - ht1) > 0.04 * RADS);
+  return(ht1);
+}
+
+/*
+  Calculates the selenographic coordinates of either the sub Earth point
+  (optical libration) or the sub-solar point (selen. coords of centre of
+  bright hemisphere).  Based on Meeus chapter 51 but neglects physical
+  libration and nutation, with some simplification of the formulas.
+*/
+void libration(double day, double lambda, double beta, double alpha, double *l, double *b, double *p) {
+  double i, f, omega, w, y, x, a, t, eps;
+  t = day / 36525;
+  i = 1.54242 * RADS;
+  eps = epsilon(day);
+  f = range(93.2720993 + 483202.0175273 * t - .0034029 * t * t) * RADS;
+  omega = range(125.044555 - 1934.1361849 * t + .0020762 * t * t) * RADS;
+  w = lambda - omega;
+  y = sin(w) * cos(beta) * cos(i) - sin(beta) * sin(i);
+  x = cos(w) * cos(beta);
+  a = atan22(y, x);
+  *l = a - f;
+
+  /*  kludge to catch cases of 'round the back' angles  */
+  if (*l < -90 * RADS) *l += TPI;
+  if (*l > 90 * RADS)  *l -= TPI;
+  *b = asin(-sin(w) * cos(beta) * sin(i) - sin(beta) * cos(i));
+
+  /*  pa pole axis - not used for Sun stuff */
+  x = sin(i) * sin(omega);
+  y = sin(i) * cos(omega) * cos(eps) - cos(i) * sin(eps);
+  w = atan22(x, y);
+  *p = rangerad(asin(sqrt(x*x + y*y) * cos(alpha - w) / cos(*b)));
+}
+
+/*
+  Takes: days since J2000.0, eq coords Moon, ratio of moon to sun distance,
+  eq coords Sun
+  Returns: position angle of bright limb wrt NCP, percentage illumination
+  of Sun
+*/
+void illumination(double day , double lra, double ldec, double dr, double sra, double sdec, double *pabl, double *ill) {
+  double x, y, phi, i;
+  (void)day;
+  y = cos(sdec) * sin(sra - lra);
+  x = sin(sdec) * cos(ldec) - cos(sdec) * sin(ldec) * cos (sra - lra);
+  *pabl = atan22(y, x);
+  phi = acos(sin(sdec) * sin(ldec) + cos(sdec) * cos(ldec) * cos(sra-lra));
+  i = atan22(sin(phi) , (dr - cos(phi)));
+  *ill = 0.5*(1 + cos(i));
+}
+
+/*
+sunpos() takes days from J2000.0 and returns ecliptic longitude
+of Sun in the pointers. Latitude is zero at this level of precision,
+but pointer left in for consistency in number of arguments.
+This function is within 0.01 degree (1 arcmin) almost all the time
+for a century either side of J2000.0. This is from the 'low precision
+fomulas for the Sun' from C24 of Astronomical Alamanac
+*/
+void sunpos(double d, double *lambda, double *beta, double *rvec) {
+  double L, g, ls, bs, rs;
+
+  L = range(280.461 + .9856474 * d) * RADS;
+  g = range(357.528 + .9856003 * d) * RADS;
+  ls = L + (1.915 * sin(g) + .02 * sin(2 * g)) * RADS;
+  bs = 0;
+  rs = 1.00014 - .01671 * cos(g) - .00014 * cos(2 * g);
+  *lambda = ls;
+  *beta = bs;
+  *rvec = rs;
+}
+
+/*
+this routine returns the altitude given the days since J2000.0
+the hour angle and declination of the object and the latitude
+of the observer. Used to find the Sun's altitude to put a letter
+code on the transit time, and to find the Moon's altitude at
+transit just to make sure that the Moon is visible.
+*/
+double alt(double glat, double ha, double dec) {
+  return(asin(sin(dec) * sin(glat) + cos(dec) * cos(glat) * cos(ha)));
+}
+
+/* returns an angle in degrees in the range 0 to 360 */
+double range(double x) {
+  double a, b;
+  b = x / 360;
+  a = 360 * (b - floor(b));
+  if (a < 0)
+    a = 360 + a;
+  return(a);
+}
+
+/* returns an angle in rads in the range 0 to two pi */
+double rangerad(double x) {
+  double a, b;
+  b = x / TPI;
+  a = TPI * (b - floor(b));
+  if (a < 0)
+    a = TPI + a;
+  return(a);
+}
+
+/*
+gets the atan2 function returning angles in the right
+order and  range
+*/
+double atan22(double y, double x) {
+  double a;
+
+  a = atan2(y, x);
+  if (a < 0) a += TPI;
+  return(a);
+}
+
+/*
+returns mean obliquity of ecliptic in radians given days since
+J2000.0.
+*/
+double epsilon(double d) {
+  double t = d/ 36525;
+  return((23.4392911111111 - (t* (46.8150 + 0.00059*t)/3600)) *RADS);
+}
+
+/*
+replaces ecliptic coordinates with equatorial coordinates
+note: call by reference destroys original values
+R is unchanged.
+*/
+void equatorial(double d, double *lon, double *lat, double * r) {
+  double  eps, ceps, seps, l, b;
+  (void)r;
+
+  l = *lon;
+  b = * lat;
+  eps = epsilon(d);
+  ceps = cos(eps);
+  seps = sin(eps);
+  *lon = atan22(sin(l)*ceps - tan(b)*seps, cos(l));
+  *lat = asin(sin(b)*ceps + cos(b)*seps*sin(l));
+}
+
+/*
+replaces equatorial coordinates with ecliptic ones. Inverse
+of above, but used to find topocentric ecliptic coords.
+*/
+void ecliptic(double d, double *lon, double *lat, double * r) {
+  double  eps, ceps, seps, alp, dec;
+  (void)r;
+
+  alp = *lon;
+  dec = *lat;
+  eps = epsilon(d);
+  ceps = cos(eps);
+  seps = sin(eps);
+  *lon = atan22(sin(alp)*ceps + tan(dec)*seps, cos(alp));
+  *lat = asin(sin(dec)*ceps - cos(dec)*seps*sin(alp));
+}
+
+/*
+returns the siderial time at greenwich meridian as
+an angle in radians given the days since J2000.0
+*/
+double gst( double d) {
+  double t = d / 36525;
+  double theta;
+  theta = range(280.46061837 + 360.98564736629 * d + 0.000387933 * t * t);
+  return(theta * RADS);
+}
+
+void tmoonsub_(double *day, double *glat, double *glong, double *moonalt, 
+   double *mrv, double *l, double *b, double *paxis)
+{
+  double mlambda, mbeta;
+  double malpha, mdelta;
+  double lst, mhr;
+  double tlambda, tbeta, trv;
+
+  lst = gst(*day) + *glong;
+      
+  /* find Moon topocentric coordinates for libration calculations */
+
+  moonpos(*day, &mlambda, &mbeta, mrv);
+  malpha = mlambda;
+  mdelta = mbeta;
+  equatorial(*day, &malpha, &mdelta, mrv);
+  topo(lst, *glat, &malpha, &mdelta, mrv);
+  mhr = rangerad(lst - malpha);
+  *moonalt = alt(*glat, mhr, mdelta);
+      
+  /* Optical libration and Position angle of the Pole */
+
+  tlambda = malpha;
+  tbeta = mdelta;
+  trv = *mrv;
+  ecliptic(*day, &tlambda, &tbeta, &trv);
+  libration(*day, tlambda, tbeta, malpha,  l, b, paxis);
+}
diff --git a/lib/toxyz.f90 b/lib/toxyz.f90
new file mode 100644
index 0000000..646dd7a
--- /dev/null
+++ b/lib/toxyz.f90
@@ -0,0 +1,25 @@
+subroutine toxyz(alpha,delta,r,vec)
+
+  implicit real*8 (a-h,o-z)
+  real*8 vec(3)
+
+  vec(1)=r*cos(delta)*cos(alpha)
+  vec(2)=r*cos(delta)*sin(alpha)
+  vec(3)=r*sin(delta)
+
+  return
+end subroutine toxyz
+
+subroutine fromxyz(vec,alpha,delta,r)
+
+  implicit real*8 (a-h,o-z)
+  real*8 vec(3)
+  data twopi/6.283185307d0/
+
+  r=sqrt(vec(1)**2 + vec(2)**2 + vec(3)**2)
+  alpha=atan2(vec(2),vec(1))
+  if(alpha.lt.0.d0) alpha=alpha+twopi
+  delta=asin(vec(3)/r)
+
+  return
+end subroutine fromxyz
diff --git a/lib/twkfreq.f90 b/lib/twkfreq.f90
index 0a9b34d..7c240d5 100644
--- a/lib/twkfreq.f90
+++ b/lib/twkfreq.f90
@@ -13,13 +13,11 @@ subroutine twkfreq(c3,c4,npts,fsample,a)
   s=2.0/npts
   do i=1,npts
      x=s*(i-x0)
-     if(mod(i,100).eq.1) then
-        p2=1.5*x*x - 0.5
+     p2=1.5*x*x - 0.5
 !          p3=2.5*(x**3) - 1.5*x
 !          p4=4.375*(x**4) - 3.75*(x**2) + 0.375
-        dphi=(a(1) + x*a(2) + p2*a(3)) * (twopi/fsample)
-        wstep=cmplx(cos(dphi),sin(dphi))
-     endif
+     dphi=(a(1) + x*a(2) + p2*a(3)) * (twopi/fsample)
+     wstep=cmplx(cos(dphi),sin(dphi))
      w=w*wstep
      c4(i)=w*c3(i)
   enddo
diff --git a/lib/unpackcall.f90 b/lib/unpackcall.f90
index f738926..3b009b2 100644
--- a/lib/unpackcall.f90
+++ b/lib/unpackcall.f90
@@ -5,11 +5,13 @@ subroutine unpackcall(ncall,word,iv2,psfx)
 
   data c/'0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ '/
 
+  word='......' 
+  psfx='    '
   n=ncall
   iv2=0
   if(n.ge.262177560) go to 20
   word='......'
-  if(n.ge.262177560) go to 999            !Plain text message ...
+!  if(n.ge.262177560) go to 999            !Plain text message ...
   i=mod(n,27)+11
   word(6:6)=c(i:i)
   n=n/27
@@ -37,7 +39,7 @@ subroutine unpackcall(ncall,word,iv2,psfx)
 20 if(n.ge.267796946) go to 999
 
 ! We have a JT65v2 message
-  if((n.ge.262178563) .and. (n.le.264002071)) Then
+  if((n.ge.262178563) .and. (n.le.264002071)) then
 ! CQ with prefix
      iv2=1
      n=n-262178563
@@ -52,9 +54,8 @@ subroutine unpackcall(ncall,word,iv2,psfx)
      n=n/37
      i=n+1
      psfx(1:1)=c(i:i)
-  endif
 
-  if((n.ge.264002072) .and. (n.le.265825580)) Then
+  else if((n.ge.264002072) .and. (n.le.265825580)) then
 ! QRZ with prefix
      iv2=2
      n=n-264002072
@@ -69,9 +70,8 @@ subroutine unpackcall(ncall,word,iv2,psfx)
      n=n/37
      i=n+1
      psfx(1:1)=c(i:i)
-  endif
 
-  if((n.ge.265825581) .and. (n.le.267649089)) Then
+  else if((n.ge.265825581) .and. (n.le.267649089)) then
 ! DE with prefix
      iv2=3
      n=n-265825581
@@ -86,9 +86,8 @@ subroutine unpackcall(ncall,word,iv2,psfx)
      n=n/37
      i=n+1
      psfx(1:1)=c(i:i)
-  endif
 
-  if((n.ge.267649090) .and. (n.le.267698374)) Then
+  else if((n.ge.267649090) .and. (n.le.267698374)) then
 ! CQ with suffix
      iv2=4
      n=n-267649090
@@ -100,9 +99,8 @@ subroutine unpackcall(ncall,word,iv2,psfx)
      n=n/37
      i=n+1
      psfx(1:1)=c(i:i)
-  endif
 
-  if((n.ge.267698375) .and. (n.le.267747659)) Then
+  else if((n.ge.267698375) .and. (n.le.267747659)) then
 ! QRZ with suffix
      iv2=5
      n=n-267698375
@@ -114,9 +112,8 @@ subroutine unpackcall(ncall,word,iv2,psfx)
      n=n/37
      i=n+1
      psfx(1:1)=c(i:i)
-  endif
 
-  if((n.ge.267747660) .and. (n.le.267796944)) Then
+  else if((n.ge.267747660) .and. (n.le.267796944)) then
 ! DE with suffix
      iv2=6
      n=n-267747660
@@ -128,9 +125,8 @@ subroutine unpackcall(ncall,word,iv2,psfx)
      n=n/37
      i=n+1
      psfx(1:1)=c(i:i)
-  endif
 
-  if(n.eq.267796945) Then
+  else if(n.eq.267796945) then
 ! DE with no prefix or suffix
      iv2=7
      psfx = '    '
diff --git a/lib/unpackmsg.f90 b/lib/unpackmsg.f90
index aca7cfc..531bb30 100644
--- a/lib/unpackmsg.f90
+++ b/lib/unpackmsg.f90
@@ -52,6 +52,7 @@ subroutine unpackmsg(dat,msg)
      if(iv2.eq.5) msg='QRZ '//c2(:n2)//'/'//psfx(:n1)//' '//grid
      if(iv2.eq.6) msg='DE '//c2(:n2)//'/'//psfx(:n1)//' '//grid
      if(iv2.eq.7) msg='DE '//c2(:n2)//' '//grid
+     if(iv2.eq.8) msg=' '
      go to 100
   else
      
diff --git a/lib/usleep.c b/lib/usleep.c
new file mode 100644
index 0000000..6fbc98c
--- /dev/null
+++ b/lib/usleep.c
@@ -0,0 +1,8 @@
+#include <unistd.h>
+#include "sleep.h"
+
+/* usleep(3) */
+void usleep_(unsigned long *microsec)
+{
+  usleep(*microsec);
+}
diff --git a/lib/wavhdr.f90 b/lib/wavhdr.f90
new file mode 100644
index 0000000..b42d5e8
--- /dev/null
+++ b/lib/wavhdr.f90
@@ -0,0 +1,38 @@
+module wavhdr
+  type hdr
+     character*4 ariff
+     integer*4 lenfile
+     character*4 awave
+     character*4 afmt
+     integer*4 lenfmt
+     integer*2 nfmt2
+     integer*2 nchan2
+     integer*4 nsamrate
+     integer*4 nbytesec
+     integer*2 nbytesam2
+     integer*2 nbitsam2
+     character*4 adata
+     integer*4 ndata
+  end type hdr
+
+  contains
+
+    function default_header(nsamrate,npts)
+      type(hdr) default_header,h
+      h%ariff='RIFF'
+      h%awave='WAVE'
+      h%afmt='fmt '
+      h%lenfmt=16
+      h%nfmt2=1
+      h%nchan2=1
+      h%nsamrate=nsamrate
+      h%nbitsam2=16
+      h%nbytesam2=h%nbitsam2 * h%nchan2 / 8
+      h%adata='data'
+      h%nbytesec=h%nsamrate * h%nbitsam2 * h%nchan2 / 8
+      h%ndata=2*npts
+      h%lenfile=h%ndata + 44 - 8
+      default_header=h
+    end function default_header
+
+end module wavhdr
diff --git a/lib/wisdom.c b/lib/wisdom.c
new file mode 100644
index 0000000..ef008a7
--- /dev/null
+++ b/lib/wisdom.c
@@ -0,0 +1,13 @@
+void export_wisdom_(char fname[], int len)
+{
+  int fftwf_export_wisdom_to_filename(const char *);
+  fname[len-1]=0;
+  fftwf_export_wisdom_to_filename(fname);
+}
+
+void import_wisdom_(char fname[], int *success, int len)
+{
+  int fftwf_import_wisdom_from_filename(const char *);
+  fname[len-1]=0;
+  *success = fftwf_import_wisdom_from_filename(fname);
+}
diff --git a/lib/wisdom1.bat b/lib/wisdom1.bat
new file mode 100644
index 0000000..ae1243f
--- /dev/null
+++ b/lib/wisdom1.bat
@@ -0,0 +1,2 @@
+C:\JTSDK-QT\fftw3f\fftwf-wisdom -o fftwf_wisdom.dat -t 1 -m rif672000 cif77175 cib77175 rif16384 rif884736 cib2048 rif8192 rif512 rib512 cib512
+
diff --git a/lib/wrapkarn.c b/lib/wrapkarn.c
index 1b1a631..9e0a51c 100644
--- a/lib/wrapkarn.c
+++ b/lib/wrapkarn.c
@@ -1,70 +1,70 @@
-#include <math.h>
-#include <stdio.h>
-#include <float.h>
-#include <limits.h>
-#include <stdlib.h>
-#include "rs.h"
-
-static void *rs;
-static int first=1;
-
-void rs_encode_(int *dgen, int *sent)
-// Encode JT65 data dgen[12], producing sent[63].
-{
-  int dat1[12];
-  int b[51];
-  int i;
-
-  if(first) {
-    // Initialize the JT65 codec
-    rs=init_rs_int(6,0x43,3,1,51,0);
-    first=0;
-  }
-
-  // Reverse data order for the Karn codec.
-  for(i=0; i<12; i++) {
-    dat1[i]=dgen[11-i];
-  }
-  // Compute the parity symbols
-  encode_rs_int(rs,dat1,b);
-
-  // Move parity symbols and data into sent[] array, in reverse order.
-  for (i = 0; i < 51; i++) sent[50-i] = b[i];
-  for (i = 0; i < 12; i++) sent[i+51] = dat1[11-i];
-}
-
-void rs_decode_(int *recd0, int *era0, int *numera0, int *decoded, int *nerr)
-// Decode JT65 received data recd0[63], producing decoded[12].
-// Erasures are indicated in era0[numera].  The number of corrected
-// errors is *nerr.  If the data are uncorrectable, *nerr=-1 is returned.
-{
-  int numera;
-  int i;
-  int era_pos[50];
-  int recd[63];
-
-  if(first) {
-    rs=init_rs_int(6,0x43,3,1,51,0);
-    first=0;
-  }
-
-  numera=*numera0;
-  for(i=0; i<12; i++) recd[i]=recd0[62-i];
-  for(i=0; i<51; i++) recd[12+i]=recd0[50-i];
-  if(numera) 
-    for(i=0; i<numera; i++) era_pos[i]=era0[i];
-  *nerr=decode_rs_int(rs,recd,era_pos,numera);
-  for(i=0; i<12; i++) decoded[i]=recd[11-i];
-}
-
-
-void rs_encode__(int *dgen, int *sent)
-{
-  rs_encode_(dgen, sent);
-}
-
-void rs_decode__(int *recd0, int *era0, int *numera0, int *decoded, int *nerr)
-{
-  rs_decode_(recd0, era0, numera0, decoded, nerr);
-}
-
+#include <math.h>
+#include <stdio.h>
+#include <float.h>
+#include <limits.h>
+#include <stdlib.h>
+#include "rs.h"
+
+static void *rs;
+static int first=1;
+
+void rs_encode_(int *dgen, int *sent)
+// Encode JT65 data dgen[12], producing sent[63].
+{
+  int dat1[12];
+  int b[51];
+  int i;
+
+  if(first) {
+    // Initialize the JT65 codec
+    rs=init_rs_int(6,0x43,3,1,51,0);
+    first=0;
+  }
+
+  // Reverse data order for the Karn codec.
+  for(i=0; i<12; i++) {
+    dat1[i]=dgen[11-i];
+  }
+  // Compute the parity symbols
+  encode_rs_int(rs,dat1,b);
+
+  // Move parity symbols and data into sent[] array, in reverse order.
+  for (i = 0; i < 51; i++) sent[50-i] = b[i];
+  for (i = 0; i < 12; i++) sent[i+51] = dat1[11-i];
+}
+
+void rs_decode_(int *recd0, int *era0, int *numera0, int *decoded, int *nerr)
+// Decode JT65 received data recd0[63], producing decoded[12].
+// Erasures are indicated in era0[numera].  The number of corrected
+// errors is *nerr.  If the data are uncorrectable, *nerr=-1 is returned.
+{
+  int numera;
+  int i;
+  int era_pos[50];
+  int recd[63];
+
+  if(first) {
+    rs=init_rs_int(6,0x43,3,1,51,0);
+    first=0;
+  }
+
+  numera=*numera0;
+  for(i=0; i<12; i++) recd[i]=recd0[62-i];
+  for(i=0; i<51; i++) recd[12+i]=recd0[50-i];
+  if(numera) 
+    for(i=0; i<numera; i++) era_pos[i]=era0[i];
+  *nerr=decode_rs_int(rs,recd,era_pos,numera);
+  for(i=0; i<12; i++) decoded[i]=recd[11-i];
+}
+
+
+void rs_encode__(int *dgen, int *sent)
+{
+  rs_encode_(dgen, sent);
+}
+
+void rs_decode__(int *recd0, int *era0, int *numera0, int *decoded, int *nerr)
+{
+  rs_decode_(recd0, era0, numera0, decoded, nerr);
+}
+
diff --git a/logbook/adif.cpp b/logbook/adif.cpp
new file mode 100644
index 0000000..fb6b3bc
--- /dev/null
+++ b/logbook/adif.cpp
@@ -0,0 +1,206 @@
+#include "adif.h"
+
+#include <QFile>
+#include <QTextStream>
+#include <QDebug>
+
+/*
+<CALL:4>W1XT<BAND:3>20m<FREQ:6>14.076<GRIDSQUARE:4>DM33<MODE:4>JT65<RST_RCVD:3>-21<RST_SENT:3>-14<QSO_DATE:8>20110422<TIME_ON:4>0417<TIME_OFF:4>0424<TX_PWR:1>4<COMMENT:34>1st JT65A QSO.   Him: mag loop 20W<STATION_CALLSIGN:6>VK3ACF<MY_GRIDSQUARE:6>qf22lb<eor>
+<CALL:6>IK1SOW<BAND:3>20m<FREQ:6>14.076<GRIDSQUARE:4>JN35<MODE:4>JT65<RST_RCVD:3>-19<RST_SENT:3>-11<QSO_DATE:8>20110422<TIME_ON:4>0525<TIME_OFF:4>0533<TX_PWR:1>3<STATION_CALLSIGN:6>VK3ACF<MY_GRIDSQUARE:6>qf22lb<eor>
+<CALL:6:S>W4ABC> ...
+*/
+
+void ADIF::init(QString filename)
+{
+    _filename = filename;
+    _data.clear(); 
+}
+
+
+QString ADIF::_extractField(const QString line, const QString fieldName)
+{
+    int fieldNameIndex = line.indexOf(fieldName,0,Qt::CaseInsensitive);
+    if (fieldNameIndex >=0)
+    {
+        int closingBracketIndex = line.indexOf('>',fieldNameIndex);
+        int fieldLengthIndex = line.indexOf(':',fieldNameIndex);  // find the size delimiter
+        int dataTypeIndex = -1;
+        if (fieldLengthIndex >= 0)
+        {
+          dataTypeIndex = line.indexOf(':',fieldLengthIndex+1);  // check for a second : indicating there is a data type
+          if (dataTypeIndex > closingBracketIndex)
+            dataTypeIndex = -1; // second : was found but it was beyond the closing >
+        }
+
+        if ((closingBracketIndex > fieldNameIndex) && (fieldLengthIndex > fieldNameIndex) && (fieldLengthIndex< closingBracketIndex))
+        {
+            int fieldLengthCharCount = closingBracketIndex - fieldLengthIndex -1;
+            if (dataTypeIndex >= 0)
+              fieldLengthCharCount -= 2; // data type indicator is always a colon followed by a single character
+            QString fieldLengthString = line.mid(fieldLengthIndex+1,fieldLengthCharCount);
+            int fieldLength = fieldLengthString.toInt();
+            if (fieldLength > 0)
+            {
+              QString field = line.mid(closingBracketIndex+1,fieldLength);
+              return field;
+            }
+       }
+    }
+    return "";
+}
+
+
+
+void ADIF::load()
+{
+    _data.clear();
+    QFile inputFile(_filename);
+    if (inputFile.open(QIODevice::ReadOnly))
+    {
+        QTextStream in(&inputFile);
+        while ( !in.atEnd() )
+        {
+            QString line = in.readLine();
+            QSO q;
+            q.call = _extractField(line,"CALL:");
+            q.band = _extractField(line,"BAND:");
+            q.mode = _extractField(line,"MODE:");
+            q.date = _extractField(line,"QSO_DATE:");
+            if (q.call != "")
+            _data.insert(q.call,q);
+        }
+        inputFile.close();
+    }
+}
+
+
+void ADIF::add(const QString call, const QString band, const QString mode, const QString date)
+{
+    QSO q;
+    q.call = call;
+    q.band = band;
+    q.mode = mode;
+    q.date = date;
+    _data.insert(q.call,q);
+    //qDebug() << "Added as worked:" << call << band << mode << date;
+}
+
+// return true if in the log same band and mode (where JT65 == JT9)
+bool ADIF::match(const QString call, const QString band, const QString mode)
+{
+    QList<QSO> qsos = _data.values(call);
+    if (qsos.size()>0)
+    {
+        QSO q;
+        foreach(q,qsos)
+        {
+            if (     (band.compare(q.band,Qt::CaseInsensitive) == 0)
+                  || (band=="")
+                  || (q.band==""))
+            {
+                if (
+                     (
+                       ((mode.compare("JT65",Qt::CaseInsensitive)==0) || (mode.compare("JT9",Qt::CaseInsensitive)==0))
+                       &&
+                       ((q.mode.compare("JT65",Qt::CaseInsensitive)==0) || (q.mode.compare("JT9",Qt::CaseInsensitive)==0))
+                     )
+                        || (mode.compare(q.mode,Qt::CaseInsensitive)==0)
+                        || (mode=="")
+                        || (q.mode=="")
+                    )
+                return true;
+            }
+        }
+    }
+    return false;
+}    
+
+QList<QString> ADIF::getCallList()
+{
+    QList<QString> p;
+    QMultiHash<QString,QSO>::const_iterator i = _data.constBegin();
+     while (i != _data.constEnd())
+     {
+         p << i.key();
+         ++i;
+     }
+    return p;
+}   
+    
+int ADIF::getCount()
+{
+    return _data.size();
+}   
+    
+
+// open ADIF file and append the QSO details. Return true on success
+bool ADIF::addQSOToFile(const QString hisCall, const QString hisGrid, const QString mode, const QString rptSent, const QString rptRcvd, const QString date, const QString time, const QString band,
+                        const QString comments, const QString name, const QString strDialFreq, const QString m_myCall, const QString m_myGrid, const QString m_txPower)
+{
+    QFile f2(_filename);
+    if (!f2.open(QIODevice::Text | QIODevice::Append))
+        return false;
+    else
+    {
+        QTextStream out(&f2);
+        if (f2.size()==0)
+            out << "WSJT-X ADIF Export<eoh>" << endl;  // new file
+
+        QString t;
+        t="<call:" + QString::number(hisCall.length()) + ">" + hisCall;
+        t+=" <gridsquare:" + QString::number(hisGrid.length()) + ">" + hisGrid;
+        t+=" <mode:" + QString::number(mode.length()) + ">" + mode;
+        t+=" <rst_sent:" + QString::number(rptSent.length()) + ">" + rptSent;
+        t+=" <rst_rcvd:" + QString::number(rptRcvd.length()) + ">" + rptRcvd;
+        t+=" <qso_date:8>" + date;
+        t+=" <time_on:4>" + time;
+        t+=" <band:" + QString::number(band.length()) + ">" + band;
+        t+=" <freq:" + QString::number(strDialFreq.length()) + ">" + strDialFreq;
+        t+=" <station_callsign:" + QString::number(m_myCall.length()) + ">" +
+                m_myCall;
+        t+=" <my_gridsquare:" + QString::number(m_myGrid.length()) + ">" +
+                m_myGrid;
+        if(m_txPower!="") t+= " <tx_pwr:" + QString::number(m_txPower.length()) +
+                ">" + m_txPower;
+        if(comments!="") t+=" <comment:" + QString::number(comments.length()) +
+                ">" + comments;
+        if(name!="") t+=" <name:" + QString::number(name.length()) +
+                ">" + name;
+        t+=" <eor>";
+        out << t << endl;
+        f2.close();
+    }
+    return true;
+}
+
+QString ADIF::bandFromFrequency(double dialFreq)
+{
+    QString band="";
+    if(dialFreq>0.135 and dialFreq<0.139) band="2200m";
+    else if(dialFreq>0.45 and dialFreq<0.55) band="630m";
+    else if(dialFreq>1.8 and dialFreq<2.0) band="160m";
+    else if(dialFreq>3.5 and dialFreq<4.0) band="80m";
+    else if(dialFreq>5.1 and dialFreq<5.45) band="60m";
+    else if(dialFreq>7.0 and dialFreq<7.3) band="40m";
+    else if(dialFreq>10.0 and dialFreq<10.15) band="30m";
+    else if(dialFreq>14.0 and dialFreq<14.35) band="20m";
+    else if(dialFreq>18.068 and dialFreq<18.168) band="17m";
+    else if(dialFreq>21.0 and dialFreq<21.45) band="15m";
+    else if(dialFreq>24.890 and dialFreq<24.990) band="12m";
+    else if(dialFreq>28.0 and dialFreq<29.7) band="10m";
+    else if(dialFreq>50.0 and dialFreq<54.0) band="6m";
+    else if(dialFreq>70.0 and dialFreq<71.0) band="4m";
+    else if(dialFreq>144.0 and dialFreq<148.0) band="2m";
+    else if(dialFreq>222.0 and dialFreq<225.0) band="1.25m";
+    else if(dialFreq>420.0 and dialFreq<450.0) band="70cm";
+    else if(dialFreq>902.0 and dialFreq<928.0) band="33cm";
+    else if(dialFreq>1240.0 and dialFreq<1300.0) band="23cm";
+    else if(dialFreq>2300.0 and dialFreq<2450.0) band="13cm";
+    else if(dialFreq>3300.0 and dialFreq<3500.0) band="9cm";
+    else if(dialFreq>5650.0 and dialFreq<5925.0) band="6cm";
+    else if(dialFreq>10000.0 and dialFreq<10500.0) band="3cm";
+    else if(dialFreq>24000.0 and dialFreq<24250.0) band="1.25cm";
+    else if(dialFreq>47000.0 and dialFreq<47200.0) band="6mm";
+    else if(dialFreq>75500.0 and dialFreq<81000.0) band="4mm";
+    return band;
+}
diff --git a/logbook/adif.h b/logbook/adif.h
new file mode 100644
index 0000000..7445d4a
--- /dev/null
+++ b/logbook/adif.h
@@ -0,0 +1,50 @@
+/*
+ * Reads an ADIF log file into memory
+ * Searches log for call, band and mode
+ * VK3ACF July 2013
+ */
+
+
+#ifndef __ADIF_H
+#define __ADIF_H
+
+#if defined (QT5)
+#include <QList>
+#include <QString>
+#include <QMultiHash>
+#else
+#include <QtGui>
+#endif
+
+
+class ADIF
+{
+	public:
+        void init(QString filename);
+		void load();
+        void add(const QString call, const QString band, const QString mode, const QString date);
+        bool match(const QString call, const QString band, const QString mode);
+        QList<QString> getCallList();
+		int getCount();
+		
+        // open ADIF file and append the QSO details. Return true on success
+        bool addQSOToFile(const QString hisCall, const QString hisGrid, const QString mode, const QString rptSent, const QString rptRcvd, const QString date, const QString time, const QString band,
+                                const QString comments, const QString name, const QString strDialFreq, const QString m_myCall, const QString m_myGrid, const QString m_txPower);
+
+        static QString bandFromFrequency(double dialFreq);
+
+	private:
+		struct QSO
+		{
+		  QString call,band,mode,date;
+		};		  
+
+        QMultiHash<QString, QSO> _data;
+		QString _filename;
+		
+        QString _extractField(const QString line, const QString fieldName);
+};
+
+
+#endif
+
diff --git a/logbook/countriesworked.cpp b/logbook/countriesworked.cpp
new file mode 100644
index 0000000..a70a4e1
--- /dev/null
+++ b/logbook/countriesworked.cpp
@@ -0,0 +1,42 @@
+#include "countriesworked.h"
+
+void CountriesWorked::init(const QStringList countryNames)
+{
+    _data.clear();
+    foreach(QString name,countryNames)
+      _data.insert(name,false);
+}
+
+void CountriesWorked::setAsWorked(const QString countryName)
+{
+    if (_data.contains(countryName))
+      _data.insert(countryName,true);
+}     
+      
+bool CountriesWorked::getHasWorked(const QString countryName)
+{  
+    if (_data.contains(countryName))
+      return _data.value(countryName);  
+
+    return false;
+}
+    
+int CountriesWorked::getWorkedCount()
+{
+    int count = 0;
+	foreach (bool value,_data)
+		if (value)
+			count += 1;
+    return count;
+}
+    
+int CountriesWorked::getSize()
+{
+    return _data.count();
+}
+    
+    
+        
+    
+    
+      
diff --git a/logbook/countriesworked.h b/logbook/countriesworked.h
new file mode 100644
index 0000000..34fcc0c
--- /dev/null
+++ b/logbook/countriesworked.h
@@ -0,0 +1,29 @@
+/*
+ * maintains a list of country names that have been worked
+ * VK3ACF July 2013
+ */
+
+#ifndef __COUNTRIESWORKDED_H
+#define __COUNTRIESWORKDED_H
+
+#include <QList>
+#include <QString>
+#include <QStringList>
+#include <QHash>
+
+
+class CountriesWorked
+{
+	public:
+        void init(const QStringList countryNames);
+        void setAsWorked(const QString countryName);
+        bool getHasWorked(const QString countryName);
+		int getWorkedCount();
+		int getSize();
+		
+	private:
+		QHash<QString, bool> _data;
+};
+
+#endif
+
diff --git a/logbook/countrydat.cpp b/logbook/countrydat.cpp
new file mode 100644
index 0000000..1d88e05
--- /dev/null
+++ b/logbook/countrydat.cpp
@@ -0,0 +1,136 @@
+/*
+#Sov Mil Order of Malta:   15:  28:  EU:   41.90:   -12.43:    -1.0:  1A:
+    #1A;
+#Spratly Islands:          26:  50:  AS:    9.88:  -114.23:    -8.0:  1S:
+    #1S,9M0,BV9S;
+#Monaco:                   14:  27:  EU:   43.73:    -7.40:    -1.0:  3A:
+    #3A;
+#Heard Island:             39:  68:  AF:  -53.08:   -73.50:    -5.0:  VK0H:
+    #=VK0IR;
+#Macquarie Island:         30:  60:  OC:  -54.60:  -158.88:   -10.0:  VK0M:
+    #=VK0KEV;
+#Cocos-Keeling:            29:  54:  OC:  -12.15:   -96.82:    -6.5:  VK9C:
+    #AX9C,AX9Y,VH9C,VH9Y,VI9C,VI9Y,VJ9C,VJ9Y,VK9C,VK9Y,VL9C,VL9Y,VM9C,VM9Y,
+    #VN9C,VN9Y,VZ9C,VZ9Y,=VK9AA;
+*/
+
+
+#include "countrydat.h"
+#include <QFile>
+#include <QTextStream>
+
+
+void CountryDat::init(const QString filename)
+{
+    _filename = filename;
+    _data.clear();
+}
+
+QString CountryDat::_extractName(const QString line)
+{
+    int s1 = line.indexOf(':');
+    if (s1>=0)
+    {
+        QString name = line.mid(0,s1);
+        return name;
+    }
+    return "";
+}
+
+void CountryDat::_removeBrackets(QString &line, const QString a, const QString b)
+{
+    int s1 = line.indexOf(a);
+    while (s1 >= 0)
+    {
+      int s2 = line.indexOf(b);
+      line = line.mid(0,s1) + line.mid(s2+1,-1);
+      s1 = line.indexOf(a);
+    }
+}    
+
+QStringList CountryDat::_extractPrefix(QString &line, bool &more)
+{
+    line = line.remove(" \n");
+    line = line.replace("=","");
+    line = line.replace(" ","");
+
+    _removeBrackets(line,"(",")");
+    _removeBrackets(line,"[","]");
+    _removeBrackets(line,"<",">");
+    _removeBrackets(line,"~","~");
+
+    int s1 = line.indexOf(';');
+    more = true;
+    if (s1 >= 0)
+    {
+      line = line.mid(0,s1);
+      more = false;
+    }
+
+    QStringList r = line.split(',');
+
+    return r;
+}
+
+
+void CountryDat::load()
+{
+    _data.clear();
+    _countryNames.clear(); //used by countriesWorked
+  
+    QFile inputFile(_filename);
+    if (inputFile.open(QIODevice::ReadOnly))
+    {
+       QTextStream in(&inputFile);
+       while ( !in.atEnd() )
+       {
+          QString line1 = in.readLine();
+          if ( !in.atEnd() )
+          {
+            QString line2 = in.readLine();
+              
+            QString name = _extractName(line1);
+            if (name.length()>0)
+            {
+                _countryNames << name;
+                bool more = true;
+                QStringList prefixs;
+                while (more)
+                {
+                    QStringList p = _extractPrefix(line2,more);
+                    prefixs += p;
+                    if (more)
+                        line2 = in.readLine();
+                }
+
+                QString p;
+                foreach(p,prefixs)
+                {
+                    if (p.length() > 0)
+                        _data.insert(p,name);
+                }
+            }
+          }
+       }
+    inputFile.close();
+    }
+}
+
+// return country name else ""
+QString CountryDat::find(const QString prefix)
+{
+    QString pf = prefix.toUpper();
+    while(pf.length() >= 1)
+  	{
+      if (_data.contains(pf))
+	  {
+        QString country = _data.value(pf);
+	    return country;
+	   }
+       pf = pf.left(pf.length()-1);
+	 }
+	 return "";
+}	   
+
+      
+
diff --git a/logbook/countrydat.h b/logbook/countrydat.h
new file mode 100644
index 0000000..cd550cf
--- /dev/null
+++ b/logbook/countrydat.h
@@ -0,0 +1,35 @@
+/*
+ * Reads cty.dat file
+ * Establishes a map between prefixes and their country names
+ * VK3ACF July 2013
+ */
+
+
+#ifndef __COUNTRYDAT_H
+#define __COUNTRYDAT_H
+
+
+#include <QString>
+#include <QStringList>
+#include <QHash>
+
+
+class CountryDat
+{
+	public:
+        void init(const QString filename);
+		void load();
+        QString find(const QString prefix); // return country name or ""
+		QStringList  getCountryNames() { return _countryNames; };
+   
+	private:
+        QString _extractName(const QString line);
+        void _removeBrackets(QString &line, const QString a, const QString b);
+        QStringList _extractPrefix(QString &line, bool &more);
+		
+        QString _filename;
+		QStringList _countryNames;
+		QHash<QString, QString> _data;
+};
+
+#endif
diff --git a/logbook/logbook.cpp b/logbook/logbook.cpp
new file mode 100644
index 0000000..f074116
--- /dev/null
+++ b/logbook/logbook.cpp
@@ -0,0 +1,99 @@
+#include "logbook.h"
+#include <QDebug>
+#include <QFontMetrics>
+#include <QStandardPaths>
+#include <QDir>
+
+namespace
+{
+  auto logFileName = "wsjtx_log.adi";
+  auto countryFileName = "cty.dat";
+}
+
+void LogBook::init()
+{
+  QDir dataPath {QStandardPaths::writableLocation (QStandardPaths::DataLocation)};
+  QString countryDataFilename;
+  if (dataPath.exists (countryFileName))
+    {
+      // User override
+      countryDataFilename = dataPath.absoluteFilePath (countryFileName);
+    }
+  else
+    {
+      countryDataFilename = QString {":/"} + countryFileName;
+    }
+
+  _countries.init(countryDataFilename);
+  _countries.load();
+
+  _worked.init(_countries.getCountryNames());
+
+  _log.init(dataPath.absoluteFilePath (logFileName));
+  _log.load();
+
+  _setAlreadyWorkedFromLog();
+
+  /*
+    int QSOcount = _log.getCount();
+    int count = _worked.getWorkedCount();
+    qDebug() << QSOcount << "QSOs and" << count << "countries worked in file" << logFilename;
+  */
+
+  //    QString call = "ok1ct";
+  //    QString countryName;
+  //    bool callWorkedBefore,countryWorkedBefore;
+  //    match(/*in*/call, /*out*/ countryName,callWorkedBefore,countryWorkedBefore);
+  //    qDebug() << countryName;
+
+}
+
+
+void LogBook::_setAlreadyWorkedFromLog()
+{
+  QList<QString> calls = _log.getCallList();
+  QString c;
+  foreach(c,calls)
+    {
+      QString countryName = _countries.find(c);
+      if (countryName.length() > 0)
+        {
+          _worked.setAsWorked(countryName);
+          //qDebug() << countryName << " worked " << c;
+        }
+    }
+}
+
+void LogBook::match(/*in*/const QString call,
+                    /*out*/ QString &countryName,
+                    bool &callWorkedBefore,
+                    bool &countryWorkedBefore)
+{
+  if (call.length() > 0)
+    {
+      QString currentMode = "JT9"; // JT65 == JT9 in ADIF::match()
+      QString currentBand = "";  // match any band
+      callWorkedBefore = _log.match(call,currentBand,currentMode);
+      countryName = _countries.find(call);
+      if (countryName.length() > 0)  //  country was found
+        countryWorkedBefore = _worked.getHasWorked(countryName);
+      else
+        {
+          countryName = "where?"; //error: prefix not found
+          countryWorkedBefore = false;
+        }
+    }
+  //qDebug() << "Logbook:" << call << ":" << countryName << "Cty B4:" << countryWorkedBefore << "call B4:" << callWorkedBefore;
+}
+
+void LogBook::addAsWorked(const QString call, const QString band, const QString mode, const QString date)
+{
+  //qDebug() << "adding " << call << " as worked";
+  _log.add(call,band,mode,date);
+  QString countryName = _countries.find(call);
+  if (countryName.length() > 0)
+    _worked.setAsWorked(countryName);
+}
+
+
+
diff --git a/logbook/logbook.h b/logbook/logbook.h
new file mode 100644
index 0000000..38ea9d1
--- /dev/null
+++ b/logbook/logbook.h
@@ -0,0 +1,39 @@
+/*
+ * From an ADIF file and cty.dat, get a call's DXCC entity and its worked before status
+ * VK3ACF July 2013
+ */
+
+#ifndef LOGBOOK_H
+#define LOGBOOK_H
+
+
+#include <QString>
+#include <QFont>
+
+#include "countrydat.h"
+#include "countriesworked.h"
+#include "adif.h"
+
+class QDir;
+
+class LogBook
+{
+public:
+    void init();
+    void match(/*in*/ const QString call,
+              /*out*/ QString &countryName,
+                      bool &callWorkedBefore,
+                      bool &countryWorkedBefore);
+    void addAsWorked(const QString call, const QString band, const QString mode, const QString date);
+
+private:
+   CountryDat _countries;
+   CountriesWorked _worked;
+   ADIF _log;
+
+   void _setAlreadyWorkedFromLog();
+
+};
+
+#endif // LOGBOOK_H
+
diff --git a/logqso.cpp b/logqso.cpp
index f5690a1..1d5c51c 100644
--- a/logqso.cpp
+++ b/logqso.cpp
@@ -1,174 +1,149 @@
-#include "logqso.h"
-#include "ui_logqso.h"
-#include <QString>
-#include <QDebug>
-
-
-LogQSO::LogQSO(QWidget *parent) :
-  QDialog(parent),
-  ui(new Ui::LogQSO)
-{
-  ui->setupUi(this);
-}
-
-LogQSO::~LogQSO()
-{
-  delete ui;
-}
-
-void LogQSO::initLogQSO(QString hisCall, QString hisGrid, QString mode,
-                        QString rptSent, QString rptRcvd, QDateTime dateTime,
-                        double dialFreq, QString myCall, QString myGrid,
-                        bool noSuffix, bool toRTTY, bool dBtoComments)
-{
-  ui->call->setText(hisCall);
-  ui->grid->setText(hisGrid);
-  ui->txPower->setText("");
-  ui->comments->setText("");
-  if(m_saveTxPower) ui->txPower->setText(m_txPower);
-  if(m_saveComments) ui->comments->setText(m_comments);
-  if(dBtoComments) {
-    QString t=mode;
-    if(rptSent!="") t+="  Sent: " + rptSent;
-    if(rptRcvd!="") t+="  Rcvd: " + rptRcvd;
-    ui->comments->setText(t);
-  }
-  if(noSuffix and mode.mid(0,3)=="JT9") mode="JT9";
-  if(toRTTY and mode.mid(0,3)=="JT9") mode="RTTY";
-  ui->mode->setText(mode);
-  ui->sent->setText(rptSent);
-  ui->rcvd->setText(rptRcvd);
-  m_dateTime=dateTime;
-  QString date=dateTime.toString("yyyy-MM-dd");
-  ui->date->setText(date);
-  QString time=dateTime.toString("hhmm");
-  ui->time->setText(time);
-  m_dialFreq=dialFreq;
-  m_myCall=myCall;
-  m_myGrid=myGrid;
-  QString band="";
-  if(dialFreq>0.135 and dialFreq<0.139) band="2200m";
-  if(dialFreq>0.45 and dialFreq<0.55) band="630m";
-  if(dialFreq>1.8 and dialFreq<2.0) band="160m";
-  if(dialFreq>3.5 and dialFreq<4.0) band="80m";
-  if(dialFreq>5.1 and dialFreq<5.45) band="60m";
-  if(dialFreq>7.0 and dialFreq<7.3) band="40m";
-  if(dialFreq>10.0 and dialFreq<10.15) band="30m";
-  if(dialFreq>14.0 and dialFreq<14.35) band="20m";
-  if(dialFreq>18.068 and dialFreq<18.168) band="17m";
-  if(dialFreq>21.0 and dialFreq<21.45) band="15m";
-  if(dialFreq>24.890 and dialFreq<24.990) band="12m";
-  if(dialFreq>28.0 and dialFreq<29.7) band="10m";
-  if(dialFreq>50.0 and dialFreq<54.0) band="6m";
-  if(dialFreq>70.0 and dialFreq<71.0) band="4m";
-  if(dialFreq>144.0 and dialFreq<148.0) band="2m";
-  if(dialFreq>222.0 and dialFreq<225.0) band="1.25m";
-  if(dialFreq>420.0 and dialFreq<450.0) band="70cm";
-  if(dialFreq>902.0 and dialFreq<928.0) band="33cm";
-  if(dialFreq>1240.0 and dialFreq<1300.0) band="23cm";
-  if(dialFreq>2300.0 and dialFreq<2450.0) band="13cm";
-  if(dialFreq>3300.0 and dialFreq<3500.0) band="9cm";
-  if(dialFreq>5650.0 and dialFreq<5925.0) band="6cm";
-  if(dialFreq>10000.0 and dialFreq<10500.0) band="3cm";
-  if(dialFreq>24000.0 and dialFreq<24250.0) band="1.25cm";
-  if(dialFreq>47000.0 and dialFreq<47200.0) band="6mm";
-  if(dialFreq>75500.0 and dialFreq<81000.0) band="4mm";
-  ui->band->setText(band);
-  ui->cbTxPower->setChecked(m_saveTxPower);
-  ui->cbComments->setChecked(m_saveComments);
-}
-
-void LogQSO::accept()
-{
-  QString hisCall,hisGrid,mode,rptSent,rptRcvd,date,time,band;
-  QString comments,name;
-
-  hisCall=ui->call->text();
-  hisGrid=ui->grid->text();
-  mode=ui->mode->text();
-  rptSent=ui->sent->text();
-  rptRcvd=ui->rcvd->text();
-  date=ui->date->text();
-  date=date.mid(0,4) + date.mid(5,2) + date.mid(8,2);
-  time=ui->time->text();
-  band=ui->band->text();
-  name=ui->name->text();
-  m_txPower=ui->txPower->text();
-  comments=ui->comments->text();
-  m_comments=comments;
-  QString strDialFreq(QString::number(m_dialFreq,'f',6));
-
-//Log this QSO to file "wsjtx_log.adi"
-  QFile f2("wsjtx_log.adi");
-  if(!f2.open(QIODevice::Text | QIODevice::Append)) {
-    QMessageBox m;
-    m.setText("Cannot open file \"wsjtx_log.adi\".");
-    m.exec();
-  } else {
-    QTextStream out(&f2);
-    if(f2.size()==0) out << "WSJT-X ADIF Export<eoh>" << endl;
-
-    QString t;
-    t="<call:" + QString::number(hisCall.length()) + ">" + hisCall;
-    t+=" <gridsquare:" + QString::number(hisGrid.length()) + ">" + hisGrid;
-    t+=" <mode:" + QString::number(mode.length()) + ">" + mode;
-    t+=" <rst_sent:" + QString::number(rptSent.length()) + ">" + rptSent;
-    t+=" <rst_rcvd:" + QString::number(rptRcvd.length()) + ">" + rptRcvd;
-    t+=" <qso_date:8>" + date;
-    t+=" <time_on:4>" + time;
-    t+=" <band:" + QString::number(band.length()) + ">" + band;
-    t+=" <freq:" + QString::number(strDialFreq.length()) + ">" + strDialFreq;
-    t+=" <station_callsign:" + QString::number(m_myCall.length()) + ">" +
-        m_myCall;
-    t+=" <my_gridsquare:" + QString::number(m_myGrid.length()) + ">" +
-        m_myGrid;
-    if(m_txPower!="") t+= " <tx_pwr:" + QString::number(m_txPower.length()) +
-        ">" + m_txPower;
-    if(comments!="") t+=" <comment:" + QString::number(comments.length()) +
-        ">" + comments;
-    if(name!="") t+=" <name:" + QString::number(name.length()) +
-        ">" + name;
-    t+=" <eor>";
-    out << t << endl;
-    f2.close();
-  }
-
-//Log this QSO to file "wsjtx.log"
-  QFile f("wsjtx.log");
-  if(!f.open(QIODevice::Text | QIODevice::Append)) {
-    QMessageBox m;
-    m.setText("Cannot open file \"wsjtx.log\".");
-    m.exec();
-  } else {
-    QString logEntry=m_dateTime.date().toString("yyyy-MMM-dd,") +
-           m_dateTime.time().toString("hh:mm,") + hisCall + "," +
-           hisGrid + "," + strDialFreq + "," + mode +
-               "," + rptSent + "," + rptRcvd;
-       if(m_txPower!="") logEntry += "," + m_txPower;
-       if(comments!="") logEntry += "," + comments;
-       if(name!="") logEntry += "," + name;
-    QTextStream out(&f);
-    out << logEntry << endl;
-    f.close();
-  }
-
-//Clean up and finish logging
-  emit(acceptQSO(true));
-  QDialog::accept();
-}
-
-void LogQSO::reject()
-{
-  emit(acceptQSO(false));
-  QDialog::reject();
-}
-
-void LogQSO::on_cbTxPower_toggled(bool checked)
-{
-  m_saveTxPower=checked;
-}
-
-void LogQSO::on_cbComments_toggled(bool checked)
-{
-  m_saveComments=checked;
-}
+#include "logqso.h"
+
+#include <QString>
+#include <QSettings>
+#include <QStandardPaths>
+#include <QDir>
+#include <QDebug>
+
+#include "logbook/adif.h"
+
+#include "ui_logqso.h"
+
+#include "moc_logqso.cpp"
+
+LogQSO::LogQSO(QString const& programTitle, QSettings * settings, QWidget *parent)
+  : QDialog(parent)
+  , ui(new Ui::LogQSO)
+  , m_settings (settings)
+{
+  ui->setupUi(this);
+  setWindowTitle(programTitle + " - Log QSO");
+  loadSettings ();
+}
+
+LogQSO::~LogQSO ()
+{
+}
+
+void LogQSO::loadSettings ()
+{
+  m_settings->beginGroup ("LogQSO");
+  restoreGeometry (m_settings->value ("geometry", saveGeometry ()).toByteArray ());
+  ui->cbTxPower->setChecked (m_settings->value ("SaveTxPower", false).toBool ());
+  ui->cbComments->setChecked (m_settings->value ("SaveComments", false).toBool ());
+  m_txPower = m_settings->value ("TxPower", "").toString ();
+  m_comments = m_settings->value ("LogComments", "").toString();
+  m_settings->endGroup ();
+}
+
+void LogQSO::storeSettings () const
+{
+  m_settings->beginGroup ("LogQSO");
+  m_settings->setValue ("geometry", saveGeometry ());
+  m_settings->setValue ("SaveTxPower", ui->cbTxPower->isChecked ());
+  m_settings->setValue ("SaveComments", ui->cbComments->isChecked ());
+  m_settings->setValue ("TxPower", m_txPower);
+  m_settings->setValue ("LogComments", m_comments);
+  m_settings->endGroup ();
+}
+
+void LogQSO::initLogQSO(QString hisCall, QString hisGrid, QString mode,
+                        QString rptSent, QString rptRcvd, QDateTime dateTime,
+                        Radio::Frequency dialFreq, QString myCall, QString myGrid,
+                        bool noSuffix, bool toRTTY, bool dBtoComments)
+{
+  ui->call->setText(hisCall);
+  ui->grid->setText(hisGrid);
+  ui->name->setText("");
+  ui->txPower->setText("");
+  ui->comments->setText("");
+  if (ui->cbTxPower->isChecked ()) ui->txPower->setText(m_txPower);
+  if (ui->cbComments->isChecked ()) ui->comments->setText(m_comments);
+  if(dBtoComments) {
+    QString t=mode;
+    if(rptSent!="") t+="  Sent: " + rptSent;
+    if(rptRcvd!="") t+="  Rcvd: " + rptRcvd;
+    ui->comments->setText(t);
+  }
+  if(noSuffix and mode.mid(0,3)=="JT9") mode="JT9";
+  if(toRTTY and mode.mid(0,3)=="JT9") mode="RTTY";
+  ui->mode->setText(mode);
+  ui->sent->setText(rptSent);
+  ui->rcvd->setText(rptRcvd);
+  m_dateTime=dateTime;
+  QString date=dateTime.toString("yyyy-MM-dd");
+  ui->date->setText(date);
+  QString time=dateTime.toString("hhmm");
+  ui->time->setText(time);
+  m_dialFreq=dialFreq;
+  m_myCall=myCall;
+  m_myGrid=myGrid;
+  QString band= ADIF::bandFromFrequency(dialFreq / 1.e6);
+  ui->band->setText(band);
+
+  show ();
+}
+
+void LogQSO::accept()
+{
+  QString hisCall,hisGrid,mode,rptSent,rptRcvd,date,time,band;
+  QString comments,name;
+
+  hisCall=ui->call->text();
+  hisGrid=ui->grid->text();
+  mode=ui->mode->text();
+  rptSent=ui->sent->text();
+  rptRcvd=ui->rcvd->text();
+  date=ui->date->text();
+  date=date.mid(0,4) + date.mid(5,2) + date.mid(8,2);
+  time=ui->time->text();
+  band=ui->band->text();
+  name=ui->name->text();
+  m_txPower=ui->txPower->text();
+  comments=ui->comments->text();
+  m_comments=comments;
+  QString strDialFreq(QString::number(m_dialFreq / 1.e6,'f',6));
+
+  //Log this QSO to ADIF file "wsjtx_log.adi"
+  QString filename = "wsjtx_log.adi";  // TODO allow user to set
+  ADIF adifile;
+  auto adifilePath = QDir {QStandardPaths::writableLocation (QStandardPaths::DataLocation)}.absoluteFilePath ("wsjtx_log.adi");
+  adifile.init(adifilePath);
+  if (!adifile.addQSOToFile(hisCall,hisGrid,mode,rptSent,rptRcvd,date,time,band,comments,name,strDialFreq,m_myCall,m_myGrid,m_txPower))
+  {
+      QMessageBox m;
+      m.setText("Cannot open file \"" + adifilePath + "\".");
+      m.exec();
+  }
+
+//Log this QSO to file "wsjtx.log"
+  static QFile f {QDir {QStandardPaths::writableLocation (QStandardPaths::DataLocation)}.absoluteFilePath ("wsjtx.log")};
+  if(!f.open(QIODevice::Text | QIODevice::Append)) {
+    QMessageBox m;
+    m.setText("Cannot open file \"" + f.fileName () + "\" for append:" + f.errorString ());
+    m.exec();
+  } else {
+    QString logEntry=m_dateTime.date().toString("yyyy-MMM-dd,") +
+      m_dateTime.time().toString("hh:mm,") + hisCall + "," +
+      hisGrid + "," + strDialFreq + "," + mode +
+      "," + rptSent + "," + rptRcvd + "," + m_txPower +
+      "," + comments; + "," + name;
+    QTextStream out(&f);
+    out << logEntry << endl;
+    f.close();
+  }
+
+//Clean up and finish logging
+  Q_EMIT acceptQSO (m_dateTime, hisCall, hisGrid, m_dialFreq, mode, rptSent, rptRcvd, m_txPower, comments, name);
+  QDialog::accept();
+}
+
+// closeEvent is only called from the system menu close widget for a
+// modeless dialog so we use the hideEvent override to store the
+// window settings
+void LogQSO::hideEvent (QHideEvent * e)
+{
+  storeSettings ();
+  QDialog::hideEvent (e);
+}
diff --git a/logqso.h b/logqso.h
index 06b2edf..fb1609a 100644
--- a/logqso.h
+++ b/logqso.h
@@ -1,53 +1,60 @@
-#ifndef LogQSO_H
-#define LogQSO_H
-
-#ifdef QT5
-#include <QtWidgets>
-#else
-#include <QtGui>
-#endif
-
-namespace Ui {
-class LogQSO;
-}
-
-class LogQSO : public QDialog
-{
-  Q_OBJECT
-
-public:
-  explicit LogQSO(QWidget *parent = 0);
-  ~LogQSO();
-  void initLogQSO(QString hisCall, QString hisGrid, QString mode,
-                  QString rptSent, QString rptRcvd, QDateTime dateTime,
-                  double dialFreq, QString myCall, QString myGrid,
-                  bool noSuffix, bool toRTTY, bool dBtoComments);
-
-  double m_dialFreq;
-
-  bool m_saveTxPower;
-  bool m_saveComments;
-
-  QString m_myCall;
-  QString m_myGrid;
-  QString m_txPower;
-  QString m_comments;
-
-  QDateTime m_dateTime;
-
-public slots:
-  void accept();
-  void reject();
-
-signals:
-  void acceptQSO(bool accepted);
-
-private slots:
-  void on_cbTxPower_toggled(bool checked);
-  void on_cbComments_toggled(bool checked);
-
-private:
-  Ui::LogQSO *ui;
-};
-
-#endif // LogQSO_H
+// -*- Mode: C++ -*-
+#ifndef LogQSO_H
+#define LogQSO_H
+
+#ifdef QT5
+#include <QtWidgets>
+#else
+#include <QtGui>
+#endif
+
+#include <QScopedPointer>
+
+#include "Radio.hpp"
+
+namespace Ui {
+  class LogQSO;
+}
+
+class QSettings;
+
+class LogQSO : public QDialog
+{
+  Q_OBJECT
+
+public:
+  explicit LogQSO(QString const& programTitle, QSettings *, QWidget *parent = 0);
+  ~LogQSO();
+  void initLogQSO(QString hisCall, QString hisGrid, QString mode,
+                  QString rptSent, QString rptRcvd, QDateTime dateTime,
+                  Radio::Frequency dialFreq, QString myCall, QString myGrid,
+                  bool noSuffix, bool toRTTY, bool dBtoComments);
+
+public slots:
+  void accept();
+
+signals:
+  void acceptQSO (QDateTime const&, QString const& call, QString const& grid
+                  , Radio::Frequency dial_freq, QString const& mode
+                  , QString const& rpt_sent, QString const& rpt_received
+                  , QString const& tx_power, QString const& comments
+                  , QString const& name);
+
+protected:
+  void hideEvent (QHideEvent *);
+
+private:
+  void loadSettings ();
+  void storeSettings () const;
+
+  QScopedPointer<Ui::LogQSO> ui;
+  QSettings * m_settings;
+  QString m_txPower;
+  QString m_comments;
+  Radio::Frequency m_dialFreq;
+  QString m_myCall;
+  QString m_myGrid;
+  QDateTime m_dateTime;
+};
+
+#endif // LogQSO_H
diff --git a/logqso.ui b/logqso.ui
index a9c6fe9..36cb100 100644
--- a/logqso.ui
+++ b/logqso.ui
@@ -16,9 +16,6 @@
     <height>16777215</height>
    </size>
   </property>
-  <property name="windowTitle">
-   <string>Log QSO</string>
-  </property>
   <layout class="QFormLayout" name="formLayout">
    <item row="0" column="0">
     <layout class="QVBoxLayout" name="verticalLayout">
diff --git a/main.cpp b/main.cpp
index add1ab1..6475dd3 100644
--- a/main.cpp
+++ b/main.cpp
@@ -1,60 +1,213 @@
-#ifdef QT5
-#include <QtWidgets>
-#else
-#include <QtGui>
-#endif
+#include <iostream>
+#include <exception>
+#include <stdexcept>
+#include <string>
+
+#include <locale.h>
+
 #include <QApplication>
-#include <portaudio.h>
+#include <QRegularExpression>
+#include <QObject>
+#include <QSettings>
+#include <QLibraryInfo>
+#include <QSysInfo>
+#include <QDir>
+#include <QStandardPaths>
+#include <QStringList>
+#include <QMessageBox>
+#include <QLockFile>
+
+#if QT_VERSION >= 0x050200
+#include <QCommandLineParser>
+#include <QCommandLineOption>
+#endif
+
+#include "revision_utils.hpp"
+
+#include "SettingsGroup.hpp"
+#include "TraceFile.hpp"
 #include "mainwindow.h"
 
-// Multiple instances:
-QSharedMemory mem_jt9;
-QUuid         my_uuid;
-QString       my_key;
 
 int main(int argc, char *argv[])
 {
+  // Multiple instances:
+  QSharedMemory mem_jt9;
+
   QApplication a(argc, argv);
+  try
+    {
+      setlocale (LC_NUMERIC, "C"); // ensure number forms are in
+                                   // consistent format, do this after
+                                   // instantiating QApplication so
+                                   // that GUI has correct l18n
+	      
+      // Override programs executable basename as application name.
+      a.setApplicationName ("WSJT-X");
+      a.setApplicationVersion (version ());
+
+      bool multiple {false};
+
+#if QT_VERSION >= 0x050200
+      QCommandLineParser parser;
+      parser.setApplicationDescription ("\nJT65A & JT9 Weak Signal Communications Program.");
+      auto help_option = parser.addHelpOption ();
+      auto version_option = parser.addVersionOption ();
+
+      // support for multiple instances running from a single installation
+      QCommandLineOption rig_option (QStringList {} << "r" << "rig-name"
+                                     , a.translate ("main", "Where <rig-name> is for multi-instance support.")
+                                     , a.translate ("main", "rig-name"));
+      parser.addOption (rig_option);
+
+      QCommandLineOption test_option (QStringList {} << "test-mode"
+                                      , a.translate ("main", "Writable files in test location.  Use with caution, for testing only."));
+      parser.addOption (test_option);
+
+      if (!parser.parse (a.arguments ()))
+        {
+          QMessageBox::critical (nullptr, a.applicationName (), parser.errorText ());
+          return -1;
+        }
+      else
+        {
+          if (parser.isSet (help_option))
+            {
+              QMessageBox::information (nullptr, a.applicationName (), parser.helpText ());
+              return 0;
+            }
+          else if (parser.isSet (version_option))
+            {
+              QMessageBox::information (nullptr, a.applicationName (), a.applicationVersion ());
+              return 0;
+            }
+        }
+
+      QStandardPaths::setTestModeEnabled (parser.isSet (test_option));
+
+      // support for multiple instances running from a single installation
+      if (parser.isSet (rig_option) || parser.isSet (test_option))
+        {
+          auto temp_name = parser.value (rig_option);
+          if (!temp_name.isEmpty ())
+            {
+              if (temp_name.contains (QRegularExpression {R"([\\/,])"}))
+                {
+                  std::cerr << QObject::tr ("Invalid rig name - \\ & / not allowed").toLocal8Bit ().data () << std::endl;
+                  parser.showHelp (-1);
+                }
+                
+              a.setApplicationName (a.applicationName () + " - " + temp_name);
+            }
+
+          if (parser.isSet (test_option))
+            {
+              a.setApplicationName (a.applicationName () + " - test");
+            }
+
+          multiple = true;
+        }
 
-  QFile f("fonts.txt");
-  if(f.open(QIODevice::ReadOnly)) {
-     QTextStream in(&f);                          //Example:
-     QString fontFamily;                          // helvetica
-     qint32 fontSize,fontWeight;                  // 8,50
-     in >> fontFamily >> fontSize >> fontWeight;
-     f.close();
-     QFont font;
-     font=QFont(fontFamily,fontSize,fontWeight);
-     a.setFont(font);
-  }
-
-  // Create and initialize shared memory segment
-  // Multiple instances: generate shared memory keys with UUID
-  my_uuid = QUuid::createUuid();
-  my_key = my_uuid.toString();
-  mem_jt9.setKey(my_key);
-
-  if(!mem_jt9.attach()) {
-    if (!mem_jt9.create(sizeof(jt9com_))) {
-      QMessageBox::critical( 0, "Error", "Unable to create shared memory segment.");
-      exit(1);
+      // disallow multiple instances with same instance key
+      QLockFile instance_lock {QDir {QStandardPaths::writableLocation (QStandardPaths::TempLocation)}.absoluteFilePath (a.applicationName () + ".lock")};
+      instance_lock.setStaleLockTime (0);
+      auto ok = false;
+      while (!(ok = instance_lock.tryLock ()))
+        {
+          if (QLockFile::LockFailedError == instance_lock.error ())
+            {
+              auto button = QMessageBox::question (nullptr
+                                                   , QApplication::applicationName ()
+                                                   , QObject::tr ("Another instance may be running, try to remove stale lock file?")
+                                                   , QMessageBox::Yes | QMessageBox::Retry | QMessageBox::No
+                                                   , QMessageBox::Yes);
+              switch (button)
+                {
+                case QMessageBox::Yes:
+                  instance_lock.removeStaleLockFile ();
+                  break;
+
+                case QMessageBox::Retry:
+                  break;
+
+                default:
+                  throw std::runtime_error {"Multiple instances must have unique rig names"};
+                }
+            }
+        }
+#endif
+
+      auto config_directory = QStandardPaths::writableLocation (QStandardPaths::ConfigLocation);
+      QDir config_path {config_directory}; // will be "." if config_directory is empty
+      if (!config_path.mkpath ("."))
+        {
+          throw std::runtime_error {"Cannot find a usable configuration path \"" + config_path.path ().toStdString () + '"'};
+        }
+
+      auto settings_file = config_path.absoluteFilePath (a.applicationName () + ".ini");
+      QSettings settings(settings_file, QSettings::IniFormat);
+      if (!settings.isWritable ())
+        {
+          throw std::runtime_error {QString {"Cannot access \"%1\" for writing"}.arg (settings_file).toStdString ()};
+        }
+
+#if WSJT_QDEBUG_TO_FILE
+      // // open a trace file
+      TraceFile trace_file {QDir {QStandardPaths::writableLocation (QStandardPaths::TempLocation)}.absoluteFilePath (a.applicationName () + "_trace.log")};
+
+      // announce to trace file
+      qDebug () << program_title (revision ()) + " - Program startup";
+#endif
+
+      // Create and initialize shared memory segment
+      // Multiple instances: use rig_name as shared memory key
+      mem_jt9.setKey(a.applicationName ());
+
+      if(!mem_jt9.attach()) {
+        if (!mem_jt9.create(sizeof(jt9com_))) {
+          QMessageBox::critical (nullptr, "Error", "Unable to create shared memory segment.");
+          exit(1);
+        }
+      }
+      char *to = (char*)mem_jt9.data();
+      int size=sizeof(jt9com_);
+      if(jt9com_.newdat==0) {
+      }
+      memset(to,0,size);         //Zero all decoding params in shared memory
+
+      unsigned downSampleFactor;
+      {
+        SettingsGroup {&settings, "Tune"};
+
+        // deal with Windows Vista and earlier input audio rate
+        // converter problems
+        downSampleFactor = settings.value ("Audio/DisableInputResampling",
+#if defined (Q_OS_WIN)
+                                           // default to true for
+                                           // Windows Vista and older
+                                           QSysInfo::WV_VISTA >= QSysInfo::WindowsVersion ? true : false
+#else
+                                           false
+#endif
+                                           ).toBool () ? 1u : 4u;
+      }
+
+      MainWindow w(multiple, &settings, &mem_jt9, downSampleFactor);
+      w.show();
+
+      QObject::connect (&a, SIGNAL (lastWindowClosed()), &a, SLOT (quit()));
+      return a.exec();
+    }
+  catch (std::exception const& e)
+    {
+      QMessageBox::critical (nullptr, a.applicationName (), e.what ());
+      std::cerr << "Error: " << e.what () << '\n';
+    }
+  catch (...)
+    {
+      QMessageBox::critical (nullptr, a.applicationName (), QObject::tr ("Unexpected error"));
+      std::cerr << "Unexpected error\n";
+      throw;			// hoping the runtime might tell us more about the exception
     }
-  }
-  char *to = (char*)mem_jt9.data();
-  int size=sizeof(jt9com_);
-  if(jt9com_.newdat==0) {
-  }
-  memset(to,0,size);         //Zero all decoding params in shared memory
-
-  //Initialize Portaudio
-  PaError paerr=Pa_Initialize();
-  if(paerr!=paNoError) {
-    QMessageBox::critical( 0, "Error", "Unable to initialize PortAudio.");
-    exit(1);
-  }
-
-// Multiple instances:  Call MainWindow() with the UUID key
-  MainWindow w(&mem_jt9, &my_key);
-  w.show();
-  return a.exec();
+  return -1;
 }
diff --git a/mainwindow.cpp b/mainwindow.cpp
index 7b50ec8..e1f6a70 100644
--- a/mainwindow.cpp
+++ b/mainwindow.cpp
@@ -1,60 +1,233 @@
-//------------------------------------------------------------- MainWindow
+//-------------------------------------------------------- MainWindow
+
 #include "mainwindow.h"
-#include "ui_mainwindow.h"
-#include "devsetup.h"
+
+#include <cinttypes>
+#include <limits>
+
+#include <QThread>
+#include <QLineEdit>
+#include <QRegExpValidator>
+#include <QRegExp>
+#include <QDesktopServices>
+#include <QUrl>
+#include <QStandardPaths>
+#include <QDir>
+#include <QDebug>
+#include <QtConcurrent/QtConcurrentRun>
+#include <QProgressDialog>
+#include <QHostInfo>
+
+#include "revision_utils.hpp"
+#include "soundout.h"
 #include "plotter.h"
 #include "about.h"
+#include "astro.h"
 #include "widegraph.h"
 #include "sleep.h"
 #include "getfile.h"
-#include <portaudio.h>
 #include "logqso.h"
+#include "Radio.hpp"
+#include "Bands.hpp"
+#include "TransceiverFactory.hpp"
+#include "FrequencyList.hpp"
+#include "StationList.hpp"
+#include "LiveFrequencyValidator.hpp"
+#include "FrequencyItemDelegate.hpp"
+#include "MessageClient.hpp"
 
-#ifdef QT5
-#include <QtConcurrent/QtConcurrentMap>
-#include <QtConcurrent/QtConcurrentRun>
-#endif
+#include "ui_mainwindow.h"
+#include "moc_mainwindow.cpp"
+
+int volatile itone[NUM_JT65_SYMBOLS];	//Audio tones for all Tx symbols
+int volatile icw[NUM_CW_SYMBOLS];	//Dits for CW ID
 
-int itone[126];                       //Audio tones for all Tx symbols
-int icw[250];                         //Dits for CW ID
 int outBufSize;
 int rc;
-qint32  g_COMportOpen;
 qint32  g_iptt;
-static int nc1=1;
 wchar_t buffer[256];
-bool btxok;                           //True if OK to transmit
-bool btxMute;
-double outputLatency;                 //Latency in seconds
-double dFreq[]={0.13613,0.4742,1.838,3.576,5.357,7.076,10.138,14.076,
-           18.102,21.076,24.917,28.076,50.276,70.091,144.489,432.178};
-
-WideGraph* g_pWideGraph = NULL;
-LogQSO* logDlg = NULL;
-Rig* rig = NULL;
-QTextEdit* pShortcuts;
-QTcpSocket* socket = new QTcpSocket(0);
-
-QString rev="$Rev: 3496 $";
-QString Program_Title_Version="  WSJT-X   v1.1, r" + rev.mid(6,4) +
-                              "    by K1JT";
-
-//-------------------------------------------------- MainWindow constructor
-// Multiple instances: new arg *thekey
-MainWindow::MainWindow(QSharedMemory *shdmem, QString *thekey, QWidget *parent) :
+
+
+namespace
+{
+  Radio::Frequency constexpr default_frequency {14076000};
+  QRegExp message_alphabet {"[- A-Za-z0-9+./?]*"};
+
+  bool message_is_73 (int type, QStringList const& msg_parts)
+  {
+    return type >= 0
+      && ((type < 6 && msg_parts.contains ("73"))
+          || (type == 6 && !msg_parts.filter ("73").isEmpty ()));
+  }
+}
+
+class BandAndFrequencyItemDelegate final
+  : public QStyledItemDelegate
+{
+public:
+  explicit BandAndFrequencyItemDelegate (Bands const * bands, QObject * parent = nullptr)
+    : QStyledItemDelegate {parent}
+    , bands_ {bands}
+  {
+  }
+
+  QString displayText (QVariant const& v, QLocale const&) const override
+  {
+    return Radio::pretty_frequency_MHz_string (Radio::frequency (v, 6))
+      + QChar::Nbsp
+      + '(' + (bands_->data (bands_->find (Radio::frequency (v, 6)))).toString () + ')';
+  }
+
+private:
+  Bands const * bands_;
+};
+
+//--------------------------------------------------- MainWindow constructor
+MainWindow::MainWindow(bool multiple, QSettings * settings, QSharedMemory *shdmem,
+                       unsigned downSampleFactor, QWidget *parent) :
   QMainWindow(parent),
-  ui(new Ui::MainWindow)
+  m_dataDir {QStandardPaths::writableLocation (QStandardPaths::DataLocation)},
+  m_revision {revision ()},
+  m_multiple {multiple},
+  m_settings (settings),
+  ui(new Ui::MainWindow),
+  m_config (settings, this),
+  m_wideGraph (new WideGraph (settings)),
+  m_logDlg (new LogQSO (program_title (), settings, this)),
+  m_dialFreq {std::numeric_limits<Radio::Frequency>::max ()},
+  m_detector (RX_SAMPLE_RATE, NTMAX / 2, 6912 / 2, downSampleFactor),
+  m_modulator (TX_SAMPLE_RATE, NTMAX / 2),
+  m_audioThread {new QThread},
+  m_diskData {false},
+  m_sentFirst73 {false},
+  m_currentMessageType {-1},
+  m_lastMessageType {-1},
+  m_appDir {QApplication::applicationDirPath ()},
+  mem_jt9 {shdmem},
+  m_msAudioOutputBuffered (0u),
+  m_framesAudioInputBuffered (RX_SAMPLE_RATE / 10),
+  m_downSampleFactor (downSampleFactor),
+  m_audioThreadPriority (QThread::HighPriority),
+  m_bandEdited {false},
+  m_splitMode {false},
+  m_monitoring {false},
+  m_transmitting {false},
+  m_tune {false},
+  m_lastMonitoredFrequency {default_frequency},
+  m_toneSpacing {0.},
+  m_firstDecode {0},
+  m_optimizingProgress {"Optimizing decoder FFTs for your CPU.\n"
+      "Please be patient,\n"
+      "this may take a few minutes", QString {}, 0, 1, this},
+  m_messageClient {new MessageClient {QApplication::applicationName (), m_config.udp_server_name (), m_config.udp_server_port (), this}},
+  psk_Reporter {new PSK_Reporter {m_messageClient, this}}
 {
   ui->setupUi(this);
-  on_EraseButton_clicked();
-  QActionGroup* paletteGroup = new QActionGroup(this);
-  ui->actionCuteSDR->setActionGroup(paletteGroup);
-  ui->actionLinrad->setActionGroup(paletteGroup);
-  ui->actionAFMHot->setActionGroup(paletteGroup);
-  ui->actionBlue->setActionGroup(paletteGroup);
+
+  m_optimizingProgress.setWindowModality (Qt::WindowModal);
+  m_optimizingProgress.setAutoReset (false);
+  m_optimizingProgress.setMinimumDuration (15000); // only show after 15s delay
+
+  // Closedown.
+  connect (ui->actionExit, &QAction::triggered, this, &QMainWindow::close);
+
+  // parts of the rig error message box that are fixed
+  m_rigErrorMessageBox.setInformativeText (tr ("Do you want to reconfigure the radio interface?"));
+  m_rigErrorMessageBox.setStandardButtons (QMessageBox::Cancel | QMessageBox::Ok | QMessageBox::Retry);
+  m_rigErrorMessageBox.setDefaultButton (QMessageBox::Ok);
+  m_rigErrorMessageBox.setIcon (QMessageBox::Critical);
+
+  // start audio thread and hook up slots & signals for shutdown management
+  // these objects need to be in the audio thread so that invoking
+  // their slots is done in a thread safe way
+  m_soundOutput.moveToThread (m_audioThread);
+  m_modulator.moveToThread (m_audioThread);
+  m_soundInput.moveToThread (m_audioThread);
+  m_detector.moveToThread (m_audioThread);
+
+  connect (this, &MainWindow::finished, m_audioThread, &QThread::quit); // quit thread event loop
+  connect (m_audioThread, &QThread::finished, m_audioThread, &QThread::deleteLater); // disposal
+
+  // hook up sound output stream slots & signals
+  connect (this, &MainWindow::initializeAudioOutputStream, &m_soundOutput, &SoundOutput::setFormat);
+  connect (&m_soundOutput, &SoundOutput::error, this, &MainWindow::showSoundOutError);
+  // connect (&m_soundOutput, &SoundOutput::status, this, &MainWindow::showStatusMessage);
+  connect (this, &MainWindow::outAttenuationChanged, &m_soundOutput, &SoundOutput::setAttenuation);
+
+  // hook up Modulator slots
+  connect (this, &MainWindow::transmitFrequency, &m_modulator, &Modulator::setFrequency);
+  connect (this, &MainWindow::endTransmitMessage, &m_modulator, &Modulator::stop);
+  connect (this, &MainWindow::tune, &m_modulator, &Modulator::tune);
+  connect (this, &MainWindow::sendMessage, &m_modulator, &Modulator::start);
+
+  // hook up the audio input stream
+  connect (this, &MainWindow::startAudioInputStream, &m_soundInput, &SoundInput::start);
+  connect (this, &MainWindow::suspendAudioInputStream, &m_soundInput, &SoundInput::suspend);
+  connect (this, &MainWindow::resumeAudioInputStream, &m_soundInput, &SoundInput::resume);
+  connect (this, &MainWindow::finished, &m_soundInput, &SoundInput::stop);
+
+  connect (this, &MainWindow::finished, this, &MainWindow::close);
+
+  connect(&m_soundInput, &SoundInput::error, this, &MainWindow::showSoundInError);
+  // connect(&m_soundInput, &SoundInput::status, this, &MainWindow::showStatusMessage);
+
+  // hook up the detector
+  connect(&m_detector, &Detector::framesWritten, this, &MainWindow::dataSink);
+
+  // setup the waterfall
+  connect(m_wideGraph.data (), SIGNAL(freezeDecode2(int)),this,
+          SLOT(freezeDecode(int)));
+  connect(m_wideGraph.data (), SIGNAL(f11f12(int)),this,
+          SLOT(bumpFqso(int)));
+  connect(m_wideGraph.data (), SIGNAL(setXIT2(int)),this,
+          SLOT(setXIT(int)));
+  //    connect(m_wideGraph.data (), SIGNAL(dialFreqChanged(double)),this,
+  //            SLOT(dialFreqChanged2(double)));
+  connect (this, &MainWindow::finished, m_wideGraph.data (), &WideGraph::close);
+
+
+  // setup the log QSO dialog
+  connect (m_logDlg.data (), &LogQSO::acceptQSO, this, &MainWindow::acceptQSO2);
+  connect (this, &MainWindow::finished, m_logDlg.data (), &LogQSO::close);
+
+  // Network message handlers
+  connect (m_messageClient, &MessageClient::reply, this, &MainWindow::replyToCQ);
+  connect (m_messageClient, &MessageClient::replay, this, &MainWindow::replayDecodes);
+  connect (m_messageClient, &MessageClient::halt_tx, [this] (bool auto_only) {
+      if (m_config.accept_udp_requests ()) {
+        if (auto_only) {
+          if (ui->autoButton->isChecked ()) {
+            ui->autoButton->click ();
+          }
+        } else {
+          ui->stopTxButton->click();
+        }
+      }
+    });
+  connect (m_messageClient, &MessageClient::error, this, &MainWindow::networkError);
+  connect (m_messageClient, &MessageClient::free_text, [this] (QString const& text, bool send) {
+      if (m_config.accept_udp_requests ()) {
+        if (0 == ui->tabWidget->currentIndex ()) {
+          ui->tx5->setCurrentText (text);
+          if (send) {
+            ui->txb5->click ();
+          } else {
+            ui->txrb5->click ();
+          }
+        } else if (1 == ui->tabWidget->currentIndex ()) {
+          ui->freeTextMsg->setCurrentText (text);
+          if (send) {
+            ui->rbFreeText->click ();
+          }
+        }
+      }
+    });
+
+  on_EraseButton_clicked ();
 
   QActionGroup* modeGroup = new QActionGroup(this);
   ui->actionJT9_1->setActionGroup(modeGroup);
+  ui->actionJT9W_1->setActionGroup(modeGroup);
   ui->actionJT65->setActionGroup(modeGroup);
   ui->actionJT9_JT65->setActionGroup(modeGroup);
 
@@ -82,77 +255,108 @@ MainWindow::MainWindow(QSharedMemory *shdmem, QString *thekey, QWidget *parent)
   connect(ui->decodedTextBrowser,SIGNAL(selectCallsign(bool,bool)),this,
           SLOT(doubleClickOnCall2(bool,bool)));
 
-  setWindowTitle(Program_Title_Version);
-  connect(&soundInThread, SIGNAL(readyForFFT(int)),
-             this, SLOT(dataSink(int)));
-  connect(&soundInThread, SIGNAL(error(QString)), this,
-          SLOT(showSoundInError(QString)));
-  connect(&soundInThread, SIGNAL(status(QString)), this,
-          SLOT(showStatusMessage(QString)));
+  // initialise decoded text font and hook up change signal
+  setDecodedTextFont (m_config.decoded_text_font ());
+  connect (&m_config, &Configuration::decoded_text_font_changed, [this] (QFont const& font) {
+      setDecodedTextFont (font);
+    });
+
+  setWindowTitle (program_title ());
   createStatusBar();
 
   connect(&proc_jt9, SIGNAL(readyReadStandardOutput()),
-                    this, SLOT(readFromStdout()));
+          this, SLOT(readFromStdout()));
 
   connect(&proc_jt9, SIGNAL(error(QProcess::ProcessError)),
-          this, SLOT(jt9_error()));
+          this, SLOT(jt9_error(QProcess::ProcessError)));
 
   connect(&proc_jt9, SIGNAL(readyReadStandardError()),
           this, SLOT(readFromStderr()));
 
-  ui->bandComboBox->setEditable(true);
-  ui->bandComboBox->lineEdit()->setReadOnly(true);
-  ui->bandComboBox->lineEdit()->setAlignment(Qt::AlignCenter);
-  for(int i = 0; i < ui->bandComboBox->count(); i++)
-    ui->bandComboBox->setItemData(i, Qt::AlignCenter, Qt::TextAlignmentRole);
+  // Hook up working frequencies.
+  ui->bandComboBox->setModel (m_config.frequencies ());
+  ui->bandComboBox->setModelColumn (1); // MHz
+
+  // Add delegate to show bands alongside frequencies in combo box
+  // popup list.
+  ui->bandComboBox->view ()->setItemDelegateForColumn (1, new BandAndFrequencyItemDelegate {m_config.bands (), this});
+
+  // combo box drop downs are limited to the drop down selector width,
+  // this almost random increase improves the situation
+  ui->bandComboBox->view ()->setMinimumWidth (ui->bandComboBox->view ()->sizeHintForColumn (1) + 40);
+
+  // Enable live band combo box entry validation and action.
+  auto band_validator = new LiveFrequencyValidator {ui->bandComboBox
+                                                    , m_config.bands ()
+                                                    , m_config.frequencies ()
+                                                    , this};
+  ui->bandComboBox->setValidator (band_validator);
+
+  // Hook up signals.
+  connect (band_validator, &LiveFrequencyValidator::valid, this, &MainWindow::band_changed);
+  connect (ui->bandComboBox->lineEdit (), &QLineEdit::textEdited, [this] (QString const&) {m_bandEdited = true;});
+
+  // hook up configuration signals
+  connect (&m_config, &Configuration::transceiver_update, this, &MainWindow::handle_transceiver_update);
+  connect (&m_config, &Configuration::transceiver_failure, this, &MainWindow::handle_transceiver_failure);
+  connect (&m_config, &Configuration::udp_server_changed, m_messageClient, &MessageClient::set_server);
+  connect (&m_config, &Configuration::udp_server_port_changed, m_messageClient, &MessageClient::set_server_port);
+
+  // set up message text validators
+  ui->tx1->setValidator (new QRegExpValidator {message_alphabet, this});
+  ui->tx2->setValidator (new QRegExpValidator {message_alphabet, this});
+  ui->tx3->setValidator (new QRegExpValidator {message_alphabet, this});
+  ui->tx4->setValidator (new QRegExpValidator {message_alphabet, this});
+  ui->tx5->setValidator (new QRegExpValidator {message_alphabet, this});
+  ui->tx6->setValidator (new QRegExpValidator {message_alphabet, this});
+  ui->freeTextMsg->setValidator (new QRegExpValidator {message_alphabet, this});
+
+  // Free text macros model to widget hook up.
+  ui->tx5->setModel (m_config.macros ());
+  connect (ui->tx5->lineEdit ()
+           , &QLineEdit::editingFinished
+           , [this] () {on_tx5_currentTextChanged (ui->tx5->lineEdit ()->text ());});
+  ui->freeTextMsg->setModel (m_config.macros ());
+  connect (ui->freeTextMsg->lineEdit ()
+           , &QLineEdit::editingFinished
+           , [this] () {on_freeTextMsg_currentTextChanged (ui->freeTextMsg->lineEdit ()->text ());});
+
+  auto font = ui->readFreq->font();
+  font.setFamily("helvetica");
+  font.setPointSize(9);
+  font.setWeight(75);
+  ui->readFreq->setFont(font);
+
+  connect(&m_guiTimer, &QTimer::timeout, this, &MainWindow::guiUpdate);
+  m_guiTimer.start(100);                            //Don't change the 100 ms!
 
-  ui->tx5->setContextMenuPolicy(Qt::CustomContextMenu);
-  connect(ui->tx5, SIGNAL(customContextMenuRequested(const QPoint&)),
-      this, SLOT(showMacros(const QPoint&)));
-
-  ui->freeTextMsg->setContextMenuPolicy(Qt::CustomContextMenu);
-  connect(ui->freeTextMsg, SIGNAL(customContextMenuRequested(const QPoint&)),
-      this, SLOT(showMacros(const QPoint&)));
-
-  QTimer *guiTimer = new QTimer(this);
-  connect(guiTimer, SIGNAL(timeout()), this, SLOT(guiUpdate()));
-  guiTimer->start(100);                            //Don't change the 100 ms!
   ptt0Timer = new QTimer(this);
   ptt0Timer->setSingleShot(true);
-  connect(ptt0Timer, SIGNAL(timeout()), this, SLOT(stopTx2()));
+  connect(ptt0Timer, &QTimer::timeout, this, &MainWindow::stopTx2);
   ptt1Timer = new QTimer(this);
   ptt1Timer->setSingleShot(true);
-  connect(ptt1Timer, SIGNAL(timeout()), this, SLOT(startTx2()));
+  connect(ptt1Timer, &QTimer::timeout, this, &MainWindow::startTx2);
 
   logQSOTimer = new QTimer(this);
   logQSOTimer->setSingleShot(true);
-  connect(logQSOTimer, SIGNAL(timeout()), this, SLOT(on_logQSOButton_clicked()));
+  connect(logQSOTimer, &QTimer::timeout, this, &MainWindow::on_logQSOButton_clicked);
 
   tuneButtonTimer= new QTimer(this);
   tuneButtonTimer->setSingleShot(true);
-  connect(tuneButtonTimer, SIGNAL(timeout()), this,
-          SLOT(on_stopTxButton_clicked()));
+  connect(tuneButtonTimer, &QTimer::timeout, this, &MainWindow::on_stopTxButton_clicked);
 
   killFileTimer = new QTimer(this);
   killFileTimer->setSingleShot(true);
-  connect(killFileTimer, SIGNAL(timeout()), this, SLOT(killFile()));
+  connect(killFileTimer, &QTimer::timeout, this, &MainWindow::killFile);
 
   m_auto=false;
   m_waterfallAvg = 1;
   m_txFirst=false;
-  btxMute=false;
-  btxok=false;
+  m_btxok=false;
   m_restart=false;
-  m_transmitting=false;
   m_killAll=false;
   m_widebandDecode=false;
   m_ntx=1;
-  m_myCall="";
-  m_myGrid="FN20qi";
-  m_appDir = QApplication::applicationDirPath();
-  m_saveDir="/users/joe/wsjtx/install/save";
-  m_rxFreq=1500;
-  m_txFreq=1500;
   m_setftx=0;
   m_loopall=false;
   m_startAnother=false;
@@ -168,101 +372,109 @@ MainWindow::MainWindow(QSharedMemory *shdmem, QString *thekey, QWidget *parent)
   m_inGain=0;
   m_dataAvailable=false;
   g_iptt=0;
-  g_COMportOpen=0;
   m_secID=0;
-  m_promptToLog=false;
   m_blankLine=false;
-  m_insertBlank=false;
-  m_clearCallGrid=false;
-  m_bMiles=false;
   m_decodedText2=false;
   m_freeText=false;
   m_msErase=0;
-  m_sent73=false;
-  m_watchdogLimit=5;
-  m_tune=false;
+  m_watchdogLimit=7;
   m_repeatMsg=0;
-  m_bRigOpen=false;
   m_secBandChanged=0;
-  m_bMultipleOK=false;
-  m_dontReadFreq=false;
   m_lockTxFreq=false;
+  m_baseCall = Radio::base_callsign (m_config.my_callsign ());
+
   ui->readFreq->setEnabled(false);
-  m_QSOmsg="";
-  m_CATerror=false;
+  m_QSOText.clear();
   decodeBusy(false);
 
   signalMeter = new SignalMeter(ui->meterFrame);
   signalMeter->resize(50, 160);
 
-//  qDebug() << signalMeter->size();
-
   ui->labAz->setStyleSheet("border: 0px;");
   ui->labDist->setStyleSheet("border: 0px;");
 
-  mem_jt9 = shdmem;
-// Multiple instances:
-  mykey_jt9 = thekey;
-  readSettings();		             //Restore user's setup params
-  if(m_dFreq.length()<=1) {      //Use the startup default frequencies
-    m_dFreq.clear();
-    for(int i=0; i<16; i++) {
-      QString t;
-      t.sprintf("%f",dFreq[i]);
-      m_dFreq.append(t);
-    }
-  }
+  readSettings();		         //Restore user's setup params
+
+  // start the audio thread
+  m_audioThread->start (m_audioThreadPriority);
 
 #ifdef WIN32
-  if(!m_bMultipleOK) {
-    while(true) {
-      int iret=killbyname("jt9.exe");
-      if(iret == 603) break;
-      if(iret != 0) msgBox("KillByName return code: " +
-                           QString::number(iret));
+  if (!m_multiple)
+    {
+      while(true)
+        {
+          int iret=killbyname("jt9.exe");
+          if(iret == 603) break;
+          if(iret != 0) msgBox("KillByName return code: " +
+                               QString::number(iret));
+        }
     }
-  }
 #endif
 
-  QFile lockFile(m_appDir + "/.lock");     //Create .lock so jt9 will wait
-  lockFile.open(QIODevice::ReadWrite);
-  //QFile quitFile(m_appDir + "/.lock");
-  //quitFile.remove();
-
-// Multiple instances: make the Qstring key into command line arg
-// Multiple instances: start "jt9 -s <thekey>"
-  QByteArray  ba = mykey_jt9->toLocal8Bit();
-  const char *bc = ba.data();
-  proc_jt9.start(QDir::toNativeSeparators('"' + m_appDir + '"' + "/jt9 -s " + bc));
-
-  m_pbdecoding_style1="QPushButton{background-color: cyan; \
-      border-style: outset; border-width: 1px; border-radius: 5px; \
-      border-color: black; min-width: 5em; padding: 3px;}";
-  m_pbmonitor_style="QPushButton{background-color: #00ff00; \
-      border-style: outset; border-width: 1px; border-radius: 5px; \
-      border-color: black; min-width: 5em; padding: 3px;}";
-  m_pbAutoOn_style="QPushButton{background-color: red; \
-      border-style: outset; border-width: 1px; border-radius: 5px; \
-      border-color: black; min-width: 5em; padding: 3px;}";
-  m_pbTune_style="QPushButton{background-color: red; \
-      border-style: outset; border-width: 1px; border-radius: 5px; \
-      border-color: black; min-width: 5em; padding: 3px;}";
+  auto_tx_label->setText (m_config.quick_call () ? "Tx-Enable Armed" : "Tx-Enable Disarmed");
+
+  {
+    //delete any .quit file that might have been left lying around
+    //since its presence will cause jt9 to exit a soon as we start it
+    //and decodes will hang
+    QFile quitFile {m_config.temp_dir ().absoluteFilePath (".quit")};
+    while (quitFile.exists ())
+      {
+        if (!quitFile.remove ())
+          {
+            msgBox ("Error removing \"" + quitFile.fileName () +
+                    "\" - OK to retry.");
+          }
+      }
+  }
+
+  //Create .lock so jt9 will wait
+  QFile {m_config.temp_dir ().absoluteFilePath (".lock")}.open(QIODevice::ReadWrite);
 
+  QStringList jt9_args {
+    "-s", QApplication::applicationName () // shared memory key,
+                                           // includes rig-name
+#ifdef NDEBUG
+      , "-w", "2"               //FFTW patience - release
+#else
+      , "-w", "1"               //FFTW patience - debug builds for speed
+#endif
+
+      // The number  of threads for  FFTW specified here is  chosen as
+      // three because  that gives  the best  throughput of  the large
+      // FFTs used  in jt9.  The count  is the minimum of  (the number
+      // available CPU threads less one) and three.  This ensures that
+      // there is always at least one free CPU thread to run the other
+      // mode decoder in parallel.
+      , "-m", QString::number (qMin (qMax (QThread::idealThreadCount () - 1, 1), 3)) //FFTW threads
+
+      , "-e", QDir::toNativeSeparators (m_appDir)
+      , "-a", QDir::toNativeSeparators (m_dataDir.absolutePath ())
+      , "-t", QDir::toNativeSeparators (m_config.temp_dir ().absolutePath ())
+      };
+  proc_jt9.start(QDir::toNativeSeparators (m_appDir) + QDir::separator () +
+          "jt9", jt9_args, QIODevice::ReadWrite | QIODevice::Unbuffered);
+
+  QString fname {QDir::toNativeSeparators(m_dataDir.absoluteFilePath ("wsjtx_wisdom.dat"))};
+  QByteArray cfname=fname.toLocal8Bit();
+  fftwf_import_wisdom_from_filename(cfname);
+
+  getpfx();                               //Load the prefix/suffix dictionary
   genStdMsgs(m_rpt);
-  if(m_mode!="JT9" and m_mode!="JT65" and m_mode!="JT9+JT65") m_mode="JT9";
+  m_ntx=6;
+  ui->txrb6->setChecked(true);
+  if(m_mode!="JT9" and m_mode!="JT9W-1" and m_mode!="JT65" and
+     m_mode!="JT9+JT65") m_mode="JT9";
   on_actionWide_Waterfall_triggered();                   //###
-  g_pWideGraph->setRxFreq(m_rxFreq);
-  g_pWideGraph->setTxFreq(m_txFreq);
-  g_pWideGraph->setLockTxFreq(m_lockTxFreq);
-  g_pWideGraph->setFmin(m_fMin);
-  g_pWideGraph->setModeTx(m_mode);
-  g_pWideGraph->setModeTx(m_modeTx);
-  dialFreqChanged2(m_dialFreq);
-
-  connect(g_pWideGraph, SIGNAL(setFreq3(int,int)),this,
+  m_wideGraph->setLockTxFreq(m_lockTxFreq);
+  m_wideGraph->setModeTx(m_mode);
+  m_wideGraph->setModeTx(m_modeTx);
+
+  connect(m_wideGraph.data (), SIGNAL(setFreq3(int,int)),this,
           SLOT(setFreq4(int,int)));
 
   if(m_mode=="JT9") on_actionJT9_1_triggered();
+  if(m_mode=="JT9W-1") on_actionJT9W_1_triggered();
   if(m_mode=="JT65") on_actionJT65_triggered();
   if(m_mode=="JT9+JT65") on_actionJT9_JT65_triggered();
 
@@ -274,347 +486,146 @@ MainWindow::MainWindow(QSharedMemory *shdmem, QString *thekey, QWidget *parent)
   watcher2 = new QFutureWatcher<void>;
   connect(watcher2, SIGNAL(finished()),this,SLOT(diskWriteFinished()));
 
-  soundInThread.setInputDevice(m_paInDevice);
-  soundInThread.start(QThread::HighestPriority);
-  soundOutThread.setOutputDevice(m_paOutDevice);
-  soundOutThread.setTxFreq(m_txFreq);
-  soundOutThread.setTune(false);
-  m_monitoring=!m_monitorStartOFF;           // Start with Monitoring ON/OFF
-  soundInThread.setMonitoring(m_monitoring);
-  m_diskData=false;
-
-// Create "m_worked", a dictionary of all calls in wsjtx.log
-  QFile f("wsjtx.log");
-  f.open(QIODevice::ReadOnly | QIODevice::Text);
-  QTextStream in(&f);
-  QString line,t,callsign;
-  for(int i=0; i<99999; i++) {
-    line=in.readLine();
-    if(line.length()<=0) break;
-    t=line.mid(18,12);
-    callsign=t.mid(0,t.indexOf(","));
-  }
-  f.close();
+  Q_EMIT startAudioInputStream (m_config.audio_input_device (), m_framesAudioInputBuffered, &m_detector, m_downSampleFactor, m_config.audio_input_channel ());
+  Q_EMIT initializeAudioOutputStream (m_config.audio_output_device (), AudioDevice::Mono == m_config.audio_output_channel () ? 1 : 2, m_msAudioOutputBuffered);
 
-  if(ui->actionLinrad->isChecked()) on_actionLinrad_triggered();
-  if(ui->actionCuteSDR->isChecked()) on_actionCuteSDR_triggered();
-  if(ui->actionAFMHot->isChecked()) on_actionAFMHot_triggered();
-  if(ui->actionBlue->isChecked()) on_actionBlue_triggered();
+  Q_EMIT transmitFrequency (ui->TxFreqSpinBox->value () - m_XIT);
 
-  ui->decodedTextLabel->setFont(ui->decodedTextBrowser2->font());
-  ui->decodedTextLabel2->setFont(ui->decodedTextBrowser->font());
-  t="UTC   dB   DT Freq   Message";
+  auto t = "UTC   dB   DT Freq   Message";
   ui->decodedTextLabel->setText(t);
   ui->decodedTextLabel2->setText(t);
 
-#ifdef WIN32
-  if(m_pskReporter) {
-    rc=ReporterInitialize(NULL,NULL);
-    if(rc==0) {
-      m_pskReporterInit=true;
-    } else {
-      m_pskReporterInit=false;
-      rc=ReporterGetInformation(buffer,256);
-      msgBox(QString::fromStdWString(buffer));
-    }
-  }
-#endif
-
-#ifdef UNIX
-  psk_Reporter = new PSK_Reporter(this);
-  psk_Reporter->setLocalStation(m_myCall,m_myGrid, "WSJT-X r" + rev.mid(6,4) );
-#endif
+  enable_DXCC_entity (m_config.DXCC ());  // sets text window proportions and (re)inits the logbook
 
   ui->label_9->setStyleSheet("QLabel{background-color: #aabec8}");
   ui->label_10->setStyleSheet("QLabel{background-color: #aabec8}");
-  ui->labUTC->setStyleSheet( \
-        "QLabel { background-color : black; color : yellow; }");
-  ui->labDialFreq->setStyleSheet( \
-        "QLabel { background-color : black; color : yellow; }");
-
-  QFile f2("ALL.TXT");
-  f2.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append);
-  QTextStream out(&f2);
-  out << QDateTime::currentDateTimeUtc().toString("yyyy-MMM-dd hh:mm")
-      << "  " << m_dialFreq << " MHz  " << m_mode << endl;
-  f2.close();
-}                                          // End of MainWindow constructor
+
+  m_config.transceiver_online (true);
+  on_monitorButton_clicked (!m_config.monitor_off_at_startup ());
+
+#if !WSJT_ENABLE_EXPERIMENTAL_FEATURES
+  ui->actionJT9W_1->setEnabled (false);
+#endif
+}
 
 //--------------------------------------------------- MainWindow destructor
 MainWindow::~MainWindow()
 {
-  writeSettings();
-  if (soundInThread.isRunning()) {
-    soundInThread.quit();
-    soundInThread.wait(3000);
-  }
-  if (soundOutThread.isRunning()) {
-    soundOutThread.quitExecution=true;
-    soundOutThread.wait(3000);
-  }
-  if(!m_decoderBusy) {
-    QFile lockFile(m_appDir + "/.lock");
-    lockFile.remove();
-  }
-  delete ui;
+  QString fname {QDir::toNativeSeparators(m_dataDir.absoluteFilePath ("wsjtx_wisdom.dat"))};
+  QByteArray cfname=fname.toLocal8Bit();
+  fftwf_export_wisdom_to_filename(cfname);
+  m_audioThread->wait ();
+  delete ui, ui = 0;
 }
 
 //-------------------------------------------------------- writeSettings()
 void MainWindow::writeSettings()
 {
-  QString inifile = m_appDir + "/wsjtx.ini";
-  QSettings settings(inifile, QSettings::IniFormat);
-
-  settings.beginGroup("MainWindow");
-  settings.setValue("geometry", saveGeometry());
-  settings.setValue("MRUdir", m_path);
-  settings.setValue("TxFirst",m_txFirst);
-  settings.setValue("DXcall",ui->dxCallEntry->text());
-  settings.setValue("DXgrid",ui->dxGridEntry->text());
-  if(g_pWideGraph->isVisible()) {
-    m_wideGraphGeom = g_pWideGraph->geometry();
-    settings.setValue("WideGraphGeom",m_wideGraphGeom);
-    m_fMin=g_pWideGraph->getFmin();
-  }
-  settings.endGroup();
-
-  settings.beginGroup("Common");
-  settings.setValue("MyCall",m_myCall);
-  settings.setValue("MyGrid",m_myGrid);
-  settings.setValue("IDint",m_idInt);
-  settings.setValue("PTTmethod",m_pttMethodIndex);
-  settings.setValue("PTTport",m_pttPort);
-  settings.setValue("SaveDir",m_saveDir);
-  char soundName[128];
-  if (Pa_GetDeviceInfo( m_paInDevice)) {  // store name, number may be different next time
-    snprintf( soundName, sizeof( soundName), "%s:%s",
-      Pa_GetHostApiInfo( Pa_GetDeviceInfo( m_paInDevice)->hostApi)->name,
-      Pa_GetDeviceInfo( m_paInDevice)->name);
-    settings.setValue("SoundInName", soundName);
-  }
-  if (Pa_GetDeviceInfo( m_paOutDevice)) {  // store name, number may be different next time
-    snprintf( soundName, sizeof( soundName), "%s:%s",
-      Pa_GetHostApiInfo( Pa_GetDeviceInfo( m_paOutDevice)->hostApi)->name,
-      Pa_GetDeviceInfo( m_paOutDevice)->name);
-    settings.setValue("SoundOutName", soundName);
-  }
-  settings.setValue("PaletteCuteSDR",ui->actionCuteSDR->isChecked());
-  settings.setValue("PaletteLinrad",ui->actionLinrad->isChecked());
-  settings.setValue("PaletteAFMHot",ui->actionAFMHot->isChecked());
-  settings.setValue("PaletteBlue",ui->actionBlue->isChecked());
-  settings.setValue("Mode",m_mode);
-  settings.setValue("ModeTx",m_modeTx);
-  settings.setValue("SaveNone",ui->actionNone->isChecked());
-  settings.setValue("SaveDecoded",ui->actionSave_decoded->isChecked());
-  settings.setValue("SaveAll",ui->actionSave_all->isChecked());
-  settings.setValue("NDepth",m_ndepth);
-  settings.setValue("MonitorOFF",m_monitorStartOFF);
-  settings.setValue("DialFreq",m_dialFreq);
-  settings.setValue("RxFreq",m_rxFreq);
-  settings.setValue("TxFreq",m_txFreq);
-  settings.setValue("InGain",m_inGain);
-  settings.setValue("PSKReporter",m_pskReporter);
-  settings.setValue("After73",m_After73);
-  settings.setValue("Macros",m_macro);
-  settings.setValue("DefaultFreqs",m_dFreq);
-  settings.setValue("toRTTY",m_toRTTY);
-  settings.setValue("NoSuffix",m_noSuffix);
-  settings.setValue("dBtoComments",m_dBtoComments);
-  settings.setValue("catEnabled",m_catEnabled);
-  settings.setValue("Rig",m_rig);
-  settings.setValue("RigIndex",m_rigIndex);
-  settings.setValue("CATport",m_catPort);
-  settings.setValue("CATportIndex",m_catPortIndex);
-  settings.setValue("SerialRate",m_serialRate);
-  settings.setValue("SerialRateIndex",m_serialRateIndex);
-  settings.setValue("DataBits",m_dataBits);
-  settings.setValue("DataBitsIndex",m_dataBitsIndex);
-  settings.setValue("StopBits",m_stopBits);
-  settings.setValue("StopBitsIndex",m_stopBitsIndex);
-  settings.setValue("Handshake",m_handshake);
-  settings.setValue("HandshakeIndex",m_handshakeIndex);
-  settings.setValue("BandIndex",m_band);
-  settings.setValue("PromptToLog",m_promptToLog);
-  settings.setValue("InsertBlank",m_insertBlank);
-  settings.setValue("ClearCallGrid",m_clearCallGrid);
-  settings.setValue("Miles",m_bMiles);
-  settings.setValue("GUItab",ui->tabWidget->currentIndex());
-  settings.setValue("QuickCall",m_quickCall);
-  settings.setValue("73TxDisable",m_73TxDisable);
-  settings.setValue("Runaway",m_runaway);
-  settings.setValue("Tx2QSO",m_tx2QSO);
-  settings.setValue("MultipleOK",m_bMultipleOK);
-  settings.setValue("DTRoff",m_bDTRoff);
-  settings.setValue("pttData",m_pttData);
-  settings.setValue("LogQSOgeom",m_logQSOgeom);
-  settings.setValue("Polling",m_poll);
-  settings.setValue("OutBufSize",outBufSize);
-  settings.setValue("LockTxFreq",m_lockTxFreq);
-  settings.setValue("SaveTxPower",m_saveTxPower);
-  settings.setValue("SaveComments",m_saveComments);
-  settings.setValue("TxPower",m_txPower);
-  settings.setValue("LogComments",m_logComments);
-  settings.setValue("PSKantenna",m_pskAntenna);
-  settings.setValue("Fmin",m_fMin);
-  settings.setValue("TxSplit",m_bSplit);
-  settings.setValue("UseXIT",m_bXIT);
-  settings.setValue("Plus2kHz",m_plus2kHz);
-  settings.endGroup();
+  m_settings->beginGroup("MainWindow");
+  m_settings->setValue ("geometry", saveGeometry ());
+  m_settings->setValue ("state", saveState ());
+  m_settings->setValue("MRUdir", m_path);
+  m_settings->setValue("TxFirst",m_txFirst);
+  m_settings->setValue("DXcall",ui->dxCallEntry->text());
+  m_settings->setValue("DXgrid",ui->dxGridEntry->text());
+  m_settings->setValue ("AstroDisplayed", m_astroWidget && m_astroWidget->isVisible());
+  m_settings->setValue ("FreeText", ui->freeTextMsg->currentText ());
+  m_settings->endGroup();
+
+  m_settings->beginGroup("Common");
+  m_settings->setValue("Mode",m_mode);
+  m_settings->setValue("ModeTx",m_modeTx);
+  m_settings->setValue("SaveNone",ui->actionNone->isChecked());
+  m_settings->setValue("SaveDecoded",ui->actionSave_decoded->isChecked());
+  m_settings->setValue("SaveAll",ui->actionSave_all->isChecked());
+  m_settings->setValue("NDepth",m_ndepth);
+  m_settings->setValue("RxFreq",ui->RxFreqSpinBox->value ());
+  m_settings->setValue("TxFreq",ui->TxFreqSpinBox->value ());
+  m_settings->setValue ("DialFreq", QVariant::fromValue(m_lastMonitoredFrequency));
+  m_settings->setValue("InGain",m_inGain);
+  m_settings->setValue("OutAttenuation", ui->outAttenuation->value ());
+  m_settings->setValue("NoSuffix",m_noSuffix);
+  m_settings->setValue("GUItab",ui->tabWidget->currentIndex());
+  m_settings->setValue("OutBufSize",outBufSize);
+  m_settings->setValue("LockTxFreq",m_lockTxFreq);
+  m_settings->setValue("Plus2kHz",m_plus2kHz);
+
+  m_settings->endGroup();
 }
 
 //---------------------------------------------------------- readSettings()
 void MainWindow::readSettings()
 {
-  QString inifile = m_appDir + "/wsjtx.ini";
-  QSettings settings(inifile, QSettings::IniFormat);
-  settings.beginGroup("MainWindow");
-  restoreGeometry(settings.value("geometry").toByteArray());
-  ui->dxCallEntry->setText(settings.value("DXcall","").toString());
-  ui->dxGridEntry->setText(settings.value("DXgrid","").toString());
-  m_wideGraphGeom = settings.value("WideGraphGeom", \
-                                   QRect(45,30,726,301)).toRect();
-  m_path = settings.value("MRUdir", m_appDir + "/save").toString();
-  m_txFirst = settings.value("TxFirst",false).toBool();
+  m_settings->beginGroup("MainWindow");
+  restoreGeometry (m_settings->value ("geometry", saveGeometry ()).toByteArray ());
+  restoreState (m_settings->value ("state", saveState ()).toByteArray ());
+  ui->dxCallEntry->setText(m_settings->value("DXcall","").toString());
+  ui->dxGridEntry->setText(m_settings->value("DXgrid","").toString());
+  m_path = m_settings->value("MRUdir", m_config.save_directory ().absolutePath ()).toString ();
+  m_txFirst = m_settings->value("TxFirst",false).toBool();
   ui->txFirstCheckBox->setChecked(m_txFirst);
-  settings.endGroup();
-
-  settings.beginGroup("Common");
-  m_myCall=settings.value("MyCall","").toString();
-  morse_(m_myCall.toLatin1().data(),icw,&m_ncw,m_myCall.length());
-  m_myGrid=settings.value("MyGrid","").toString();
-  m_idInt=settings.value("IDint",0).toInt();
-  m_pttMethodIndex=settings.value("PTTmethod",1).toInt();
-  m_pttPort=settings.value("PTTport",0).toInt();
-  m_saveDir=settings.value("SaveDir",m_appDir + "/save").toString();
-
-  char soundName[128];
-  QString savedName = settings.value( "SoundInName", "default").toString();
-  for (m_paInDevice = Pa_GetDeviceCount() - 1; m_paInDevice >= 0; m_paInDevice--) {
-    snprintf( soundName, sizeof( soundName), "%s:%s",
-      Pa_GetHostApiInfo( Pa_GetDeviceInfo( m_paInDevice)->hostApi)->name,
-      Pa_GetDeviceInfo( m_paInDevice)->name);
-    if ((savedName == soundName) && (Pa_GetDeviceInfo(m_paInDevice)->maxInputChannels > 0))
-      break;
-  }
-  if (m_paInDevice < 0) { // no match for device name?
-    m_paInDevice = Pa_GetDefaultInputDevice();
-    if (m_paInDevice == paNoDevice)  // no default input device?
-      m_paInDevice = 0;
-  }
+  auto displayAstro = m_settings->value ("AstroDisplayed", false).toBool ();
 
-  savedName = settings.value("SoundOutName", "default").toString();
-  for (m_paOutDevice = Pa_GetDeviceCount() - 1; m_paOutDevice >= 0; m_paOutDevice--) {
-    snprintf( soundName, sizeof( soundName), "%s:%s",
-      Pa_GetHostApiInfo( Pa_GetDeviceInfo( m_paOutDevice)->hostApi)->name,
-      Pa_GetDeviceInfo( m_paOutDevice)->name);
-    if ((savedName == soundName) && (Pa_GetDeviceInfo(m_paOutDevice)->maxOutputChannels > 0))
-      break;
-  }
-  if (m_paOutDevice < 0) { // no match for device name?
-    m_paOutDevice = Pa_GetDefaultOutputDevice();
-    if (m_paOutDevice == paNoDevice)  // no default output device?
-      m_paOutDevice = 0;
+  if (m_settings->contains ("FreeText"))
+  {
+    ui->freeTextMsg->setCurrentText (m_settings->value ("FreeText").toString ());
   }
 
-  ui->actionCuteSDR->setChecked(settings.value(
-                                  "PaletteCuteSDR",false).toBool());
-  ui->actionLinrad->setChecked(settings.value(
-                                 "PaletteLinrad",true).toBool());
-  ui->actionAFMHot->setChecked(settings.value(
-                                 "PaletteAFMHot",false).toBool());
-  ui->actionBlue->setChecked(settings.value(
-                                 "PaletteBlue",false).toBool());
-  m_mode=settings.value("Mode","JT9").toString();
-  m_modeTx=settings.value("ModeTx","JT9").toString();
-  if(m_modeTx=="JT9") ui->pbTxMode->setText("Tx JT9  @");
+  m_settings->endGroup();
+
+  // do this outside of settings group because it uses groups internally
+  if (displayAstro)
+    {
+      on_actionAstronomical_data_triggered ();
+    }
+
+  m_settings->beginGroup("Common");
+  morse_(const_cast<char *> (m_config.my_callsign ().toLatin1().constData())
+         , const_cast<int *> (icw)
+         , &m_ncw
+         , m_config.my_callsign ().length());
+  m_mode=m_settings->value("Mode","JT9").toString();
+  m_modeTx=m_settings->value("ModeTx","JT9").toString();
+  if(m_modeTx.mid(0,3)=="JT9") ui->pbTxMode->setText("Tx JT9  @");
   if(m_modeTx=="JT65") ui->pbTxMode->setText("Tx JT65  #");
-  ui->actionNone->setChecked(settings.value("SaveNone",true).toBool());
-  ui->actionSave_decoded->setChecked(settings.value(
-                                         "SaveDecoded",false).toBool());
-  ui->actionSave_all->setChecked(settings.value("SaveAll",false).toBool());
-  m_dialFreq=settings.value("DialFreq",14.078).toDouble();
-  m_rxFreq=settings.value("RxFreq",1500).toInt();
-  ui->RxFreqSpinBox->setValue(m_rxFreq);
-  m_txFreq=settings.value("TxFreq",1500).toInt();
-  ui->TxFreqSpinBox->setValue(m_txFreq);
-  soundOutThread.setTxFreq(m_txFreq);
+  ui->actionNone->setChecked(m_settings->value("SaveNone",true).toBool());
+  ui->actionSave_decoded->setChecked(m_settings->value(
+                                                       "SaveDecoded",false).toBool());
+  ui->actionSave_all->setChecked(m_settings->value("SaveAll",false).toBool());
+  ui->RxFreqSpinBox->setValue(0); // ensure a change is signaled
+  ui->RxFreqSpinBox->setValue(m_settings->value("RxFreq",1500).toInt());
+  m_lastMonitoredFrequency = m_settings->value ("DialFreq", QVariant::fromValue<Frequency> (default_frequency)).value<Frequency> ();
+  ui->TxFreqSpinBox->setValue(0); // ensure a change is signaled
+  ui->TxFreqSpinBox->setValue(m_settings->value("TxFreq",1500).toInt());
+  Q_EMIT transmitFrequency (ui->TxFreqSpinBox->value () - m_XIT);
   m_saveDecoded=ui->actionSave_decoded->isChecked();
   m_saveAll=ui->actionSave_all->isChecked();
-  m_ndepth=settings.value("NDepth",3).toInt();
-  m_inGain=settings.value("InGain",0).toInt();
+  m_ndepth=m_settings->value("NDepth",3).toInt();
+  m_inGain=m_settings->value("InGain",0).toInt();
   ui->inGain->setValue(m_inGain);
-  m_monitorStartOFF=settings.value("MonitorOFF",false).toBool();
-  ui->actionMonitor_OFF_at_startup->setChecked(m_monitorStartOFF);
-  m_pskReporter=settings.value("PSKReporter",false).toBool();
-  m_After73=settings.value("After73",false).toBool();
-  m_macro=settings.value("Macros","TNX 73 GL").toStringList();
-  m_dFreq=settings.value("DefaultFreqs","").toStringList();
-  m_toRTTY=settings.value("toRTTY",false).toBool();
-  ui->actionConvert_JT9_x_to_RTTY->setChecked(m_toRTTY);
-  m_noSuffix=settings.value("NoSuffix",false).toBool();
-  ui->actionLog_JT9_without_submode->setChecked(m_noSuffix);
-  m_dBtoComments=settings.value("dBtoComments",false).toBool();
-  ui->actionLog_dB_reports_to_Comments->setChecked(m_dBtoComments);
-  m_rig=settings.value("Rig",214).toInt();
-  m_rigIndex=settings.value("RigIndex",100).toInt();
-  m_catPort=settings.value("CATport","None").toString();
-  m_catPortIndex=settings.value("CATportIndex",0).toInt();
-  m_serialRate=settings.value("SerialRate",4800).toInt();
-  m_serialRateIndex=settings.value("SerialRateIndex",1).toInt();
-  m_dataBits=settings.value("DataBits",8).toInt();
-  m_dataBitsIndex=settings.value("DataBitsIndex",1).toInt();
-  m_stopBits=settings.value("StopBits",2).toInt();
-  m_stopBitsIndex=settings.value("StopBitsIndex",1).toInt();
-  m_handshake=settings.value("Handshake","None").toString();
-  m_handshakeIndex=settings.value("HandshakeIndex",0).toInt();
-  m_band=settings.value("BandIndex",7).toInt();
-  ui->bandComboBox->setCurrentIndex(m_band);
-  dialFreqChanged2(m_dialFreq);
-  m_catEnabled=settings.value("catEnabled",false).toBool();
-  m_promptToLog=settings.value("PromptToLog",false).toBool();
-  ui->actionPrompt_to_log_QSO->setChecked(m_promptToLog);
-  m_insertBlank=settings.value("InsertBlank",false).toBool();
-  ui->actionBlank_line_between_decoding_periods->setChecked(m_insertBlank);
-  m_clearCallGrid=settings.value("ClearCallGrid",false).toBool();
-  ui->actionClear_DX_Call_and_Grid_after_logging->setChecked(m_clearCallGrid);
-  m_bMiles=settings.value("Miles",false).toBool();
-  ui->actionDisplay_distance_in_miles->setChecked(m_bMiles);
-  int n=settings.value("GUItab",0).toInt();
+
+  // setup initial value of tx attenuator
+  ui->outAttenuation->setValue (m_settings->value ("OutAttenuation", 0).toInt ());
+  on_outAttenuation_valueChanged (ui->outAttenuation->value ());
+
+  m_noSuffix=m_settings->value("NoSuffix",false).toBool();
+  int n=m_settings->value("GUItab",0).toInt();
   ui->tabWidget->setCurrentIndex(n);
-  m_quickCall=settings.value("QuickCall",false).toBool();
-  ui->actionDouble_click_on_call_sets_Tx_Enable->setChecked(m_quickCall);
-  m_73TxDisable=settings.value("73TxDisable",false).toBool();
-  ui->action_73TxDisable->setChecked(m_73TxDisable);
-  m_runaway=settings.value("Runaway",false).toBool();
-  ui->actionRunaway_Tx_watchdog->setChecked(m_runaway);
-  m_tx2QSO=settings.value("Tx2QSO",false).toBool();
-  ui->actionTx2QSO->setChecked(m_tx2QSO);
-  m_bMultipleOK=settings.value("MultipleOK",false).toBool();
-  ui->actionAllow_multiple_instances->setChecked(m_bMultipleOK);
-  m_bDTRoff=settings.value("DTRoff",false).toBool();
-  m_pttData=settings.value("pttData",false).toBool();
-  m_poll=settings.value("Polling",0).toInt();
-  m_logQSOgeom=settings.value("LogQSOgeom",QRect(500,400,424,283)).toRect();
-  outBufSize=settings.value("OutBufSize",4096).toInt();
-  m_lockTxFreq=settings.value("LockTxFreq",false).toBool();
+  outBufSize=m_settings->value("OutBufSize",4096).toInt();
+  m_lockTxFreq=m_settings->value("LockTxFreq",false).toBool();
   ui->cbTxLock->setChecked(m_lockTxFreq);
-  m_saveTxPower=settings.value("SaveTxPower",false).toBool();
-  m_saveComments=settings.value("SaveComments",false).toBool();
-  m_txPower=settings.value("TxPower","").toString();
-  m_logComments=settings.value("LogComments","").toString();
-  m_pskAntenna=settings.value("PSKantenna","").toString();
-  m_fMin=settings.value("fMin",2500).toInt();
-  m_bSplit=settings.value("TxSplit",false).toBool();
-  m_bXIT=settings.value("UseXit",false).toBool();
-  m_plus2kHz=settings.value("Plus2kHz",false).toBool();
+  m_plus2kHz=m_settings->value("Plus2kHz",false).toBool();
   ui->cbPlus2kHz->setChecked(m_plus2kHz);
-  settings.endGroup();
+  m_settings->endGroup();
+
+  // use these initialisation settings to tune the audio o/p buffer
+  // size and audio thread priority
+  m_settings->beginGroup ("Tune");
+  m_msAudioOutputBuffered = m_settings->value ("Audio/OutputBufferMs").toInt ();
+  m_framesAudioInputBuffered = m_settings->value ("Audio/InputBufferFrames", RX_SAMPLE_RATE / 10).toInt ();
+  m_audioThreadPriority = static_cast<QThread::Priority> (m_settings->value ("Audio/ThreadPriority", QThread::HighPriority).toInt () % 8);
+  m_settings->endGroup ();
 
-  if(!ui->actionLinrad->isChecked() && !ui->actionCuteSDR->isChecked() &&
-    !ui->actionAFMHot->isChecked() && !ui->actionBlue->isChecked()) {
-    on_actionLinrad_triggered();
-    ui->actionLinrad->setChecked(true);
-  }
   if(m_ndepth==1) ui->actionQuickDecode->setChecked(true);
   if(m_ndepth==2) ui->actionMediumDecode->setChecked(true);
   if(m_ndepth==3) ui->actionDeepestDecode->setChecked(true);
@@ -622,17 +633,26 @@ void MainWindow::readSettings()
   statusChanged();
 }
 
+void MainWindow::setDecodedTextFont (QFont const& font)
+{
+  ui->decodedTextBrowser->setContentFont (font);
+  ui->decodedTextBrowser2->setContentFont (font);
+  auto style_sheet = "QLabel {" + font_as_stylesheet (font) + '}';
+  ui->decodedTextLabel->setStyleSheet (ui->decodedTextLabel->styleSheet () + style_sheet);
+  ui->decodedTextLabel2->setStyleSheet (ui->decodedTextLabel2->styleSheet () + style_sheet);
+}
+
 //-------------------------------------------------------------- dataSink()
-void MainWindow::dataSink(int k)
+void MainWindow::dataSink(qint64 frames)
 {
   static float s[NSMAX];
   static int ihsym=0;
   static int nzap=0;
   static int trmin;
   static int npts8;
+  static int nflatten=0;
   static float px=0.0;
   static float df3;
-  static float slope;
 
   if(m_diskData) {
     jt9com_.ndiskdat=1;
@@ -640,18 +660,21 @@ void MainWindow::dataSink(int k)
     jt9com_.ndiskdat=0;
   }
 
-// Get power, spectrum, and ihsym
+  // Get power, spectrum, and ihsym
   trmin=m_TRperiod/60;
-  slope=0.0;
-  if(g_pWideGraph!=NULL) slope=(float)g_pWideGraph->getSlope();
-  symspec_(&k,&trmin,&m_nsps,&m_inGain,&slope,&px,s,&df3,&ihsym,&npts8);
+  int k (frames - 1);
+  jt9com_.nfa=m_wideGraph->nStartFreq();
+  jt9com_.nfb=m_wideGraph->getFmax();
+  nflatten=0;
+  if(m_wideGraph->flatten()) nflatten=1;
+  symspec_(&k,&trmin,&m_nsps,&m_inGain,&nflatten,&px,s,&df3,&ihsym,&npts8);
   if(ihsym <=0) return;
   QString t;
   m_pctZap=nzap*100.0/m_nsps;
   t.sprintf(" Rx noise: %5.1f ",px);
   signalMeter->setValue(px);                            // Update thermometer
   if(m_monitoring || m_diskData) {
-    g_pWideGraph->dataSink2(s,df3,ihsym,m_diskData);
+    m_wideGraph->dataSink2(s,df3,ihsym,m_diskData);
   }
 
   if(ihsym == m_hsymStop) {
@@ -669,305 +692,237 @@ void MainWindow::dataSink(int k)
       imin=imin - (imin%(m_TRperiod/60));
       QString t2;
       t2.sprintf("%2.2d%2.2d",ihr,imin);
-      m_fname=m_saveDir + "/" + t.date().toString("yyMMdd") + "_" +
-            t2 + ".wav";
+      m_fname=m_config.save_directory ().absoluteFilePath (t.date().toString("yyMMdd") + "_" + t2 + ".wav");
       *future2 = QtConcurrent::run(savewav, m_fname, m_TRperiod);
       watcher2->setFuture(*future2);
     }
   }
-  soundInThread.m_dataSinkBusy=false;
 }
 
 void MainWindow::showSoundInError(const QString& errorMsg)
- {QMessageBox::critical(this, tr("Error in SoundIn"), errorMsg);}
+{QMessageBox::critical(this, tr("Error in SoundInput"), errorMsg);}
+
+void MainWindow::showSoundOutError(const QString& errorMsg)
+{QMessageBox::critical(this, tr("Error in SoundOutput"), errorMsg);}
 
 void MainWindow::showStatusMessage(const QString& statusMsg)
- {statusBar()->showMessage(statusMsg);}
-
-void MainWindow::on_actionDeviceSetup_triggered()               //Setup Dialog
-{
-  DevSetup dlg(this);
-  dlg.m_myCall=m_myCall;
-  dlg.m_myGrid=m_myGrid;
-  dlg.m_pskAntenna=m_pskAntenna;
-  dlg.m_idInt=m_idInt;
-  dlg.m_pttMethodIndex=m_pttMethodIndex;
-  dlg.m_pttPort=m_pttPort;
-  dlg.m_saveDir=m_saveDir;
-  dlg.m_paInDevice=m_paInDevice;
-  dlg.m_paOutDevice=m_paOutDevice;
-  dlg.m_pskReporter=m_pskReporter;
-  dlg.m_After73=m_After73;
-  dlg.m_macro=m_macro;
-  dlg.m_dFreq=m_dFreq;
-  dlg.m_catEnabled=m_catEnabled;
-  dlg.m_rig=m_rig;
-  dlg.m_rigIndex=m_rigIndex;
-  dlg.m_catPort=m_catPort;
-  dlg.m_catPortIndex=m_catPortIndex;
-  dlg.m_serialRate=m_serialRate;
-  dlg.m_serialRateIndex=m_serialRateIndex;
-  dlg.m_dataBits=m_dataBits;
-  dlg.m_dataBitsIndex=m_dataBitsIndex;
-  dlg.m_stopBits=m_stopBits;
-  dlg.m_stopBitsIndex=m_stopBitsIndex;
-  dlg.m_handshake=m_handshake;
-  dlg.m_handshakeIndex=m_handshakeIndex;
-  dlg.m_bDTRoff=m_bDTRoff;
-  dlg.m_pttData=m_pttData;
-  dlg.m_poll=m_poll;
-  dlg.m_bSplit=m_bSplit;
-  dlg.m_bXIT=m_bXIT;
-
-  if(m_bRigOpen) {
-    rig->close();
-    ui->readFreq->setStyleSheet("");
-    ui->readFreq->setEnabled(false);
-    if(m_rig<9900) delete rig;
-    m_bRigOpen=false;
-    m_catEnabled=false;
-    m_CATerror=false;
-  }
+{statusBar()->showMessage(statusMsg);}
+
+void MainWindow::on_actionSettings_triggered()               //Setup Dialog
+{
+  ui->readFreq->setStyleSheet("");
+  ui->readFreq->setEnabled(false);
 
-  dlg.initDlg();
-  if(dlg.exec() == QDialog::Accepted) {
-    m_myCall=dlg.m_myCall;
-    m_myGrid=dlg.m_myGrid;
-    m_pskAntenna=dlg.m_pskAntenna;
-    m_idInt=dlg.m_idInt;
-    m_pttMethodIndex=dlg.m_pttMethodIndex;
-    m_pttPort=dlg.m_pttPort;
-    m_saveDir=dlg.m_saveDir;
-    m_paInDevice=dlg.m_paInDevice;
-    m_paOutDevice=dlg.m_paOutDevice;
-    m_macro=dlg.m_macro;
-    m_dFreq=dlg.m_dFreq;
-    m_catEnabled=dlg.m_catEnabled;
-    m_rig=dlg.m_rig;
-    m_rigIndex=dlg.m_rigIndex;
-    m_catPort=dlg.m_catPort;
-    m_catPortIndex=dlg.m_catPortIndex;
-    m_serialRate=dlg.m_serialRate;
-    m_serialRateIndex=dlg.m_serialRateIndex;
-    m_dataBits=dlg.m_dataBits;
-    m_dataBitsIndex=dlg.m_dataBitsIndex;
-    m_stopBits=dlg.m_stopBits;
-    m_stopBitsIndex=dlg.m_stopBitsIndex;
-    m_handshake=dlg.m_handshake;
-    m_handshakeIndex=dlg.m_handshakeIndex;
-    m_bDTRoff=dlg.m_bDTRoff;
-    m_pttData=dlg.m_pttData;
-    m_poll=dlg.m_poll;
+  // things that might change that we need know about
+  auto callsign = m_config.my_callsign ();
+
+  if (QDialog::Accepted == m_config.exec ())
+    {
+      if (m_config.my_callsign () != callsign)
+        {
+          m_baseCall = Radio::base_callsign (m_config.my_callsign ());
+          morse_(const_cast<char *> (m_config.my_callsign ().toLatin1().constData())
+                 , const_cast<int *> (icw)
+                 , &m_ncw
+                 , m_config.my_callsign ().length());
+        }
 
-#ifdef WIN32
-    if(dlg.m_pskReporter!=m_pskReporter) {
-      if(dlg.m_pskReporter) {
-        int rc=ReporterInitialize(NULL,NULL);
-        if(rc==0) {
-          m_pskReporterInit=true;
-        } else {
-          m_pskReporterInit=false;
-          rc=ReporterGetInformation(buffer,256);
-          msgBox(QString::fromStdWString(buffer));
+      on_dxGridEntry_textChanged (m_hisGrid); // recalculate distances in case of units change
+      enable_DXCC_entity (m_config.DXCC ());  // sets text window proportions and (re)inits the logbook
+
+      if(m_config.spot_to_psk_reporter ())
+        {
+          pskSetLocal ();
         }
-      } else {
-        rc=ReporterUninitialize();
-        m_pskReporterInit=false;
-      }
-    }
-#endif
-    m_pskReporter=dlg.m_pskReporter;
 
-#ifdef UNIX
-    if(m_pskReporter) {
-      psk_Reporter->setLocalStation(m_myCall,m_myGrid, "WSJT-X r" + rev.mid(6,4) );
-    }
-#endif
+      if(m_mode=="JT9W-1") m_toneSpacing=pow(2,m_config.jt9w_bw_mult ())*12000.0/6912.0;
 
-    m_After73=dlg.m_After73;
+      if(m_config.restart_audio_input ()) {
+        Q_EMIT startAudioInputStream (m_config.audio_input_device (), m_framesAudioInputBuffered, &m_detector, m_downSampleFactor, m_config.audio_input_channel ());
+      }
+      if(m_config.restart_audio_output ()) {
+        Q_EMIT initializeAudioOutputStream (m_config.audio_output_device (), AudioDevice::Mono == m_config.audio_output_channel () ? 1 : 2, m_msAudioOutputBuffered);
+      }
 
-    if(dlg.m_restartSoundIn) {
-      soundInThread.quit();
-      soundInThread.wait(1000);
-      soundInThread.setInputDevice(m_paInDevice);
-      soundInThread.start(QThread::HighestPriority);
-    }
+      auto_tx_label->setText (m_config.quick_call () ? "Tx-Enable Armed" : "Tx-Enable Disarmed");
 
-    if(dlg.m_restartSoundOut) {
-      soundOutThread.quitExecution=true;
-      soundOutThread.wait(1000);
-      soundOutThread.setOutputDevice(m_paOutDevice);
+      displayDialFrequency ();
     }
-  }
-  m_catEnabled=dlg.m_catEnabled;
 
-  if(m_catEnabled) {
-    rigOpen();
-  } else {
-    ui->readFreq->setStyleSheet("");
-  }
-
-  if(dlg.m_bSplit!=m_bSplit or dlg.m_bXIT!=m_bXIT) {
-    m_bSplit=dlg.m_bSplit;
-    m_bXIT=dlg.m_bXIT;
-    if(m_bSplit or m_bXIT) setXIT(m_txFreq);
-    if(m_bRigOpen and !m_bSplit) {
-      int ret=rig->setSplitFreq(MHz(m_dialFreq),RIG_VFO_B);
-      if(ret!=RIG_OK) {
-        QString rt;
-        rt.sprintf("Setting VFO_B failed:  %d",ret);
-        msgBox(rt);
-      }
+  setXIT (ui->TxFreqSpinBox->value ());
+  if (m_config.transceiver_online ())
+    {
+      Q_EMIT m_config.transceiver_frequency (m_dialFreq);
     }
-  }
 }
 
-void MainWindow::on_monitorButton_clicked()                  //Monitor
+void MainWindow::on_monitorButton_clicked (bool checked)
 {
-  m_monitoring=true;
-  soundInThread.setMonitoring(true);
-  m_diskData=false;
-}
+  if (!m_transmitting)
+    {
+      auto prior = m_monitoring;
+      monitor (checked);
 
-void MainWindow::on_actionLinrad_triggered()                 //Linrad palette
-{
-  if(g_pWideGraph != NULL) g_pWideGraph->setPalette("Linrad");
-}
+      if (checked && !prior)
+        {
+          m_diskData = false;	// no longer reading WAV files
 
-void MainWindow::on_actionCuteSDR_triggered()                //CuteSDR palette
-{
-  if(g_pWideGraph != NULL) g_pWideGraph->setPalette("CuteSDR");
+          Frequency operating_frequency {m_dialFreq};
+          if (m_config.monitor_last_used ())
+            {
+              // put rig back where it was when last in control
+              operating_frequency = m_lastMonitoredFrequency;
+              Q_EMIT m_config.transceiver_frequency (operating_frequency);
+            }
+          qsy (operating_frequency);
+          if (m_config.monitor_last_used ())
+            {
+              setXIT (ui->TxFreqSpinBox->value ());
+            }
+        }
+
+      Q_EMIT m_config.sync_transceiver (true, checked); // gets
+                                                        // Configuration
+                                                        // in/out of
+                                                        // strict
+                                                        // split and
+                                                        // mode
+                                                        // checking
+
+    }
+  else
+    {
+      ui->monitorButton->setChecked (false); // disallow
+    }
 }
 
-void MainWindow::on_actionAFMHot_triggered()
+void MainWindow::monitor (bool state)
 {
-  if(g_pWideGraph != NULL) g_pWideGraph->setPalette("AFMHot");
+  ui->monitorButton->setChecked (state);
+  if (state)
+    {
+      if (!m_monitoring)
+        {
+          Q_EMIT resumeAudioInputStream ();
+        }
+    }
+  else
+    {
+      Q_EMIT suspendAudioInputStream ();
+    }
+  m_monitoring = state;
 }
 
-void MainWindow::on_actionBlue_triggered()
+void MainWindow::on_actionAbout_triggered()                  //Display "About"
 {
-  if(g_pWideGraph != NULL) g_pWideGraph->setPalette("Blue");
+  CAboutDlg {this}.exec ();
 }
 
-void MainWindow::on_actionAbout_triggered()                  //Display "About"
+void MainWindow::on_autoButton_clicked (bool checked)
 {
-  CAboutDlg dlg(this,Program_Title_Version);
-  dlg.exec();
+  m_auto = checked;
+  m_messageClient->status_update (m_dialFreq, m_mode, m_hisCall, QString::number (ui->rptSpinBox->value ()), m_modeTx, ui->autoButton->isChecked (), m_transmitting);
 }
 
-void MainWindow::on_autoButton_clicked()                     //Auto
+void MainWindow::auto_tx_mode (bool state)
 {
-  m_auto = !m_auto;
-  if(m_auto) {
-    ui->autoButton->setStyleSheet(m_pbAutoOn_style);
-  } else {
-    btxok=false;
-    ui->autoButton->setStyleSheet("");
-    on_monitorButton_clicked();
-    m_repeatMsg=0;
-  }
+  ui->autoButton->setChecked (state);
+  on_autoButton_clicked (state);
 }
 
 void MainWindow::keyPressEvent( QKeyEvent *e )                //keyPressEvent
 {
   int n;
   switch(e->key())
-  {
-  case Qt::Key_1:
-    if(e->modifiers() & Qt::AltModifier) {
-      on_txb1_clicked();
-      break;
-    }
-  case Qt::Key_2:
-    if(e->modifiers() & Qt::AltModifier) {
-      on_txb2_clicked();
-      break;
-    }
-  case Qt::Key_3:
-    if(e->modifiers() & Qt::AltModifier) {
-      on_txb3_clicked();
-      break;
-    }
-  case Qt::Key_4:
-    if(e->modifiers() & Qt::AltModifier) {
-      on_txb4_clicked();
-      break;
-    }
-  case Qt::Key_5:
-    if(e->modifiers() & Qt::AltModifier) {
-      on_txb5_clicked();
-      break;
-    }
-  case Qt::Key_6:
-    if(e->modifiers() & Qt::AltModifier) {
-      on_txb6_clicked();
+    {
+    case Qt::Key_D:
+      if(e->modifiers() & Qt::ShiftModifier) {
+        if(!m_decoderBusy) {
+          jt9com_.newdat=0;
+          jt9com_.nagain=0;
+          decode();
+          return;
+        }
+      }
       break;
-    }
-  case Qt::Key_D:
-    if(e->modifiers() & Qt::ShiftModifier) {
-      if(!m_decoderBusy) {
-        jt9com_.newdat=0;
-        jt9com_.nagain=0;
-        decode();
-        break;
+    case Qt::Key_F4:
+      ui->dxCallEntry->setText("");
+      ui->dxGridEntry->setText("");
+      m_hisCall="";
+      m_hisGrid="";
+      m_rptSent="";
+      m_rptRcvd="";
+      m_qsoStart="";
+      m_qsoStop="";
+      genStdMsgs("");
+      if (1 == ui->tabWidget->currentIndex())
+        {
+          ui->genMsg->setText(ui->tx6->text());
+          m_ntx=7;
+          ui->rbGenMsg->setChecked(true);
+        }
+      else
+        {
+          m_ntx=6;
+          ui->txrb6->setChecked(true);
+        }
+      return;
+    case Qt::Key_F6:
+      if(e->modifiers() & Qt::ShiftModifier) {
+        on_actionDecode_remaining_files_in_directory_triggered();
+        return;
       }
-    }
-    break;
-  case Qt::Key_F4:
-    ui->dxCallEntry->setText("");
-    ui->dxGridEntry->setText("");
-    genStdMsgs("");
-    m_ntx=6;
-    ui->txrb6->setChecked(true);
-    break;
-  case Qt::Key_F6:
-    if(e->modifiers() & Qt::ShiftModifier) {
-      on_actionDecode_remaining_files_in_directory_triggered();
-    }
-    break;
-  case Qt::Key_F11:
-    n=11;
-    if(e->modifiers() & Qt::ControlModifier) n+=100;
-    bumpFqso(n);
-    break;
-  case Qt::Key_F12:
-    n=12;
-    if(e->modifiers() & Qt::ControlModifier) n+=100;
-    bumpFqso(n);
-    break;
-  case Qt::Key_F:
-    if(e->modifiers() & Qt::ControlModifier) {
-      if(ui->tabWidget->currentIndex()==0) {
-        ui->tx5->clear();
-        ui->tx5->setFocus();
-      } else {
-        ui->freeTextMsg->clear();
-        ui->freeTextMsg->setFocus();
+      break;
+    case Qt::Key_F11:
+      n=11;
+      if(e->modifiers() & Qt::ControlModifier) n+=100;
+      bumpFqso(n);
+      return;
+    case Qt::Key_F12:
+      n=12;
+      if(e->modifiers() & Qt::ControlModifier) n+=100;
+      bumpFqso(n);
+      return;
+    case Qt::Key_F:
+      if(e->modifiers() & Qt::ControlModifier) {
+        if(ui->tabWidget->currentIndex()==0) {
+          ui->tx5->clearEditText();
+          ui->tx5->setFocus();
+        } else {
+          ui->freeTextMsg->clearEditText();
+          ui->freeTextMsg->setFocus();
+        }
+        return;
       }
       break;
-    }
-  case Qt::Key_G:
-    if(e->modifiers() & Qt::AltModifier) {
-      genStdMsgs(m_rpt);
+    case Qt::Key_G:
+      if(e->modifiers() & Qt::AltModifier) {
+        genStdMsgs(m_rpt);
+        return;
+      }
       break;
-    }
-  case Qt::Key_H:
-    if(e->modifiers() & Qt::AltModifier) {
-      on_stopTxButton_clicked();
+    case Qt::Key_H:
+      if(e->modifiers() & Qt::AltModifier) {
+        on_stopTxButton_clicked();
+        return;
+      }
       break;
-    }
-  case Qt::Key_L:
-    if(e->modifiers() & Qt::ControlModifier) {
-      lookup();
-      genStdMsgs(m_rpt);
+    case Qt::Key_L:
+      if(e->modifiers() & Qt::ControlModifier) {
+        lookup();
+        genStdMsgs(m_rpt);
+        return;
+      }
       break;
-    }
-  case Qt::Key_V:
-    if(e->modifiers() & Qt::AltModifier) {
-      m_fileToSave=m_fname;
+    case Qt::Key_V:
+      if(e->modifiers() & Qt::AltModifier) {
+        m_fileToSave=m_fname;
+        return;
+      }
       break;
     }
-  }
+
+  QMainWindow::keyPressEvent (e);
 }
 
 void MainWindow::bumpFqso(int n)                                 //bumpFqso()
@@ -975,49 +930,101 @@ void MainWindow::bumpFqso(int n)                                 //bumpFqso()
   int i;
   bool ctrl = (n>=100);
   n=n%100;
-  i=g_pWideGraph->rxFreq();
+  i=ui->RxFreqSpinBox->value ();
   if(n==11) i--;
   if(n==12) i++;
-  g_pWideGraph->setRxFreq(i);
-  if(ctrl) {
-    ui->TxFreqSpinBox->setValue(i);
-    g_pWideGraph->setTxFreq(i);
-  }
+  if (ui->RxFreqSpinBox->isEnabled ())
+    {
+      ui->RxFreqSpinBox->setValue (i);
+    }
+  if(ctrl && ui->TxFreqSpinBox->isEnabled ())
+    {
+      ui->TxFreqSpinBox->setValue (i);
+    }
 }
 
-void MainWindow::dialFreqChanged2(double f)
+void MainWindow::qsy (Frequency f)
 {
-  m_dialFreq=f;
-  if(m_band<0 or m_band>15 or m_dFreq.length()<=1) return;
-  QString t;
-  t.sprintf("%.6f",m_dialFreq);
-  int n=t.length();
-  t=t.mid(0,n-3) + " " + t.mid(n-3,3);
-  double fBand=m_dFreq[m_band].toDouble();
-  if(qAbs(m_dialFreq-fBand)<0.01) {
-    ui->labDialFreq->setStyleSheet( \
-        "QLabel { background-color : black; color : yellow; }");
-  } else {
-    ui->labDialFreq->setStyleSheet( \
-          "QLabel { background-color : red; color : yellow; }");
-    ui->labDialFreq->setText(t);
-  }
-  ui->labDialFreq->setText(t);
-  statusChanged();
-  if(g_pWideGraph!=NULL) g_pWideGraph->setDialFreq(m_dialFreq);
+  if (!m_transmitting)
+    {
+      if (m_monitoring)
+        {
+          m_lastMonitoredFrequency = f;
+        }
+
+      if (m_dialFreq != f)
+        {
+          m_dialFreq = f;
+
+          m_repeatMsg=0;
+          m_secBandChanged=QDateTime::currentMSecsSinceEpoch()/1000;
+
+          QFile f2 {m_dataDir.absoluteFilePath ("ALL.TXT")};
+          if (f2.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append))
+            {
+              QTextStream out(&f2);
+              out << QDateTime::currentDateTimeUtc().toString("yyyy-MMM-dd hh:mm")
+                  << "  " << (m_dialFreq / 1.e6) << " MHz  " << m_mode << endl;
+              f2.close();
+            }
+          else
+            {
+              msgBox("Cannot open \"" + f2.fileName () + "\" for append:" + f2.errorString ());
+            }
+          if (m_config.spot_to_psk_reporter ())
+            {
+              pskSetLocal ();
+            }
+
+          displayDialFrequency ();
+          statusChanged();
+          m_wideGraph->setDialFreq(m_dialFreq / 1.e6);
+        }
+    }
+}
+
+void MainWindow::displayDialFrequency ()
+{
+  // lookup band
+  auto bands_model = m_config.bands ();
+  ui->bandComboBox->setCurrentText (bands_model->data (bands_model->find (m_dialFreq)).toString ());
+
+  // search working frequencies for one we are within 10kHz of
+  auto frequencies = m_config.frequencies ();
+  bool valid {false};
+  for (int row = 0; row < frequencies->rowCount (); ++row)
+    {
+      // we need to do specific checks for above and below here to
+      // ensure that we can use unsigned Radio::Frequency since we
+      // potentially use the full 64-bit unsigned range.
+      auto working_frequency = frequencies->data (frequencies->index (row, 0)).value<Frequency> ();
+      auto offset = m_dialFreq > working_frequency ? m_dialFreq - working_frequency : working_frequency - m_dialFreq;
+      if (offset < 10000u)
+        {
+          valid = true;
+        }
+    }
+  ui->labDialFreq->setProperty ("oob", !valid);
+  // the following sequence is necessary to update the style
+  ui->labDialFreq->style ()->unpolish (ui->labDialFreq);
+  ui->labDialFreq->style ()->polish (ui->labDialFreq);
+  ui->labDialFreq->update ();
+
+  ui->labDialFreq->setText (Radio::pretty_frequency_MHz_string (m_dialFreq));
 }
 
 void MainWindow::statusChanged()
 {
-  QFile f("wsjtx_status.txt");
+  m_messageClient->status_update (m_dialFreq, m_mode, m_hisCall, QString::number (ui->rptSpinBox->value ()), m_modeTx, ui->autoButton->isChecked (), m_transmitting);
+
+  QFile f {m_config.temp_dir ().absoluteFilePath ("wsjtx_status.txt")};
   if(f.open(QFile::WriteOnly | QIODevice::Text)) {
     QTextStream out(&f);
-    out << m_dialFreq << ";" << m_mode << ";" << m_hisCall << ";"
+    out << (m_dialFreq / 1.e6) << ";" << m_mode << ";" << m_hisCall << ";"
         << ui->rptSpinBox->value() << ";" << m_modeTx << endl;
     f.close();
   } else {
-    msgBox("Cannot open file \"wsjtx_status.txt\".");
-    return;
+    msgBox("Cannot open \"" + f.fileName () + "\" for writing:" + f.errorString ());
   }
 }
 
@@ -1033,56 +1040,60 @@ bool MainWindow::eventFilter(QObject *object, QEvent *event)  //eventFilter()
 
 void MainWindow::createStatusBar()                           //createStatusBar
 {
-  lab1 = new QLabel("Receiving");
-  lab1->setAlignment(Qt::AlignHCenter);
-  lab1->setMinimumSize(QSize(80,18));
-  lab1->setStyleSheet("QLabel{background-color: #00ff00}");
-  lab1->setFrameStyle(QFrame::Panel | QFrame::Sunken);
-  statusBar()->addWidget(lab1);
+  tx_status_label = new QLabel("Receiving");
+  tx_status_label->setAlignment(Qt::AlignHCenter);
+  tx_status_label->setMinimumSize(QSize(80,18));
+  tx_status_label->setStyleSheet("QLabel{background-color: #00ff00}");
+  tx_status_label->setFrameStyle(QFrame::Panel | QFrame::Sunken);
+  statusBar()->addWidget(tx_status_label);
 
-  lab2 = new QLabel("");
-  lab2->setAlignment(Qt::AlignHCenter);
-  lab2->setMinimumSize(QSize(150,18));
-  lab2->setFrameStyle(QFrame::Panel | QFrame::Sunken);
-  statusBar()->addWidget(lab2);
 
-  lab3 = new QLabel("");
-  lab3->setAlignment(Qt::AlignHCenter);
-  lab3->setMinimumSize(QSize(80,18));
-  lab3->setFrameStyle(QFrame::Panel | QFrame::Sunken);
-  statusBar()->addWidget(lab3);
-}
+  mode_label = new QLabel("");
+  mode_label->setAlignment(Qt::AlignHCenter);
+  mode_label->setMinimumSize(QSize(80,18));
+  mode_label->setFrameStyle(QFrame::Panel | QFrame::Sunken);
+  statusBar()->addWidget(mode_label);
 
-void MainWindow::on_actionExit_triggered()                     //Exit()
-{
-  OnExit();
-}
+  last_tx_label = new QLabel("");
+  last_tx_label->setAlignment(Qt::AlignHCenter);
+  last_tx_label->setMinimumSize(QSize(150,18));
+  last_tx_label->setFrameStyle(QFrame::Panel | QFrame::Sunken);
+  statusBar()->addWidget(last_tx_label);
 
-void MainWindow::closeEvent(QCloseEvent*)
-{
-  OnExit();
+  auto_tx_label = new QLabel("");
+  auto_tx_label->setAlignment(Qt::AlignHCenter);
+  auto_tx_label->setMinimumSize(QSize(150,18));
+  auto_tx_label->setFrameStyle(QFrame::Panel | QFrame::Sunken);
+  statusBar()->addWidget(auto_tx_label);
 }
 
-void MainWindow::OnExit()
+void MainWindow::closeEvent(QCloseEvent * e)
 {
-  g_pWideGraph->saveSettings();
+  m_config.transceiver_offline ();
+  writeSettings ();
+  m_guiTimer.stop ();
+  m_prefixes.reset ();
+  m_shortcuts.reset ();
+  m_mouseCmnds.reset ();
+
   if(m_fname != "") killFile();
   m_killAll=true;
   mem_jt9->detach();
-  QFile quitFile(m_appDir + "/.quit");
+  QFile quitFile {m_config.temp_dir ().absoluteFilePath (".quit")};
   quitFile.open(QIODevice::ReadWrite);
-  QFile lockFile(m_appDir + "/.lock");
-  lockFile.remove();                      // Allow jt9 to terminate
+  QFile {m_config.temp_dir ().absoluteFilePath (".lock")}.remove(); // Allow jt9 to terminate
   bool b=proc_jt9.waitForFinished(1000);
   if(!b) proc_jt9.kill();
   quitFile.remove();
-  qApp->exit(0);                                      // Exit the event loop
+
+  Q_EMIT finished ();
+
+  QMainWindow::closeEvent (e);
 }
 
 void MainWindow::on_stopButton_clicked()                       //stopButton
 {
-  m_monitoring=false;
-  soundInThread.setMonitoring(m_monitoring);
+  monitor (false);
   m_loopall=false;  
 }
 
@@ -1092,48 +1103,54 @@ void MainWindow::msgBox(QString t)                             //msgBox
   msgBox0.exec();
 }
 
-void MainWindow::on_actionOnline_Users_Guide_triggered()      //Display manual
+void MainWindow::on_actionOnline_User_Guide_triggered()      //Display manual
+{
+#if defined (CMAKE_BUILD)
+  QDesktopServices::openUrl (QUrl (PROJECT_MANUAL_DIRECTORY_URL "/" PROJECT_MANUAL));
+#endif
+}
+
+//Display local copy of manual
+void MainWindow::on_actionLocal_User_Guide_triggered()
 {
-  QDesktopServices::openUrl(QUrl(
-  "http://www.physics.princeton.edu/pulsar/K1JT/WSJT-X_Users_Guide_v1.1.pdf",
-                              QUrl::TolerantMode));
+#if defined (CMAKE_BUILD)
+  auto file = m_config.doc_dir ().absoluteFilePath (PROJECT_MANUAL);
+  QDesktopServices::openUrl (QUrl {"file:///" + file});
+#endif
 }
 
 void MainWindow::on_actionWide_Waterfall_triggered()      //Display Waterfalls
 {
-  if(g_pWideGraph==NULL) {
-    g_pWideGraph = new WideGraph(0);
-    g_pWideGraph->setWindowTitle("Wide Graph");
-    g_pWideGraph->setGeometry(m_wideGraphGeom);
-    Qt::WindowFlags flags = Qt::WindowCloseButtonHint |
-        Qt::WindowMinimizeButtonHint;
-    g_pWideGraph->setWindowFlags(flags);
-    connect(g_pWideGraph, SIGNAL(freezeDecode2(int)),this,
-            SLOT(freezeDecode(int)));
-    connect(g_pWideGraph, SIGNAL(f11f12(int)),this,
-            SLOT(bumpFqso(int)));
-    connect(g_pWideGraph, SIGNAL(setXIT2(int)),this,
-            SLOT(setXIT(int)));
-//    connect(g_pWideGraph, SIGNAL(dialFreqChanged(double)),this,
-//            SLOT(dialFreqChanged2(double)));
-  }
-  g_pWideGraph->show();
+  m_wideGraph->show();
+}
+
+void MainWindow::on_actionAstronomical_data_triggered()
+{
+  if (!m_astroWidget)
+    {
+      m_astroWidget.reset (new Astro {m_settings});
+
+      // hook up termination signal
+      connect (this, &MainWindow::finished, m_astroWidget.data (), &Astro::close);
+    }
+  m_astroWidget->showNormal();
 }
 
 void MainWindow::on_actionOpen_triggered()                     //Open File
 {
-  m_monitoring=false;
-  soundInThread.setMonitoring(m_monitoring);
+  monitor (false);
+
   QString fname;
   fname=QFileDialog::getOpenFileName(this, "Open File", m_path,
-                                       "WSJT Files (*.wav)");
+                                     "WSJT Files (*.wav)");
   if(fname != "") {
     m_path=fname;
     int i;
     i=fname.indexOf(".wav") - 11;
     if(i>=0) {
-      lab1->setStyleSheet("QLabel{background-color: #66ff66}");
-      lab1->setText(" " + fname.mid(i,15) + " ");
+      tx_status_label->setStyleSheet("QLabel{background-color: #66ff66}");
+      tx_status_label->setText(" " + fname.mid(i,15) + " ");
+      //      lab1->setText(" " + fname + " ");
     }
     on_stopButton_clicked();
     m_diskData=true;
@@ -1144,10 +1161,12 @@ void MainWindow::on_actionOpen_triggered()                     //Open File
 
 void MainWindow::on_actionOpen_next_in_directory_triggered()   //Open Next
 {
+  monitor (false);
+
   int i,len;
   QFileInfo fi(m_path);
   QStringList list;
-  list= fi.dir().entryList().filter(".wav");
+  list= fi.dir().entryList().filter(".wav",Qt::CaseInsensitive);
   for (i = 0; i < list.size()-1; ++i) {
     if(i==list.size()-2) m_loopall=false;
     len=list.at(i).length();
@@ -1158,8 +1177,8 @@ void MainWindow::on_actionOpen_next_in_directory_triggered()   //Open Next
       int i;
       i=fname.indexOf(".wav") - 11;
       if(i>=0) {
-        lab1->setStyleSheet("QLabel{background-color: #66ff66}");
-        lab1->setText(" " + fname.mid(i,len) + " ");
+        tx_status_label->setStyleSheet("QLabel{background-color: #66ff66}");
+        tx_status_label->setText(" " + fname.mid(i,len) + " ");
       }
       m_diskData=true;
       *future1 = QtConcurrent::run(getfile, fname, m_TRperiod);
@@ -1168,7 +1187,7 @@ void MainWindow::on_actionOpen_next_in_directory_triggered()   //Open Next
     }
   }
 }
-                                                   //Open all remaining files
+//Open all remaining files
 void MainWindow::on_actionDecode_remaining_files_in_directory_triggered()
 {
   m_loopall=true;
@@ -1183,9 +1202,9 @@ void MainWindow::diskDat()                                   //diskDat()
   for(int n=1; n<=m_hsymStop; n++) {              // Do the half-symbol FFTs
     k=(n+1)*kstep;
     jt9com_.npts8=k/8;
-    dataSink(k);
+    dataSink(k * sizeof (jt9com_.d2[0]));
     if(n%10 == 1 or n == m_hsymStop)
-        qApp->processEvents();                   //Keep GUI responsive
+      qApp->processEvents();                   //Keep GUI responsive
   }
 }
 
@@ -1199,11 +1218,11 @@ void MainWindow::on_actionDelete_all_wav_files_in_SaveDir_triggered()
   int i;
   QString fname;
   int ret = QMessageBox::warning(this, "Confirm Delete",
-      "Are you sure you want to delete all *.wav files in\n" +
-       QDir::toNativeSeparators(m_saveDir) + " ?",
-       QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
+                                 "Are you sure you want to delete all *.wav files in\n" +
+                                 QDir::toNativeSeparators(m_config.save_directory ().absolutePath ()) + " ?",
+                                 QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
   if(ret==QMessageBox::Yes) {
-    QDir dir(m_saveDir);
+    QDir dir(m_config.save_directory ());
     QStringList files=dir.entryList(QDir::Files);
     QList<QString>::iterator f;
     for(f=files.begin(); f!=files.end(); ++f) {
@@ -1237,81 +1256,79 @@ void MainWindow::on_actionSave_all_triggered()                //Save All
 
 void MainWindow::on_actionKeyboard_shortcuts_triggered()
 {
-  pShortcuts = new QTextEdit(0);
-  pShortcuts->setReadOnly(true);
-  pShortcuts->setFontPointSize(10);
-  pShortcuts->setWindowTitle("Keyboard Shortcuts");
-  pShortcuts->setGeometry(QRect(45,50,430,460));
-  Qt::WindowFlags flags = Qt::WindowCloseButtonHint |
-      Qt::WindowMinimizeButtonHint;
-  pShortcuts->setWindowFlags(flags);
-  QString shortcuts = m_appDir + "/shortcuts.txt";
-  QFile f(shortcuts);
-  if(!f.open(QIODevice::ReadOnly | QIODevice::Text)) {
-    msgBox("Cannot open " + shortcuts);
-    return;
-  }
-  QTextStream s(&f);
-  QString t;
-  for(int i=0; i<100; i++) {
-    t=s.readLine();
-    pShortcuts->append(t);
-    if(s.atEnd()) break;
-  }
-  pShortcuts->show();
+  if (!m_shortcuts)
+    {
+      QFile f(":/shortcuts.txt");
+      if(!f.open(QIODevice::ReadOnly | QIODevice::Text)) {
+        msgBox("Cannot open \"" + f.fileName () + "\" for reading:"+f.errorString ());
+        return;
+      }
+      m_shortcuts.reset (new QTextEdit);
+      m_shortcuts->setReadOnly(true);
+      m_shortcuts->setFontPointSize(10);
+      m_shortcuts->setWindowTitle(QApplication::applicationName () + " - " + tr ("Keyboard Shortcuts"));
+      m_shortcuts->setGeometry(QRect(45,50,430,460));
+      Qt::WindowFlags flags = Qt::WindowCloseButtonHint |
+        Qt::WindowMinimizeButtonHint;
+      m_shortcuts->setWindowFlags(flags);
+      QTextStream s(&f);
+      QString t;
+      for(int i=0; i<100; i++) {
+        t=s.readLine();
+        m_shortcuts->append(t);
+        if(s.atEnd()) break;
+      }
+    }
+  m_shortcuts->showNormal();
 }
 
 void MainWindow::on_actionSpecial_mouse_commands_triggered()
 {
-  QTextEdit* pMouseCmnds;
-  pMouseCmnds = new QTextEdit(0);
-  pMouseCmnds->setReadOnly(true);
-  pMouseCmnds->setFontPointSize(10);
-  pMouseCmnds->setWindowTitle("Special Mouse Commands");
-  pMouseCmnds->setGeometry(QRect(45,50,440,300));
-  Qt::WindowFlags flags = Qt::WindowCloseButtonHint |
-      Qt::WindowMinimizeButtonHint;
-  pMouseCmnds->setWindowFlags(flags);
-  QString mouseCmnds = m_appDir + "/mouse_commands.txt";
-  QFile f(mouseCmnds);
-  if(!f.open(QIODevice::ReadOnly | QIODevice::Text)) {
-    msgBox("Cannot open " + mouseCmnds);
-    return;
-  }
-  QTextStream s(&f);
-  QString t;
-  for(int i=0; i<100; i++) {
-    t=s.readLine();
-    pMouseCmnds->append(t);
-    if(s.atEnd()) break;
-  }
-  pMouseCmnds->show();
+  if (!m_mouseCmnds)
+    {
+      QFile f(":/mouse_commands.txt");
+      if(!f.open(QIODevice::ReadOnly | QIODevice::Text)) {
+        msgBox("Cannot open \"" + f.fileName () + "\" for reading:" + f.errorString ());
+        return;
+      }
+      m_mouseCmnds.reset (new QTextEdit);
+      m_mouseCmnds->setReadOnly(true);
+      m_mouseCmnds->setFontPointSize(10);
+      m_mouseCmnds->setWindowTitle(QApplication::applicationName () + " - " + tr ("Special Mouse Commands"));
+      m_mouseCmnds->setGeometry(QRect(45,50,440,300));
+      Qt::WindowFlags flags = Qt::WindowCloseButtonHint |
+        Qt::WindowMinimizeButtonHint;
+      m_mouseCmnds->setWindowFlags(flags);
+      QTextStream s(&f);
+      QString t;
+      for(int i=0; i<100; i++) {
+        t=s.readLine();
+        m_mouseCmnds->append(t);
+        if(s.atEnd()) break;
+      }
+    }
+  m_mouseCmnds->showNormal();
 }
 
-void MainWindow::on_DecodeButton_clicked()                    //Decode request
+void MainWindow::on_DecodeButton_clicked (bool /* checked */)	//Decode request
 {
   if(!m_decoderBusy) {
     jt9com_.newdat=0;
     jt9com_.nagain=1;
+    m_blankLine=false; // don't insert the separator again
     decode();
   }
 }
 
 void MainWindow::freezeDecode(int n)                          //freezeDecode()
 {
-  bool ctrl = (n>=100);
-  int i=g_pWideGraph->rxFreq();
-  if(ctrl) {
-    ui->TxFreqSpinBox->setValue(i);
-    g_pWideGraph->setTxFreq(i);
-  }
-  if((n%100)==2) on_DecodeButton_clicked();
+  if((n%100)==2) on_DecodeButton_clicked (true);
 }
 
 void MainWindow::decode()                                       //decode()
 {
   if(!m_dataAvailable) return;
-  ui->DecodeButton->setStyleSheet(m_pbdecoding_style1);
+  ui->DecodeButton->setChecked (true);
   if(jt9com_.newdat==1 && (!m_diskData)) {
     qint64 ms = QDateTime::currentMSecsSinceEpoch() % 86400000;
     int imin=ms/60000;
@@ -1321,24 +1338,22 @@ void MainWindow::decode()                                       //decode()
     jt9com_.nutc=100*ihr + imin;
   }
 
-  jt9com_.nfqso=g_pWideGraph->rxFreq();
+  jt9com_.nfqso=m_wideGraph->rxFreq();
   jt9com_.ndepth=m_ndepth;
   jt9com_.ndiskdat=0;
   if(m_diskData) jt9com_.ndiskdat=1;
-  int nfa=g_pWideGraph->getFmin();
-  int nfb=g_pWideGraph->getFmax();
-  if(m_mode=="JT9") nfa=200;                //decode from 0 to fmax
-  if(m_mode=="JT65") nfa=nfb;               //decode from 0 to fmax
-  jt9com_.nfa=nfa;
-  jt9com_.nfb=nfb;
+  jt9com_.nfa=m_wideGraph->nStartFreq();
+  jt9com_.nfSplit=m_wideGraph->getFmin();
+  jt9com_.nfb=m_wideGraph->getFmax();
   jt9com_.ntol=20;
-  if(jt9com_.nutc < m_nutc0) m_RxLog |= 1;  //Date and Time to all.txt
+  if(jt9com_.nutc < m_nutc0) m_RxLog = 1;       //Date and Time to all.txt
   m_nutc0=jt9com_.nutc;
   jt9com_.ntxmode=9;
   if(m_modeTx=="JT65") jt9com_.ntxmode=65;
   jt9com_.nmode=9;
+  if(m_mode=="JT9W-1") jt9com_.nmode=91;
   if(m_mode=="JT65") jt9com_.nmode=65;
-  if(m_mode=="JT9+JT65") jt9com_.nmode=9+65;
+  if(m_mode=="JT9+JT65") jt9com_.nmode=9+65;  // = 74
   jt9com_.ntrperiod=m_TRperiod;
   m_nsave=0;
   if(m_saveDecoded) m_nsave=2;
@@ -1359,15 +1374,15 @@ void MainWindow::decode()                                       //decode()
   }
   memcpy(to, from, qMin(mem_jt9->size(), size));
 
-  QFile lockFile(m_appDir + "/.lock");       // Allow jt9 to start
-  lockFile.remove();
+  QFile {m_config.temp_dir ().absoluteFilePath (".lock")}.remove (); // Allow jt9 to start
   decodeBusy(true);
 }
 
-void MainWindow::jt9_error()                                     //jt9_error
+void MainWindow::jt9_error (QProcess::ProcessError e)
 {
   if(!m_killAll) {
     msgBox("Error starting or running\n" + m_appDir + "/jt9 -s");
+    qDebug() << e;                           // silence compiler warning
     exit(1);
   }
 }
@@ -1380,157 +1395,117 @@ void MainWindow::readFromStderr()                             //readFromStderr
 
 void MainWindow::readFromStdout()                             //readFromStdout
 {
-  while(proc_jt9.canReadLine()) {
-    QByteArray t=proc_jt9.readLine();
-    if(t.indexOf("<DecodeFinished>") >= 0) {
-      m_bdecoded = (t.mid(23,1).toInt()==1);
-      bool keepFile=m_saveAll or (m_saveDecoded and m_bdecoded);
-      if(!keepFile and !m_diskData) killFileTimer->start(45*1000); //Kill in 45 s
-      jt9com_.nagain=0;
-      jt9com_.ndiskdat=0;
-      QFile lockFile(m_appDir + "/.lock");
-      lockFile.open(QIODevice::ReadWrite);
-      ui->DecodeButton->setStyleSheet("");
-      decodeBusy(false);
-      m_RxLog=0;
-      m_startAnother=m_loopall;
-      m_blankLine=true;
-      return;
-    } else {
-      QFile f("ALL.TXT");
-      f.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append);
-      QTextStream out(&f);
-      if(m_RxLog && 1) {
-        out << QDateTime::currentDateTimeUtc().toString("yyyy-MMM-dd hh:mm")
-            << "  " << m_dialFreq << " MHz  " << m_mode << endl;
-        m_RxLog=0;
-      }
-      int n=t.length();
-      out << t.mid(0,n-2) << endl;
-      f.close();
+  QString band = m_config.bands ()->data (m_config.bands ()->find (m_dialFreq)).toString();
+
+  while(proc_jt9.canReadLine())
+    {
+      QByteArray t=proc_jt9.readLine();
+      if(t.indexOf("<DecodeFinished>") >= 0)
+        {
+          m_bdecoded = (t.mid(23,1).toInt()==1);
+          bool keepFile=m_saveAll or (m_saveDecoded and m_bdecoded);
+          if(!keepFile and !m_diskData) killFileTimer->start(45*1000); //Kill in 45 s
+          jt9com_.nagain=0;
+          jt9com_.ndiskdat=0;
+          QFile {m_config.temp_dir ().absoluteFilePath (".lock")}.open(QIODevice::ReadWrite);
+          ui->DecodeButton->setChecked (false);
+          decodeBusy(false);
+          m_RxLog=0;
+          m_startAnother=m_loopall;
+          m_blankLine=true;
+          return;
+        } else {
+        QFile f {m_dataDir.absoluteFilePath ("ALL.TXT")};
+        if (f.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append))
+          {
+            QTextStream out(&f);
+            if(m_RxLog==1) {
+              out << QDateTime::currentDateTimeUtc().toString("yyyy-MMM-dd hh:mm")
+                  << "  " << (m_dialFreq / 1.e6) << " MHz  " << m_mode << endl;
+              m_RxLog=0;
+            }
+            int n=t.length();
+            out << t.mid(0,n-2) << endl;
+            f.close();
+          }
+        else
+          {
+            msgBox("Cannot open \"" + f.fileName () + "\" for append:" + f.errorString ());
+          }
 
-      QTextCursor cursor;
-      QTextBlockFormat bf;
-      if(m_insertBlank and m_blankLine and jt9com_.nagain==0) {
-        QString bg="#d3d3d3";
-        bf.setBackground(QBrush(QColor(bg)));
-        QString tt="----------------------------------------";
-        QString s = "<table border=0 cellspacing=0 width=100%><tr><td bgcolor=\"" +
-            bg + "\"><pre>" + tt + "</pre></td></tr></table>";
-        cursor = ui->decodedTextBrowser->textCursor();
-        cursor.movePosition(QTextCursor::End);
-        bf = cursor.blockFormat();
-        bf.setBackground(QBrush(QColor(bg)));
-        cursor.insertHtml(s);
-        m_blankLine=false;
-      }
+        if (m_config.insert_blank () && m_blankLine)
+          {
+            QString band;
+            if (QDateTime::currentMSecsSinceEpoch() / 1000 - m_secBandChanged > 50)
+              {
+                auto const& bands_model = m_config.bands ();
+                band = ' ' + bands_model->data (bands_model->find (m_dialFreq + ui->TxFreqSpinBox->value ())).toString ();
+              }
+            ui->decodedTextBrowser->insertLineSpacer (band.rightJustified  (40, '-'));
+            m_blankLine = false;
+          }
 
-      QString bg="white";
-      if(t.indexOf(" CQ ")>0) bg="#66ff66";                          //green
-      if(m_myCall!="" and t.indexOf(" "+m_myCall+" ")>0) bg="#ff6666"; //red
-      bool bQSO=abs(t.mid(14,4).toInt() - g_pWideGraph->rxFreq()) <= 10;
-      QString t1=t.replace("\n","").mid(0,t.length()-4);
-      QString s = "<table border=0 cellspacing=0 width=100%><tr><td bgcolor=\"" +
-          bg + "\"><pre>" + t1 + "</pre></td></tr></table>";
-      bool b65=t1.indexOf("#")==19;
-      if(bQSO) {
-        cursor = ui->decodedTextBrowser2->textCursor();
-        cursor.movePosition(QTextCursor::End);
-        bf = cursor.blockFormat();
-        bf.setBackground(QBrush(QColor(bg)));
-        cursor.insertHtml(s);
-        ui->decodedTextBrowser2->setTextCursor(cursor);
-        m_QSOmsg=t1;
-        if(b65 and m_modeTx!="JT65") on_pbTxMode_clicked();
-        if(!b65 and m_modeTx=="JT65") on_pbTxMode_clicked();
-      }
-
-      if(jt9com_.nagain==0) {
-        if(t.indexOf(" CQ ")>0) bg="#66ff66";                          //green
-        if(m_myCall!="" and t.indexOf(" "+m_myCall+" ")>0) bg="#ff6666"; //red
-        QString s = "<table border=0 cellspacing=0 width=100%><tr><td bgcolor=\"" +
-            bg + "\"><pre>" + t1 + "</pre></td></tr></table>";
-        cursor = ui->decodedTextBrowser->textCursor();
-        cursor.movePosition(QTextCursor::End);
-        bf = cursor.blockFormat();
-        bf.setBackground(QBrush(QColor(bg)));
-        cursor.insertHtml(s);
-        ui->decodedTextBrowser->setTextCursor(cursor);
-      }
-
-      QString msg=t.mid(21);
-      int i1=msg.indexOf("\r");
-      if(i1>0) msg=msg.mid(0,i1-1) + "                      ";
-      bool b=stdmsg_(msg.mid(0,22).toLatin1().constData(),22);
-      QStringList w=msg.split(" ",QString::SkipEmptyParts);
-      if(b and w[0]==m_myCall) {
-        QString tt="";
-        if(w.length()>=3) tt=w[2];
-        bool ok;
-        i1=tt.toInt(&ok);
-        if(ok and i1>=-50 and i1<50) {
-          m_rptRcvd=tt;
-        } else {
-          if(tt.mid(0,1)=="R") {
-            i1=tt.mid(1).toInt(&ok);
-            if(ok and i1>=-50 and i1<50) {
-              m_rptRcvd=tt.mid(1);
-            }
+        DecodedText decodedtext;
+        decodedtext = t.replace("\n",""); //t.replace("\n","").mid(0,t.length()-4);
+
+        // the left band display
+        ui->decodedTextBrowser->displayDecodedText (decodedtext
+                                                    , m_baseCall
+                                                    , m_config.DXCC ()
+                                                    , m_logBook
+                                                    , m_config.color_CQ()
+                                                    , m_config.color_MyCall()
+                                                    , m_config.color_DXCC()
+                                                    , m_config.color_NewCall());
+
+        if (abs(decodedtext.frequencyOffset() - m_wideGraph->rxFreq()) <= 10) // this msg is within 10 hertz of our tuned frequency
+          {
+            // the right QSO window
+            ui->decodedTextBrowser2->displayDecodedText(decodedtext
+                                                        , m_baseCall
+                                                        , false
+                                                        , m_logBook
+                                                        , m_config.color_CQ()
+                                                        , m_config.color_MyCall()
+                                                        , m_config.color_DXCC()
+                                                        , m_config.color_NewCall());
+
+            bool b65=decodedtext.isJT65();
+            if(b65 and m_modeTx!="JT65") on_pbTxMode_clicked();
+            if(!b65 and m_modeTx=="JT65") on_pbTxMode_clicked();
+            m_QSOText=decodedtext;
           }
-        }
-      }
 
-      int nsec=QDateTime::currentMSecsSinceEpoch()/1000-m_secBandChanged;
-      bool okToPost=(nsec>50);
-      QString msgmode="JT9";
-      if(b65) msgmode="JT65";
-      i1=msg.indexOf(" ");
-      QString c2=msg.mid(i1+1);
-      int i2=c2.indexOf(" ");
-      QString g2=c2.mid(i2+1,4);
-      c2=c2.mid(0,i2);
-      QString remote="call," + c2 + ",";
-      if(gridOK(g2)) remote += "gridsquare," + g2 + ",";
-      int nHz=t.mid(14,4).toInt();
-      uint nfreq=1000000.0*m_dialFreq + nHz + 0.5;
-      remote += "freq," + QString::number(nfreq);
-      int nsnr=t.mid(5,3).toInt();
-      remote += ",mode," + msgmode + ",snr," + QString::number(nsnr) + ",,";
-      wchar_t tremote[256];
-      remote.toWCharArray(tremote);
-
-#ifdef WIN32
-      if(m_pskReporterInit and b and !m_diskData and okToPost) {
-
-        QString local="station_callsign#" + m_myCall + "#" +
-            "my_gridsquare#" + m_myGrid + "#";
-        if(m_pskAntenna!="") local += "my_antenna#" + m_pskAntenna + "#";
-        local += "programid#WSJT-X#programversion#" + rev.mid(6,4) + "##";
-        wchar_t tlocal[256];
-        local.toWCharArray(tlocal);
-
-        int flags=REPORTER_SOURCE_AUTOMATIC;
-        rc=ReporterSeenCallsign(tremote,tlocal,flags);
-        if(rc!=0) {
-          ReporterGetInformation(buffer,256);
-        }
-        rc=ReporterTickle();
-        if(rc!=0) {
-          rc=ReporterGetInformation(buffer,256);
-        }
-      }
-#else
-      if(m_pskReporter and b and !m_diskData and okToPost) {
-        QString freq = QString::number(nfreq);
-        QString snr= QString::number(nsnr);
-        if(gridOK(g2)) {
-          psk_Reporter->addRemoteStation(c2,g2,freq,msgmode,snr,
-                   QString::number(QDateTime::currentDateTime().toTime_t()));
-        }
+        postDecode (true, decodedtext.string ());
+
+        // find and extract any report for myCall
+        bool stdMsg = decodedtext.report(m_baseCall
+                                         , Radio::base_callsign (ui->dxCallEntry-> text ().toUpper ().trimmed ())
+                                         , /*mod*/m_rptRcvd);
+
+        // extract details and send to PSKreporter
+        int nsec=QDateTime::currentMSecsSinceEpoch()/1000-m_secBandChanged;
+        bool okToPost=(nsec>50);
+        if(m_config.spot_to_psk_reporter () and stdMsg and !m_diskData and okToPost)
+          {
+            QString msgmode="JT9";
+            if (decodedtext.isJT65())
+              msgmode="JT65";
+
+            QString deCall;
+            QString grid;
+            decodedtext.deCallAndGrid(/*out*/deCall,grid);
+            int audioFrequency = decodedtext.frequencyOffset();
+            int snr = decodedtext.snr();
+            Frequency frequency = m_dialFreq + audioFrequency;
+
+            pskSetLocal ();
+            if(gridOK(grid))
+              psk_Reporter->addRemoteStation(deCall,grid,QString::number(frequency),msgmode,QString::number(snr),
+                                             QString::number(QDateTime::currentDateTime().toTime_t()));
+          }
       }
-#endif
     }
-  }
 }
 
 void MainWindow::killFile()
@@ -1546,17 +1521,43 @@ void MainWindow::on_EraseButton_clicked()                          //Erase
 {
   qint64 ms=QDateTime::currentMSecsSinceEpoch();
   ui->decodedTextBrowser2->clear();
-  m_QSOmsg="";
+  m_QSOText.clear();
   if((ms-m_msErase)<500) {
-      ui->decodedTextBrowser->clear();
-      QFile f(m_appDir + "/decoded.txt");
-      if(f.exists()) f.remove();
+    ui->decodedTextBrowser->clear();
+    m_messageClient->clear_decodes ();
+    QFile f(m_config.temp_dir ().absoluteFilePath ("decoded.txt"));
+    if(f.exists()) f.remove();
   }
   m_msErase=ms;
 }
 
 void MainWindow::decodeBusy(bool b)                             //decodeBusy()
 {
+  bool showProgress = false;
+  if (b && m_firstDecode < 65 && ("JT65" == m_mode || "JT9+JT65" == m_mode))
+    {
+      m_firstDecode += 65;
+      if ("JT9+JT65" == m_mode) m_firstDecode = 65 + 9;
+      showProgress = true;
+    }
+  if (b && m_firstDecode != 9 && m_firstDecode != 65 + 9 && ("JT9" == m_mode || "JT9W-1" == m_mode))
+    {
+      m_firstDecode += 9;
+      showProgress = true;
+    }
+  if (showProgress)
+    {
+      // this sequence is needed to create an indeterminate progress
+      // bar
+      m_optimizingProgress.setRange (0, 1);
+      m_optimizingProgress.setValue (0);
+      m_optimizingProgress.setRange (0, 0);
+    }
+  if (!b)
+    {
+      m_optimizingProgress.reset ();
+    }
+
   m_decoderBusy=b;
   ui->DecodeButton->setEnabled(!b);
   ui->actionOpen->setEnabled(!b);
@@ -1572,10 +1573,7 @@ void MainWindow::guiUpdate()
   static char message[29];
   static char msgsent[29];
   static int nsendingsh=0;
-  static int giptt00=-1;
-  static int gcomport00=-1;
   static double onAirFreq0=0.0;
-  int ret=0;
   QString rt;
 
   double tx1=0.0;
@@ -1592,335 +1590,336 @@ void MainWindow::guiUpdate()
   double t2p=fmod(tsec,2*m_TRperiod);
   bool bTxTime = ((t2p >= tx1) and (t2p < tx2)) or m_tune;
 
-  if(m_auto or m_tune) {
-    QFile f("txboth");
+  if(m_transmitting || m_auto || m_tune) {
+
+    QFile f(m_config.temp_dir ().absoluteFilePath ("txboth"));
     if(f.exists() and fmod(tsec,m_TRperiod) < (1.0 + 85.0*m_nsps/12000.0)) {
       bTxTime=true;
     }
 
-    double onAirFreq=m_dialFreq+1.e-6*m_txFreq;
-    if(onAirFreq>10.139900 and onAirFreq<10.140320) {
-      bTxTime=false;
-      if(m_tune) on_tuneButton_clicked();
-      if(onAirFreq!=onAirFreq0) {
-        onAirFreq0=onAirFreq;
-        on_autoButton_clicked();
-        QString t="Please choose another Tx frequency.\n";
-        t+="WSJT-X will not knowingly transmit\n";
-        t+="in the WSPR sub-band on 30 m.";
-        msgBox0.setText(t);
-        msgBox0.show();
+    Frequency onAirFreq = m_dialFreq + ui->TxFreqSpinBox->value ();
+    if (onAirFreq > 10139900 && onAirFreq < 10140320)
+      {
+        bTxTime=false;
+        if (m_tune)
+          {
+            stop_tuning ();
+          }
+	
+        if (m_auto)
+          {
+            auto_tx_mode (false);
+          }
+
+        if(onAirFreq!=onAirFreq0)
+          {
+            onAirFreq0=onAirFreq;
+            QString t="Please choose another Tx frequency.\n";
+            t+="WSJT-X will not knowingly transmit\n";
+            t+="in the WSPR sub-band on 30 m.";
+            msgBox(t);
+          }
       }
-    }
 
     float fTR=float((nsec%m_TRperiod))/m_TRperiod;
-    if(g_iptt==0 and ((bTxTime and !btxMute and fTR<0.4) or m_tune )) {
+    if(g_iptt==0 and ((bTxTime and fTR<0.4) or m_tune )) {
       icw[0]=m_ncw;
-
-//Raise PTT
-      if(m_catEnabled and m_bRigOpen and  m_pttMethodIndex==0) {
-        g_iptt=1;
-        if(m_pttData) ret=rig->setPTT(RIG_PTT_ON_DATA, RIG_VFO_CURR);
-        if(!m_pttData) ret=rig->setPTT(RIG_PTT_ON_MIC, RIG_VFO_CURR);
-        if(ret!=RIG_OK) {
-          rt.sprintf("CAT control PTT failed:  %d",ret);
-          msgBox(rt);
-        }
-
-      }
-
-      if(m_pttMethodIndex==1 or m_pttMethodIndex==2) {  //DTR or RTS
-        ptt(m_pttPort,1,&g_iptt,&g_COMportOpen);
-      }
-      if(m_pttMethodIndex==3) {                    //VOX
-        g_iptt=1;
-      }
+      g_iptt = 1;
+      setXIT (ui->TxFreqSpinBox->value ()); // ensure correct offset
+      Q_EMIT m_config.transceiver_ptt (true);
       ptt1Timer->start(200);                       //Sequencer delay
     }
-    if(!bTxTime || btxMute) {
-      btxok=false;
+
+    if(!bTxTime) {
+      m_btxok=false;
     }
   }
 
-// Calculate Tx tones when needed
+  // Calculate Tx tones when needed
   if((g_iptt==1 && iptt0==0) || m_restart) {
     QByteArray ba;
     if(m_ntx == 1) ba=ui->tx1->text().toLocal8Bit();
     if(m_ntx == 2) ba=ui->tx2->text().toLocal8Bit();
     if(m_ntx == 3) ba=ui->tx3->text().toLocal8Bit();
     if(m_ntx == 4) ba=ui->tx4->text().toLocal8Bit();
-    if(m_ntx == 5) ba=ui->tx5->text().toLocal8Bit();
+    if(m_ntx == 5) ba=ui->tx5->currentText().toLocal8Bit();
     if(m_ntx == 6) ba=ui->tx6->text().toLocal8Bit();
     if(m_ntx == 7) ba=ui->genMsg->text().toLocal8Bit();
-    if(m_ntx == 8) ba=ui->freeTextMsg->text().toLocal8Bit();
+    if(m_ntx == 8) ba=ui->freeTextMsg->currentText().toLocal8Bit();
 
     ba2msg(ba,message);
-//    ba2msg(ba,msgsent);
+    //    ba2msg(ba,msgsent);
     int len1=22;
-    int ichk=0,itext=0;
-    if(m_modeTx=="JT9") genjt9_(message,&ichk,msgsent,itone,&itext,len1,len1);
-    if(m_modeTx=="JT65") gen65_(message,&ichk,msgsent,itone,&itext,len1,len1);
+    int ichk=0;
+    if (m_lastMessageSent != m_currentMessage
+        || m_lastMessageType != m_currentMessageType)
+      {
+        m_lastMessageSent = m_currentMessage;
+        m_lastMessageType = m_currentMessageType;
+      }
+    m_currentMessageType = 0;
+    if(m_modeTx=="JT9") genjt9_(message
+                                , &ichk
+                                , msgsent
+                                , const_cast<int *> (itone)
+                                , &m_currentMessageType
+                                , len1
+                                , len1);
+    if(m_modeTx=="JT65") gen65_(message
+                                , &ichk
+                                , msgsent
+                                , const_cast<int *> (itone)
+                                , &m_currentMessageType
+                                , len1
+                                , len1);
     msgsent[22]=0;
-    QString t=QString::fromLatin1(msgsent);
-    if(m_tune) t="TUNE";
-    lab2->setText("Last Tx:  " + t);
+    m_currentMessage = QString::fromLatin1(msgsent);
+    if (m_tune)
+      {
+        m_currentMessage = "TUNE";
+        m_currentMessageType = -1;
+      }
+    last_tx_label->setText("Last Tx:  " + m_currentMessage);
     if(m_restart) {
-      QFile f("ALL.TXT");
-      f.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append);
-      QTextStream out(&f);
-      out << QDateTime::currentDateTimeUtc().toString("hhmm")
-          << "  Transmitting " << m_dialFreq << " MHz  " << m_modeTx
-          << ":  " << t << endl;
-      f.close();
-      if(m_tx2QSO) displayTxMsg(t);
+      QFile f {m_dataDir.absoluteFilePath ("ALL.TXT")};
+      if (f.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append))
+        {
+          QTextStream out(&f);
+          out << QDateTime::currentDateTimeUtc().toString("hhmm")
+              << "  Transmitting " << (m_dialFreq / 1.e6) << " MHz  " << m_modeTx
+              << ":  " << m_currentMessage << endl;
+          f.close();
+        }
+      else
+        {
+          msgBox("Cannot open \"" + f.fileName () + "\" for append:" + f.errorString ());
+        }
+      if (m_config.TX_messages ())
+        {
+          ui->decodedTextBrowser2->displayTransmittedText(m_currentMessage,m_modeTx,
+                                ui->TxFreqSpinBox->value(),m_config.color_TxMsg());
+        }
     }
 
-    QStringList w=t.split(" ",QString::SkipEmptyParts);
-    t="";
-    if(w.length()==3) t=w[2];
-    icw[0]=0;
-    m_sent73=(t=="73" or itext!=0);
-    if(m_sent73)  {
-      if(m_After73)  icw[0]=m_ncw;
-      if(m_promptToLog and !m_tune) logQSOTimer->start(200);
-    }
+    auto t2 = QDateTime::currentDateTimeUtc ().toString ("hhmm");
+    icw[0] = 0;
+    auto msg_parts = m_currentMessage.split (' ', QString::SkipEmptyParts);
+    auto is_73 = message_is_73 (m_currentMessageType, msg_parts);
+    m_sentFirst73 = is_73
+      && !message_is_73 (m_lastMessageType, m_lastMessageSent.split (' ', QString::SkipEmptyParts));
+    if (m_sentFirst73)
+      {
+        m_qsoStop=t2;
+        if(m_config.id_after_73 ())
+          {
+            icw[0] = m_ncw;
+          }
+        if (m_config.prompt_to_log () && !m_tune)
+          {
+            logQSOTimer->start (0);
+          }
+      }
+    if (is_73 && m_config.disable_TX_on_73 ())
+      {
+        auto_tx_mode (false);
+      }
 
-    if(m_idInt>0) {
+    if(m_config.id_interval () >0) {
       int nmin=(m_sec0-m_secID)/60;
-      if(nmin >= m_idInt) {
+      if(nmin >= m_config.id_interval ()) {
         icw[0]=m_ncw;
         m_secID=m_sec0;
       }
     }
 
-    QString t2=QDateTime::currentDateTimeUtc().toString("hhmm");
-    if(itext==0 and w.length()>=3 and w[1]==m_myCall) {
-      int i1;
-      bool ok;
-      i1=t.toInt(&ok);
-      if(ok and i1>=-50 and i1<50) {
-        m_rptSent=t;
-        m_qsoStart=t2;
-      } else {
-        if(t.mid(0,1)=="R") {
-          i1=t.mid(1).toInt(&ok);
-          if(ok and i1>=-50 and i1<50) {
-            m_rptSent=t.mid(1);
-            m_qsoStart=t2;
+    if (m_currentMessageType < 6 && msg_parts.length() >= 3
+       && (msg_parts[1] == m_config.my_callsign () || msg_parts[1] == m_baseCall))
+      {
+        int i1;
+        bool ok;
+        i1 = msg_parts[2].toInt(&ok);
+        if(ok and i1>=-50 and i1<50)
+          {
+            m_rptSent = msg_parts[2];
+            m_qsoStart = t2;
+          }
+        else
+          {
+            if (msg_parts[2].mid (0, 1) == "R")
+              {
+                i1 = msg_parts[2].mid (1).toInt (&ok);
+                if (ok and i1 >= -50 and i1 < 50)
+                  {
+                    m_rptSent = msg_parts[2].mid (1);
+                    m_qsoStart = t2;
+                  }
+              }
           }
-        }
       }
-    }
-    if(itext==1 or (w.length()==3 and w[2]=="73")) m_qsoStop=t2;
     m_restart=false;
   }
+  else
+    {
+      if (!m_auto && m_sentFirst73)
+        {
+          m_sentFirst73 = false;
+          if (1 == ui->tabWidget->currentIndex())
+            {
+              ui->genMsg->setText(ui->tx6->text());
+              m_ntx=7;
+              ui->rbGenMsg->setChecked(true);
+            }
+          else
+            {
+              m_ntx=6;
+              ui->txrb6->setChecked(true);
+            }
+        }
+    }
+
+  if (g_iptt == 1 && iptt0 == 0)
+    {
+      QString t=QString::fromLatin1(msgsent);
+      if(t==m_msgSent0)
+        {
+          m_repeatMsg++;
+        }
+      else
+        {
+          m_repeatMsg=0;
+          m_msgSent0=t;
+        }
 
+      if(!m_tune)
+        {
+          QFile f {m_dataDir.absoluteFilePath ("ALL.TXT")};
+          if (f.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append))
+            {
+              QTextStream out(&f);
+              out << QDateTime::currentDateTimeUtc().toString("hhmm")
+                  << "  Transmitting " << (m_dialFreq / 1.e6) << " MHz  " << m_modeTx
+                  << ":  " << m_currentMessage << endl;
+              f.close();
+            }
+          else
+            {
+              msgBox("Cannot open \"" + f.fileName () + "\" for append:" + f.errorString ());
+            }
+        }
 
-// If PTT was just raised, start a countdown for raising TxOK:
-// NB: could be better implemented with a timer
-  if(g_iptt == 1 && iptt0 == 0) {
-      nc1=-9;    // TxDelay = 0.8 s
-  }
-  if(nc1 <= 0) {
-      nc1++;
-  }
-  if(nc1 == 0) {
-    QString t=QString::fromLatin1(msgsent);
-    if(t==m_msgSent0) {
-      m_repeatMsg++;
-    } else {
-      m_repeatMsg=0;
-      m_msgSent0=t;
-    }
+      if (m_config.TX_messages () && !m_tune)
+        {
+          ui->decodedTextBrowser2->displayTransmittedText(t,m_modeTx,
+                             ui->TxFreqSpinBox->value(),m_config.color_TxMsg());
+        }
 
-    signalMeter->setValue(0);
-    m_monitoring=false;
-    soundInThread.setMonitoring(false);
-    btxok=true;
-    m_transmitting=true;
-    ui->pbTxMode->setEnabled(false);
-    if(!m_tune) {
-      QFile f("ALL.TXT");
-      f.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append);
-      QTextStream out(&f);
-      out << QDateTime::currentDateTimeUtc().toString("hhmm")
-          << "  Transmitting " << m_dialFreq << " MHz  " << m_modeTx
-          << ":  " << t << endl;
-      f.close();
+      m_transmitting = true;
+      transmitDisplay (true);
+      m_messageClient->status_update (m_dialFreq, m_mode, m_hisCall, QString::number (ui->rptSpinBox->value ()), m_modeTx, ui->autoButton->isChecked (), m_transmitting);
     }
-    if(m_tx2QSO and !m_tune) displayTxMsg(t);
-  }
 
-  if(!btxok && btxok0 && g_iptt==1) stopTx();
+  if(!m_btxok && btxok0 && g_iptt==1) stopTx();
 
-/*
-// If btxok was just lowered, start a countdown for lowering PTT
-  if(!btxok && btxok0 && g_iptt==1) nc0=-11;  //RxDelay = 1.0 s
+  /*
+  // If m_btxok was just lowered, start a countdown for lowering PTT
+  if(!m_btxok && btxok0 && g_iptt==1) nc0=-11;  //RxDelay = 1.0 s
   if(nc0 <= 0) {
-    nc0++;
-  }
-*/
-
-  if(m_monitoring) {
-    ui->monitorButton->setStyleSheet(m_pbmonitor_style);
-  } else {
-    ui->monitorButton->setStyleSheet("");
+  nc0++;
   }
+  */
 
   if(m_startAnother) {
     m_startAnother=false;
     on_actionOpen_next_in_directory_triggered();
   }
 
-  if(m_catEnabled and !m_bRigOpen) {
-    rigOpen();
-  }
-
   if(nsec != m_sec0) {                                     //Once per second
     QDateTime t = QDateTime::currentDateTimeUtc();
+    int fQSO=125;
+    if(m_astroWidget) m_astroWidget->astroUpdate(t, m_config.my_grid (), m_hisGrid, fQSO,
+                                                 m_setftx, ui->TxFreqSpinBox->value ());
+
     if(m_transmitting) {
       if(nsendingsh==1) {
-        lab1->setStyleSheet("QLabel{background-color: #66ffff}");
+        tx_status_label->setStyleSheet("QLabel{background-color: #66ffff}");
       } else if(nsendingsh==-1) {
-        lab1->setStyleSheet("QLabel{background-color: #ffccff}");
+        tx_status_label->setStyleSheet("QLabel{background-color: #ffccff}");
       } else {
-        lab1->setStyleSheet("QLabel{background-color: #ffff33}");
+        tx_status_label->setStyleSheet("QLabel{background-color: #ffff33}");
       }
       if(m_tune) {
-        lab1->setText("Tx: TUNE");
+        tx_status_label->setText("Tx: TUNE");
       } else {
-          char s[37];
-          sprintf(s,"Tx: %s",msgsent);
-          lab1->setText(s);
+        char s[37];
+        sprintf(s,"Tx: %s",msgsent);
+        tx_status_label->setText(s);
       }
     } else if(m_monitoring) {
-      lab1->setStyleSheet("QLabel{background-color: #00ff00}");
-      lab1->setText("Receiving ");
+      tx_status_label->setStyleSheet("QLabel{background-color: #00ff00}");
+      tx_status_label->setText("Receiving ");
     } else if (!m_diskData) {
-      lab1->setStyleSheet("");
-      lab1->setText("");
+      tx_status_label->setStyleSheet("");
+      tx_status_label->setText("");
     }
 
     m_setftx=0;
     QString utc = t.date().toString("yyyy MMM dd") + "\n " +
-            t.time().toString() + " ";
+      t.time().toString() + " ";
     ui->labUTC->setText(utc);
     if(!m_monitoring and !m_diskData) {
       signalMeter->setValue(0);
     }
 
-    if(m_catEnabled and m_poll>0 and (nsec%m_poll)==0 and !m_decoderBusy) {
-      double fMHz;
-      if(m_dontReadFreq) {
-        m_dontReadFreq=false;
-      } else if(!m_transmitting) {
-        for(int iter=0; iter<3; iter++) {
-          fMHz=rig->getFreq(RIG_VFO_CURR)/1000000.0;
-          if(fMHz<0.0 and iter>=2) {
-            rt.sprintf("Rig control error %d\nFailed to read frequency.",
-                       int(1000000.0*fMHz));
-            msgBox(rt);
-            m_catEnabled=false;
-            ui->readFreq->setStyleSheet("QPushButton{background-color: red; \
-                                    border-width: 0px; border-radius: 5px;}");
-        }
-      }
-        int ndiff=1000000.0*(fMHz-m_dialFreq);
-        if(ndiff!=0) dialFreqChanged2(fMHz);
-      }
-    }
-
     m_sec0=nsec;
   }
 
-  if(g_iptt!=giptt00 or g_COMportOpen!=gcomport00) {
-    giptt00=g_iptt;
-    gcomport00=g_COMportOpen;
-  }
-
   iptt0=g_iptt;
-  btxok0=btxok;
+  btxok0=m_btxok;
 }               //End of GUIupdate
 
-void MainWindow::displayTxMsg(QString t)
-{
-      QString bg="yellow";
-      QTextBlockFormat bf;
-      QTextCursor cursor;
-      QString t1=" @ ";
-      if(m_modeTx=="JT65") t1=" # ";
-      QString t2;
-      t2.sprintf("%4d",m_txFreq);
-      t=QDateTime::currentDateTimeUtc().toString("hhmm") + \
-          "  Tx      " + t2 + t1 + t;
-      QString s = "<table border=0 cellspacing=0 width=100%><tr><td bgcolor=\"" +
-          bg + "\"><pre>" + t + "</pre></td></tr></table>";
-      cursor = ui->decodedTextBrowser2->textCursor();
-      cursor.movePosition(QTextCursor::End);
-      bf = cursor.blockFormat();
-      bf.setBackground(QBrush(QColor(bg)));
-      cursor.insertHtml(s);
-      ui->decodedTextBrowser2->setTextCursor(cursor);
-}
 
 void MainWindow::startTx2()
 {
-  if(!soundOutThread.isRunning()) {
-    QString t=ui->tx6->text();
-    double snr=t.mid(1,5).toDouble();
+  if (!m_modulator.isActive ()) {
+    double fSpread=0.0;
+    double snr=99.0;
+    QString t=ui->tx5->currentText();
+    if(t.mid(0,1)=="#") fSpread=t.mid(1,5).toDouble();
+    m_modulator.setSpread(fSpread);
+    t=ui->tx6->text();
+    if(t.mid(0,1)=="#") snr=t.mid(1,5).toDouble();
     if(snr>0.0 or snr < -50.0) snr=99.0;
-    soundOutThread.setTxSNR(snr);
-    soundOutThread.m_modeTx=m_modeTx;
-    soundOutThread.start(QThread::HighestPriority);
+    transmit (snr);
     signalMeter->setValue(0);
-    m_monitoring=false;
-    soundInThread.setMonitoring(false);
-    btxok=true;
-    m_transmitting=true;
-    ui->pbTxMode->setEnabled(false);
   }
 }
 
 void MainWindow::stopTx()
 {
-  if (soundOutThread.isRunning()) {
-    soundOutThread.quitExecution=true;
-    soundOutThread.wait(3000);
-  }
-  m_transmitting=false;
-  ui->pbTxMode->setEnabled(true);
+  Q_EMIT endTransmitMessage ();
+  m_btxok = false;
+  m_transmitting = false;
   g_iptt=0;
-  lab1->setStyleSheet("");
-  lab1->setText("");
+  tx_status_label->setStyleSheet("");
+  tx_status_label->setText("");
   ptt0Timer->start(200);                       //Sequencer delay
-  m_monitoring=true;
-  soundInThread.setMonitoring(true);
+  monitor (true);
+  m_messageClient->status_update (m_dialFreq, m_mode, m_hisCall, QString::number (ui->rptSpinBox->value ()), m_modeTx, ui->autoButton->isChecked (), m_transmitting);
 }
 
 void MainWindow::stopTx2()
 {
-  int ret=0;
   QString rt;
 
-//Lower PTT
-  if(m_catEnabled and m_bRigOpen and  m_pttMethodIndex==0) {
-    ret=rig->setPTT(RIG_PTT_OFF, RIG_VFO_CURR);  //CAT control for PTT=0
-    if(ret!=RIG_OK) {
-      rt.sprintf("CAT control PTT failed:  %d",ret);
-      msgBox(rt);
-    }
-  }
-  if(m_pttMethodIndex==1 or m_pttMethodIndex==2) {
-    ptt(m_pttPort,0,&g_iptt,&g_COMportOpen);
-  }
-  if(m_73TxDisable and m_sent73) on_stopTxButton_clicked();
+  //Lower PTT
+  Q_EMIT m_config.transceiver_ptt (false);
 
-  if(m_runaway and m_repeatMsg>m_watchdogLimit) {
-    on_stopTxButton_clicked();
-    msgBox0.setText("Runaway Tx watchdog");
-    msgBox0.show();
-    m_repeatMsg=0;
-  }
+  if (m_config.watchdog () && m_repeatMsg>=m_watchdogLimit-1)
+    {
+      on_stopTxButton_clicked();
+      msgBox("Runaway Tx watchdog");
+      m_repeatMsg=0;
+    }
 }
 
 void MainWindow::ba2msg(QByteArray ba, char message[])             //ba2msg()
@@ -1950,47 +1949,46 @@ void MainWindow::on_txb1_clicked()                                //txb1
 {
   m_ntx=1;
   ui->txrb1->setChecked(true);
-  m_restart=true;
+  if (m_transmitting) m_restart=true;
 }
 
 void MainWindow::on_txb2_clicked()                                //txb2
 {
   m_ntx=2;
   ui->txrb2->setChecked(true);
-  m_restart=true;
+  if (m_transmitting) m_restart=true;
 }
 
 void MainWindow::on_txb3_clicked()                                //txb3
 {
   m_ntx=3;
   ui->txrb3->setChecked(true);
-  m_restart=true;
+  if (m_transmitting) m_restart=true;
 }
 
 void MainWindow::on_txb4_clicked()                                //txb4
 {
   m_ntx=4;
   ui->txrb4->setChecked(true);
-  m_restart=true;
+  if (m_transmitting) m_restart=true;
 }
 
 void MainWindow::on_txb5_clicked()                                //txb5
 {
   m_ntx=5;
   ui->txrb5->setChecked(true);
-  m_restart=true;
+  if (m_transmitting) m_restart=true;
 }
 
 void MainWindow::on_txb6_clicked()                                //txb6
 {
   m_ntx=6;
   ui->txrb6->setChecked(true);
-  m_restart=true;
+  if (m_transmitting) m_restart=true;
 }
 
 void MainWindow::doubleClickOnCall2(bool shift, bool ctrl)
 {
-
   m_decodedText2=true;
   doubleClickOnCall(shift,ctrl);
   m_decodedText2=false;
@@ -2002,153 +2000,254 @@ void MainWindow::doubleClickOnCall(bool shift, bool ctrl)
   if(!m_decodedText2) cursor=ui->decodedTextBrowser2->textCursor();
   if(m_decodedText2) cursor=ui->decodedTextBrowser->textCursor();
   cursor.select(QTextCursor::LineUnderCursor);
-  int i2=cursor.position();
-  if(shift and i2==-9999) return;        //Silence compiler warning
+  int position {cursor.position()};
+  if(shift && position==-9999) return;        //Silence compiler warning
 
-  QString t;
-  if(!m_decodedText2) t= ui->decodedTextBrowser2->toPlainText(); //Full contents
-  if(m_decodedText2) t= ui->decodedTextBrowser->toPlainText();
+  QString messages;
+  if(!m_decodedText2) messages= ui->decodedTextBrowser2->toPlainText();
+  //Full contents
+  if(m_decodedText2) messages= ui->decodedTextBrowser->toPlainText();
+
+  processMessage(messages, position, ctrl);
+}
 
-  QString t1 = t.mid(0,i2);              //contents up to \n on selected line
+void MainWindow::processMessage(QString const& messages, int position, bool ctrl)
+{
+  QString t1 = messages.mid(0,position);              //contents up to \n on selected line
   int i1=t1.lastIndexOf("\n") + 1;       //points to first char of line
-  QString t2 = t1.mid(i1,i2-i1);         //selected line
-//  if(t2.indexOf("Tx")==6) return;        //Ignore Tx line
-  int i4=t.mid(i1).length();
-  if(i4>55) i4=55;
-  QString t3=t.mid(i1,i4);
-  int i5=t3.indexOf(" CQ DX ");
-  if(i5>0) t3=t3.mid(0,i5+3) + "_" + t3.mid(i5+4);  //Make it "CQ_DX" (one word)
-  QStringList t4=t3.split(" ",QString::SkipEmptyParts);
-  if(t4.length() <5) return;             //Skip the rest if no decoded text
-
-  int i9=m_QSOmsg.indexOf(t2);
-  if(i9<0 and t2.indexOf("Tx")==-1) {
-    QString bg="white";
-    if(t2.indexOf(" CQ ")>0) bg="#66ff66";                           //green
-    if(m_myCall!="" and t2.indexOf(" "+m_myCall+" ")>0) bg="#ff6666"; //red
-    QTextBlockFormat bf;
-    QString s = "<table border=0 cellspacing=0 width=100%><tr><td bgcolor=\"" +
-        bg + "\"><pre>" + t2 + "</pre></td></tr></table>";
-    cursor = ui->decodedTextBrowser2->textCursor();
-    cursor.movePosition(QTextCursor::End);
-    bf = cursor.blockFormat();
-    bf.setBackground(QBrush(QColor(bg)));
-    cursor.insertHtml(s);
-    ui->decodedTextBrowser2->setTextCursor(cursor);
-    m_QSOmsg=t2;
-  }
+  DecodedText decodedtext;
+  decodedtext = messages.mid(i1,position-i1);         //selected line
+
+  if (decodedtext.indexOf(" CQ ") > 0)
+    {
+      // TODO this magic 36 characters is also referenced in DisplayText::_appendDXCCWorkedB4()
+      auto eom_pos = decodedtext.string ().indexOf (' ', 35);
+      if (eom_pos < 35) eom_pos = decodedtext.string ().size () - 1; // we always want at least the characters
+                            // to position 35
+      decodedtext = decodedtext.string ().left (eom_pos + 1);  // remove DXCC entity and worked B4 status. TODO need a better way to do this
+    }
 
-  int nfreq=t4.at(3).toInt();
-  if(t4.at(1)=="Tx") nfreq=t4.at(2).toInt();
-  g_pWideGraph->setRxFreq(nfreq);                      //Set Rx freq
-  if(t4.at(1)=="Tx") {
-    if(ctrl) ui->TxFreqSpinBox->setValue(nfreq);       //Set Tx freq
-    return;
-  }
-  if(t4.at(4)=="@") {
-    m_modeTx="JT9";
-    ui->pbTxMode->setText("Tx JT9  @");
-    g_pWideGraph->setModeTx(m_modeTx);
-  }
-  if(t4.at(4)=="#") {
-    m_modeTx="JT65";
-    ui->pbTxMode->setText("Tx JT65  #");
-    g_pWideGraph->setModeTx(m_modeTx);
-  }
-  QString firstcall=t4.at(5);
+
+  //  if(decodedtext.indexOf("Tx")==6) return;        //Ignore Tx line
+  // int i4=t.mid(i1).length();
+  // if(i4>55) i4=55;
+  // QString t3=t.mid(i1,i4);
+  auto t3 = decodedtext.string ();
+  auto t4 = t3.replace (" CQ DX ", " CQ_DX ").split (" ", QString::SkipEmptyParts);
+  if(t4.size () < 6) return;             //Skip the rest if no decoded text
+
+  QString hiscall;
+  QString hisgrid;
+  decodedtext.deCallAndGrid(/*out*/hiscall,hisgrid);
+  if (!Radio::is_callsign (hiscall) // not interested if not from QSO partner
+      && !(t4.size () == 7          // unless it is of the form
+           && (t4.at (5) == m_baseCall // "<our-call> 73"
+               || t4.at (5).startsWith (m_baseCall + '/')
+               || t4.at (5).endsWith ('/' + m_baseCall))
+           && t4.at (6) == "73"))
+    {
+      qDebug () << "Not processing message - hiscall:" << hiscall << "hisgrid:" << hisgrid;
+      return;
+    }
+
+  // only allow automatic mode changes when not transmitting
+  if (!m_transmitting)
+    {
+      if (decodedtext.isJT9())
+        {
+          m_modeTx="JT9";
+          ui->pbTxMode->setText("Tx JT9  @");
+          m_wideGraph->setModeTx(m_modeTx);
+        }
+      else if (decodedtext.isJT65())
+        {
+          m_modeTx="JT65";
+          ui->pbTxMode->setText("Tx JT65  #");
+          m_wideGraph->setModeTx(m_modeTx);
+        }
+    }
+  else if ((decodedtext.isJT9 () && m_modeTx != "JT9") || (decodedtext.isJT65 () && m_modeTx != "JT65"))
+    {
+      // if we are not allowing mode change then don't process decode
+      return;
+    }
+
+  int frequency = decodedtext.frequencyOffset();
+  QString firstcall = decodedtext.call();
   // Don't change Tx freq if a station is calling me, unless m_lockTxFreq
-  // is true or CTRL is held down or
-  if((firstcall!=m_myCall) or m_lockTxFreq or ctrl) {
-    ui->TxFreqSpinBox->setValue(nfreq);
-  }
-  QString hiscall=t4.at(6);
-  QString hisgrid="";
-  if(t4.length()>=8) hisgrid=t4.at(7);
-  if(hiscall!=ui->dxCallEntry->text())   ui->dxGridEntry->setText("");
-  ui->dxCallEntry->setText(hiscall);
-  if(gridOK(hisgrid)) ui->dxGridEntry->setText(hisgrid);
-  if(ui->dxGridEntry->text()=="") lookup();
-  m_hisGrid=ui->dxGridEntry->text();
-  int n = 60*t2.mid(0,2).toInt() + t2.mid(2,2).toInt();
+  // is true or CTRL is held down
+  if ((firstcall!=m_config.my_callsign () && firstcall != m_baseCall) || m_lockTxFreq or ctrl)
+    {
+      if (ui->TxFreqSpinBox->isEnabled ())
+        {
+          ui->TxFreqSpinBox->setValue(frequency);
+        }
+      else
+        {
+          return;
+        }
+    }
+
+  int i9=m_QSOText.indexOf(decodedtext.string());
+  if (i9<0 and !decodedtext.isTX())
+    {
+      ui->decodedTextBrowser2->displayDecodedText(decodedtext
+                                                  , m_baseCall
+                                                  , false
+                                                  , m_logBook
+                                                  , m_config.color_CQ()
+                                                  , m_config.color_MyCall()
+                                                  , m_config.color_DXCC()
+                                                  , m_config.color_NewCall());
+      m_QSOText=decodedtext;
+    }
+
+  if (ui->RxFreqSpinBox->isEnabled ())
+    {
+      ui->RxFreqSpinBox->setValue (frequency); //Set Rx freq
+    }
+  if (decodedtext.isTX())
+    {
+      if (ctrl && ui->TxFreqSpinBox->isEnabled ())
+        {
+          ui->TxFreqSpinBox->setValue(frequency); //Set Tx freq
+        }
+      return;
+    }
+
+  // prior DX call (possible QSO partner)
+  auto qso_partner_base_call = Radio::base_callsign (ui->dxCallEntry-> text ().toUpper ().trimmed ());
+
+  auto base_call = Radio::base_callsign (hiscall);
+  if (base_call != Radio::base_callsign (ui->dxCallEntry-> text ().toUpper ().trimmed ()) || base_call != hiscall)
+    {
+      // his base call different or his call more qualified
+      // i.e. compound version of same base call
+      ui->dxCallEntry->setText(hiscall);
+    }
+  if (gridOK(hisgrid))
+    ui->dxGridEntry->setText(hisgrid);
+  if (ui->dxGridEntry->text()=="")
+    lookup();
+  m_hisGrid = ui->dxGridEntry->text();
+
+  int n = decodedtext.timeInSeconds();
   int nmod=n%(m_TRperiod/30);
   m_txFirst=(nmod!=0);
   ui->txFirstCheckBox->setChecked(m_txFirst);
-  QString rpt=t4.at(1);
-  if(rpt.indexOf("  ")==0) rpt="+" + rpt.mid(2,2);
-  if(rpt.indexOf(" -")==0) rpt=rpt.mid(1,2);
-  if(rpt.indexOf(" ")==0) rpt="+" + rpt.mid(1,2);
-  int nr=rpt.toInt();
-  if(nr<-50) rpt="-50";
-  if(nr>49) rpt="+49";
-  if(nr>=-9 and nr<=-1) rpt="-0" + rpt.mid(1);
-  if(nr>=0 and nr<=9) rpt="+0" + rpt;
-  if(nr>=10) rpt="+" + rpt;
+
+  QString rpt = decodedtext.report();
   ui->rptSpinBox->setValue(rpt.toInt());
   genStdMsgs(rpt);
-  if(t2.indexOf(m_myCall)>=0) {
-    if(t4.length()>=7 and !gridOK(t4.at(7))) {
-      QString r=t4.at(7);
-      if(r.mid(0,3)=="RRR") {
+
+  // determine the appropriate response to the received msg
+  auto dtext = " " + decodedtext.string () + " ";
+  if(dtext.contains (" " + m_baseCall + " ")
+     || dtext.contains ("/" + m_baseCall + " ")
+     || dtext.contains (" " + m_baseCall + "/")
+     || (firstcall == "DE" && ((t4.size () > 7 && t4.at(7) != "73") || t4.size () <= 7)))
+    {
+      if (t4.size () > 7   // enough fields for a normal msg
+          and !gridOK (t4.at (7))) // but no grid on end of msg
+        {
+          QString r=t4.at (7);
+          if(r.mid(0,3)=="RRR" || (r.toInt()==73)) {
+            m_ntx=5;
+            ui->txrb5->setChecked(true);
+            if(ui->tabWidget->currentIndex()==1) {
+              ui->genMsg->setText(ui->tx5->currentText());
+              m_ntx=7;
+              ui->rbGenMsg->setChecked(true);
+            }
+          } else if(r.mid(0,1)=="R") {
+            m_ntx=4;
+            ui->txrb4->setChecked(true);
+            if(ui->tabWidget->currentIndex()==1) {
+              ui->genMsg->setText(ui->tx4->text());
+              m_ntx=7;
+              ui->rbGenMsg->setChecked(true);
+            }
+          } else if(r.toInt()>=-50 and r.toInt()<=49) {
+            m_ntx=3;
+            ui->txrb3->setChecked(true);
+            if(ui->tabWidget->currentIndex()==1) {
+              ui->genMsg->setText(ui->tx3->text());
+              m_ntx=7;
+              ui->rbGenMsg->setChecked(true);
+            }
+          }
+        }
+      else if (t4.size () == 7 && t4.at (6) == "73") {
+        // 73 back to compound call holder
         m_ntx=5;
         ui->txrb5->setChecked(true);
         if(ui->tabWidget->currentIndex()==1) {
-          ui->genMsg->setText(ui->tx5->text());
-          m_ntx=7;
-          ui->rbGenMsg->setChecked(true);
-        }
-      } else if(r.mid(0,1)=="R") {
-        m_ntx=4;
-        ui->txrb4->setChecked(true);
-        if(ui->tabWidget->currentIndex()==1) {
-          ui->genMsg->setText(ui->tx4->text());
+          ui->genMsg->setText(ui->tx5->currentText());
           m_ntx=7;
           ui->rbGenMsg->setChecked(true);
         }
-      } else if(r.toInt()>=-50 and r.toInt()<=49) {
-        m_ntx=3;
-        ui->txrb3->setChecked(true);
-        if(ui->tabWidget->currentIndex()==1) {
-          ui->genMsg->setText(ui->tx3->text());
-          m_ntx=7;
-          ui->rbGenMsg->setChecked(true);
-        }
-      } else if(r.toInt()==73) {
-        m_ntx=5;
-        ui->txrb5->setChecked(true);
+      }
+      else {
+        m_ntx=2;
+        ui->txrb2->setChecked(true);
         if(ui->tabWidget->currentIndex()==1) {
-          ui->genMsg->setText(ui->tx5->text());
+          ui->genMsg->setText(ui->tx2->text());
           m_ntx=7;
           ui->rbGenMsg->setChecked(true);
         }
       }
-    } else {
-      m_ntx=2;
-      ui->txrb2->setChecked(true);
+    }
+  else if (firstcall == "DE" && t4.size () == 8 && t4.at (7) == "73") {
+    if (base_call == qso_partner_base_call) {
+      // 73 back to compound call holder
+      m_ntx=5;
+      ui->txrb5->setChecked(true);
       if(ui->tabWidget->currentIndex()==1) {
-        ui->genMsg->setText(ui->tx2->text());
+        ui->genMsg->setText(ui->tx5->currentText());
         m_ntx=7;
         ui->rbGenMsg->setChecked(true);
       }
     }
-
-  } else {
-    m_ntx=1;
-    ui->txrb1->setChecked(true);
-    if(ui->tabWidget->currentIndex()==1) {
-      ui->genMsg->setText(ui->tx1->text());
-      m_ntx=7;
-      ui->rbGenMsg->setChecked(true);
+    else {
+      // treat like a CQ/QRZ
+      m_ntx=1;
+      ui->txrb1->setChecked(true);
+      if(ui->tabWidget->currentIndex()==1) {
+        ui->genMsg->setText(ui->tx1->text());
+        m_ntx=7;
+        ui->rbGenMsg->setChecked(true);
+      }
     }
   }
-  if(m_quickCall) {
-    m_auto=true;
-    ui->autoButton->setStyleSheet(m_pbAutoOn_style);
-  }
+  else // myCall not in msg
+    {
+      m_ntx=1;
+      ui->txrb1->setChecked(true);
+      if(ui->tabWidget->currentIndex()==1) {
+        ui->genMsg->setText(ui->tx1->text());
+        m_ntx=7;
+        ui->rbGenMsg->setChecked(true);
+      }
+    }
+  if(m_transmitting) m_restart=true;
+  if(m_config.quick_call ())
+    {
+      auto_tx_mode (true);
+    }
 }
 
 void MainWindow::genStdMsgs(QString rpt)                       //genStdMsgs()
 {
   QString t;
+  if(m_config.my_callsign () !="" and m_config.my_grid () !="")
+    {
+      t="CQ " + m_config.my_callsign () + " " + m_config.my_grid ().mid(0,4);
+      msgtype(t, ui->tx6);
+    }
+  else
+    {
+      ui->tx6->setText("");
+    }
   QString hisCall=ui->dxCallEntry->text().toUpper().trimmed();
   ui->dxCallEntry->setText(hisCall);
   if(hisCall=="") {
@@ -2158,28 +2257,21 @@ void MainWindow::genStdMsgs(QString rpt)                       //genStdMsgs()
     ui->tx2->setText("");
     ui->tx3->setText("");
     ui->tx4->setText("");
-    ui->tx5->setText("");
-    ui->tx6->setText("");
-    if(m_myCall!="" and m_myGrid!="") {
-      t="CQ " + m_myCall + " " + m_myGrid.mid(0,4);
-      msgtype(t, ui->tx6);
-    }
+    ui->tx5->setCurrentText("");
     ui->genMsg->setText("");
-    ui->freeTextMsg->setText("");
     return;
   }
-  QString hisBase=baseCall(hisCall);
-  QString myBase=baseCall(m_myCall);
-  QString t0=hisBase + " " + myBase + " ";
-  t=t0 + m_myGrid.mid(0,4);
-  if(myBase!=m_myCall) t="DE " + m_myCall + " " + m_myGrid.mid(0,4);
+  QString hisBase = Radio::base_callsign (hisCall);
+
+  QString t0=hisBase + " " + m_baseCall + " ";
+  t=t0 + m_config.my_grid ().mid(0,4);
   msgtype(t, ui->tx1);
   if(rpt == "") {
     t=t+" OOO";
     msgtype(t, ui->tx2);
     msgtype("RO", ui->tx3);
     msgtype("RRR", ui->tx4);
-    msgtype("73", ui->tx5);
+    msgtype("73", ui->tx5->lineEdit ());
   } else {
     t=t0 + rpt;
     msgtype(t, ui->tx2);
@@ -2188,59 +2280,92 @@ void MainWindow::genStdMsgs(QString rpt)                       //genStdMsgs()
     t=t0 + "RRR";
     msgtype(t, ui->tx4);
     t=t0 + "73";
-    if(myBase!=m_myCall) t="DE " + m_myCall + " 73";
-    msgtype(t, ui->tx5);
+    msgtype(t, ui->tx5->lineEdit ());
   }
 
-  t="CQ " + m_myCall + " " + m_myGrid.mid(0,4);
-  msgtype(t, ui->tx6);
+  if(m_config.my_callsign () != m_baseCall) {
+    if(shortList(m_config.my_callsign ())) {
+      t=hisBase + " " + m_config.my_callsign ();
+      msgtype(t, ui->tx1);
+      t="CQ " + m_config.my_callsign ();
+      msgtype(t, ui->tx6);
+    } else {
+      switch (m_config.type_2_msg_gen ())
+        {
+        case Configuration::type_2_msg_1_full:
+          t="DE " + m_config.my_callsign () + " " + m_config.my_grid ().mid(0,4);
+          msgtype(t, ui->tx1);
+          t=t0 + "R" + rpt;
+          msgtype(t, ui->tx3);
+          break;
+
+        case Configuration::type_2_msg_3_full:
+          t = t0 + m_config.my_grid ().mid(0,4);
+          msgtype(t, ui->tx1);
+          t="DE " + m_config.my_callsign () + " R" + rpt;
+          msgtype(t, ui->tx3);
+          break;
+
+        case Configuration::type_2_msg_5_only:
+          t = t0 + m_config.my_grid ().mid(0,4);
+          msgtype(t, ui->tx1);
+          t=t0 + "R" + rpt;
+          msgtype(t, ui->tx3);
+          break;
+        }
+      t="DE " + m_config.my_callsign () + " 73";
+      msgtype(t, ui->tx5->lineEdit ());
+    }
+  } else {
+    if(hisCall!=hisBase) {
+      if(shortList(hisCall)) {
+        t=hisBase + " " + m_config.my_callsign () + " " + m_config.my_grid ().mid (0,4);
+        msgtype(t, ui->tx1);
+      }
+      t=hisCall + " 73";
+      msgtype(t, ui->tx5->lineEdit());
+    }
+  }
   m_ntx=1;
   ui->txrb1->setChecked(true);
   m_rpt=rpt;
 }
 
-QString MainWindow::baseCall(QString t)
-{
-  int n1=t.indexOf("/");
-  if(n1<0) return t;
-  int n2=t.length()-n1-1;
-  if(n2>=n1) return t.mid(n1+1);
-  return t.mid(0,n1);
-}
-
 void MainWindow::lookup()                                       //lookup()
 {
   QString hisCall=ui->dxCallEntry->text().toUpper().trimmed();
+  if (hisCall.isEmpty ())
+    {
+      return;
+    }
   ui->dxCallEntry->setText(hisCall);
-  QString call3File = m_appDir + "/CALL3.TXT";
-  QFile f(call3File);
-  if(!f.open(QIODevice::ReadOnly | QIODevice::Text)) {
-    msgBox("Cannot open " + call3File);
-    return;
-  }
-  char c[132];
-  qint64 n=0;
-  for(int i=0; i<999999; i++) {
-    n=f.readLine(c,sizeof(c));
-    if(n <= 0) {
-      ui->dxGridEntry->setText("");
-      break;
-     }
-    QString t=QString(c);
-    if(t.indexOf(hisCall)==0) {
-      int i1=t.indexOf(",");
-      QString hisgrid=t.mid(i1+1,6);
-      i1=hisgrid.indexOf(",");
-      if(i1>0) {
-        hisgrid=hisgrid.mid(0,4);
-      } else {
-        hisgrid=hisgrid.mid(0,4) + hisgrid.mid(4,2).toLower();
+  QFile f {m_dataDir.absoluteFilePath ("CALL3.TXT")};
+  if (f.open (QIODevice::ReadOnly | QIODevice::Text))
+    {
+      char c[132];
+      qint64 n=0;
+      for(int i=0; i<999999; i++) {
+        n=f.readLine(c,sizeof(c));
+        if(n <= 0) {
+          ui->dxGridEntry->setText("");
+          break;
+        }
+        QString t=QString(c);
+        if(t.indexOf(hisCall)==0) {
+          int i1=t.indexOf(",");
+          QString hisgrid=t.mid(i1+1,6);
+          i1=hisgrid.indexOf(",");
+          if(i1>0) {
+            hisgrid=hisgrid.mid(0,4);
+          } else {
+            hisgrid=hisgrid.mid(0,4) + hisgrid.mid(4,2).toLower();
+          }
+          ui->dxGridEntry->setText(hisgrid);
+          break;
+        }
       }
-      ui->dxGridEntry->setText(hisgrid);
-      break;
+      f.close();
     }
-  }
-  f.close();
 }
 
 void MainWindow::on_lookupButton_clicked()                    //Lookup button
@@ -2259,61 +2384,54 @@ void MainWindow::on_addButton_clicked()                       //Add button
   QString hisgrid=ui->dxGridEntry->text().trimmed();
   QString newEntry=hisCall + "," + hisgrid;
 
-//  int ret = QMessageBox::warning(this, "Add",
-//       newEntry + "\n" + "Is this station known to be active on EME?",
-//       QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
-//  if(ret==QMessageBox::Yes) {
-//    newEntry += ",EME,,";
-//  } else {
-    newEntry += ",,,";
-//  }
-
-  QString call3File = m_appDir + "/CALL3.TXT";
-  QFile f1(call3File);
-  if(!f1.open(QIODevice::ReadOnly | QIODevice::Text)) {
-    msgBox("Cannot open " + call3File);
+  //  int ret = QMessageBox::warning(this, "Add",
+  //       newEntry + "\n" + "Is this station known to be active on EME?",
+  //       QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
+  //  if(ret==QMessageBox::Yes) {
+  //    newEntry += ",EME,,";
+  //  } else {
+  newEntry += ",,,";
+  //  }
+  
+  QFile f1 {m_dataDir.absoluteFilePath ("CALL3.TXT")};
+  if(!f1.open(QIODevice::ReadWrite | QIODevice::Text)) {
+    msgBox("Cannot open \"" + f1.fileName () + "\" for read/write:" + f1.errorString ());
     return;
   }
   if(f1.size()==0) {
-    f1.close();
-    f1.open(QIODevice::WriteOnly | QIODevice::Text);
     QTextStream out(&f1);
     out << "ZZZZZZ" << endl;
     f1.close();
     f1.open(QIODevice::ReadOnly | QIODevice::Text);
   }
-  QString tmpFile = m_appDir + "/CALL3.TMP";
-  QFile f2(tmpFile);
+  QFile f2 {m_dataDir.absoluteFilePath ("CALL3.TMP")};
   if(!f2.open(QIODevice::WriteOnly | QIODevice::Text)) {
-    msgBox("Cannot open " + tmpFile);
+    msgBox("Cannot open \"" + f2.fileName () + "\" for writing:" + f2.errorString ());
     return;
   }
-  QTextStream in(&f1);
-  QTextStream out(&f2);
+  QTextStream in(&f1);          //Read from CALL3.TXT
+  QTextStream out(&f2);         //Copy into CALL3.TMP
   QString hc=hisCall;
   QString hc1="";
-  QString hc2="AAAAAA";
+  QString hc2="000000";
   QString s;
   do {
     s=in.readLine();
     hc1=hc2;
     if(s.mid(0,2)=="//") {
-      out << s + "\n";
+      out << s + "\n";          //Copy all comment lines
     } else {
       int i1=s.indexOf(",");
       hc2=s.mid(0,i1);
       if(hc>hc1 && hc<hc2) {
         out << newEntry + "\n";
-        if(s.mid(0,6)=="ZZZZZZ") {
-          out << s + "\n";
-//          exit;                             //Statement has no effect!
-        }
+        out << s + "\n";
         m_call3Modified=true;
       } else if(hc==hc2) {
         QString t=s + "\n\n is already in CALL3.TXT\n" +
-            "Do you wish to replace it?";
+          "Do you wish to replace it?";
         int ret = QMessageBox::warning(this, "Add",t,
-             QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
+                                       QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
         if(ret==QMessageBox::Yes) {
           out << newEntry + "\n";
           m_call3Modified=true;
@@ -2325,15 +2443,13 @@ void MainWindow::on_addButton_clicked()                       //Add button
   } while(!s.isNull());
 
   f1.close();
-  if(hc>hc1 && !m_call3Modified) {
-    out << newEntry + "\n";
-  }
+  if(hc>hc1 && !m_call3Modified) out << newEntry + "\n";
   if(m_call3Modified) {
-    QFile f0(m_appDir + "/CALL3.OLD");
+    QFile f0 {m_dataDir.absoluteFilePath ("CALL3.OLD")};
     if(f0.exists()) f0.remove();
-    QFile f1(m_appDir + "/CALL3.TXT");
-    f1.rename(m_appDir + "/CALL3.OLD");
-    f2.rename(m_appDir + "/CALL3.TXT");
+    QFile f1 {m_dataDir.absoluteFilePath ("CALL3.TXT")};
+    f1.rename(m_dataDir.absoluteFilePath ("CALL3.OLD"));
+    f2.rename(m_dataDir.absoluteFilePath ("CALL3.TXT"));
     f2.close();
   }
 }
@@ -2347,11 +2463,17 @@ void MainWindow::msgtype(QString t, QLineEdit* tx)               //msgtype()
   t=t.toUpper();
   QByteArray s=t.toUpper().toLocal8Bit();
   ba2msg(s,message);
-  int ichk=1,itext=0;
-  genjt9_(message,&ichk,msgsent,itone,&itext,len1,len1);
+  int ichk=1,itype=0;
+  genjt9_(message
+          , &ichk
+          , msgsent
+          , const_cast<int *> (itone)
+          , &itype
+          , len1
+          , len1);
   msgsent[22]=0;
   bool text=false;
-  if(itext!=0) text=true;
+  if(itype==6) text=true;
   QString t1;
   t1.fromLatin1(msgsent);
   if(text) t1=t1.mid(0,13);
@@ -2363,12 +2485,14 @@ void MainWindow::msgtype(QString t, QLineEdit* tx)               //msgtype()
   }
   tx->setPalette(p);
   int len=t.length();
+  auto pos  = tx->cursorPosition ();
   if(text) {
     len=qMin(len,13);
     tx->setText(t.mid(0,len).toUpper());
   } else {
     tx->setText(t);
   }
+  tx->setCursorPosition (pos);
 }
 
 void MainWindow::on_tx1_editingFinished()                       //tx1 edited
@@ -2395,19 +2519,22 @@ void MainWindow::on_tx4_editingFinished()                       //tx4 edited
   msgtype(t, ui->tx4);
 }
 
-void MainWindow::on_tx5_editingFinished()                       //tx5 edited
+void MainWindow::on_tx5_currentTextChanged (QString const& text) //tx5 edited
 {
-  QString t=ui->tx5->text();
-  msgtype(t, ui->tx5);
+  msgtype(text, ui->tx5->lineEdit ());
 }
 
 void MainWindow::on_tx6_editingFinished()                       //tx6 edited
 {
   QString t=ui->tx6->text();
   msgtype(t, ui->tx6);
-  double snr=t.mid(1,5).toDouble();
-  if(snr>0.0 or snr < -50.0) snr=99.0;
-  soundOutThread.setTxSNR(snr);
+
+  // G4WJS: disabled setting of snr from msg 6 on live edit, will
+  // still generate noise on next full tx period
+
+  // double snr=t.mid(1,5).toDouble();
+  // if(snr>0.0 or snr < -50.0) snr=99.0;
+  // m_modulator.setTxSNR(snr);
 }
 
 void MainWindow::on_dxCallEntry_textChanged(const QString &t) //dxCall changed
@@ -2429,20 +2556,26 @@ void MainWindow::on_dxGridEntry_textChanged(const QString &t) //dxGrid changed
   if(!t[2].isDigit() or !t[3].isDigit()) return;
   if(n==4) m_hisGrid=t.mid(0,2).toUpper() + t.mid(2,2);
   if(n==6) m_hisGrid=t.mid(0,2).toUpper() + t.mid(2,2) +
-      t.mid(4,2).toLower();
+             t.mid(4,2).toLower();
   ui->dxGridEntry->setText(m_hisGrid);
   if(gridOK(m_hisGrid)) {
     qint64 nsec = QDateTime::currentMSecsSinceEpoch() % 86400;
     double utch=nsec/3600.0;
     int nAz,nEl,nDmiles,nDkm,nHotAz,nHotABetter;
 
-    azdist_(m_myGrid.toLatin1().data(),m_hisGrid.toLatin1().data(),&utch,
-           &nAz,&nEl,&nDmiles,&nDkm,&nHotAz,&nHotABetter,6,6);
+    azdist_(const_cast <char *> (m_config.my_grid ().toLatin1().constData()),const_cast<char *> (m_hisGrid.toLatin1().constData()),&utch,
+            &nAz,&nEl,&nDmiles,&nDkm,&nHotAz,&nHotABetter,6,6);
     QString t;
     t.sprintf("Az: %d",nAz);
     ui->labAz->setText(t);
-    if(m_bMiles) t.sprintf("%d mi",int(0.621371*nDkm));
-    if(!m_bMiles) t.sprintf("%d km",nDkm);
+    if (m_config.miles ())
+      {
+        t.sprintf ("%d mi", int (0.621371 * nDkm));
+      }
+    else
+      {
+        t.sprintf ("%d km", nDkm);
+      }
     ui->labDist->setText(t);
   } else {
     ui->labAz->setText("");
@@ -2460,28 +2593,35 @@ void MainWindow::on_logQSOButton_clicked()                 //Log QSO button
   if(m_hisCall=="") return;
   m_dateTimeQSO=QDateTime::currentDateTimeUtc();
 
-  logDlg = new LogQSO(0);
-  logDlg->m_saveTxPower=m_saveTxPower;
-  logDlg->m_saveComments=m_saveComments;
-  logDlg->m_txPower=m_txPower;
-  logDlg->m_comments=m_logComments;
-  logDlg->initLogQSO(m_hisCall,m_hisGrid,m_modeTx,m_rptSent,m_rptRcvd,
-                     m_dateTimeQSO,m_dialFreq+m_txFreq/1.0e6,
-                     m_myCall,m_myGrid,m_noSuffix,m_toRTTY,m_dBtoComments);
-  connect(logDlg, SIGNAL(acceptQSO(bool)),this,SLOT(acceptQSO2(bool)));
-  if(m_logQSOgeom != QRect(500,400,424,283)) logDlg->setGeometry(m_logQSOgeom);
-  logDlg->show();
-}
-
-void MainWindow::acceptQSO2(bool accepted)
-{
-  if(accepted) {
-    m_logQSOgeom=logDlg->geometry();
-    m_saveTxPower=logDlg->m_saveTxPower;
-    m_saveComments=logDlg->m_saveComments;
-    m_txPower=logDlg->m_txPower;
-    m_logComments=logDlg->m_comments;
-    if(m_clearCallGrid) {
+  m_logDlg->initLogQSO (m_hisCall
+                        , m_hisGrid
+                        , m_modeTx
+                        , m_rptSent
+                        , m_rptRcvd
+                        , m_dateTimeQSO
+                        , m_dialFreq + ui->TxFreqSpinBox->value ()
+                        , m_config.my_callsign ()
+                        , m_config.my_grid ()
+                        , m_noSuffix
+                        , m_config.log_as_RTTY ()
+                        , m_config.report_in_comments ()
+                        );
+}
+
+void MainWindow::acceptQSO2(QDateTime const& QSO_date, QString const& call, QString const& grid
+                            , Frequency dial_freq, QString const& mode
+                            , QString const& rpt_sent, QString const& rpt_received
+                            , QString const& tx_power, QString const& comments
+                            , QString const& name)
+{
+  QString band = ADIF::bandFromFrequency ((m_dialFreq + ui->TxFreqSpinBox->value ()) / 1.e6);
+  QString date = m_dateTimeQSO.toString("yyyyMMdd");
+  m_logBook.addAsWorked(m_hisCall,band,m_modeTx,date);
+
+  m_messageClient->qso_logged (QSO_date, call, grid, dial_freq, mode, rpt_sent, rpt_received, tx_power, comments, name);
+
+  if (m_config.clear_DX ())
+    {
       m_hisCall="";
       ui->dxCallEntry->setText("");
       m_hisGrid="";
@@ -2491,7 +2631,6 @@ void MainWindow::acceptQSO2(bool accepted)
       m_qsoStart="";
       m_qsoStop="";
     }
-  }
 }
 
 void MainWindow::on_actionJT9_1_triggered()
@@ -2502,14 +2641,31 @@ void MainWindow::on_actionJT9_1_triggered()
   m_TRperiod=60;
   m_nsps=6912;
   m_hsymStop=173;
-  soundInThread.setPeriod(m_TRperiod,m_nsps);
-  soundOutThread.setPeriod(m_TRperiod,m_nsps);
-  lab3->setStyleSheet("QLabel{background-color: #ff6ec7}");
-  lab3->setText(m_mode);
+  mode_label->setStyleSheet("QLabel{background-color: #ff6ec7}");
+  mode_label->setText(m_mode);
+  m_toneSpacing=0.0;
   ui->actionJT9_1->setChecked(true);
-  g_pWideGraph->setPeriod(m_TRperiod,m_nsps);
-  g_pWideGraph->setMode(m_mode);
-  g_pWideGraph->setModeTx(m_modeTx);
+  m_wideGraph->setPeriod(m_TRperiod,m_nsps);
+  m_wideGraph->setMode(m_mode);
+  m_wideGraph->setModeTx(m_modeTx);
+  ui->pbTxMode->setEnabled(false);
+}
+
+void MainWindow::on_actionJT9W_1_triggered()
+{
+  m_mode="JT9W-1";
+  if(m_modeTx!="JT9") on_pbTxMode_clicked();
+  statusChanged();
+  m_TRperiod=60;
+  m_nsps=6912;
+  m_hsymStop=173;
+  m_toneSpacing=pow(2,m_config.jt9w_bw_mult ())*12000.0/6912.0;
+  mode_label->setStyleSheet("QLabel{background-color: #ff6ec7}");
+  mode_label->setText(m_mode);
+  ui->actionJT9W_1->setChecked(true);
+  m_wideGraph->setPeriod(m_TRperiod,m_nsps);
+  m_wideGraph->setMode(m_mode);
+  m_wideGraph->setModeTx(m_modeTx);
   ui->pbTxMode->setEnabled(false);
 }
 
@@ -2521,49 +2677,49 @@ void MainWindow::on_actionJT65_triggered()
   m_TRperiod=60;
   m_nsps=6912;                   //For symspec only
   m_hsymStop=173;
-  soundInThread.setPeriod(m_TRperiod,m_nsps);
-  soundOutThread.setPeriod(m_TRperiod,m_nsps);
-  lab3->setStyleSheet("QLabel{background-color: #ffff00}");
-  lab3->setText(m_mode);
+  m_toneSpacing=0.0;
+  mode_label->setStyleSheet("QLabel{background-color: #ffff00}");
+  mode_label->setText(m_mode);
   ui->actionJT65->setChecked(true);
-  g_pWideGraph->setPeriod(m_TRperiod,m_nsps);
-  g_pWideGraph->setMode(m_mode);
-  g_pWideGraph->setModeTx(m_modeTx);
+  m_wideGraph->setPeriod(m_TRperiod,m_nsps);
+  m_wideGraph->setMode(m_mode);
+  m_wideGraph->setModeTx(m_modeTx);
   ui->pbTxMode->setEnabled(false);
 }
 
 void MainWindow::on_actionJT9_JT65_triggered()
 {
   m_mode="JT9+JT65";
-//  if(m_modeTx!="JT9") on_pbTxMode_clicked();
+  //  if(m_modeTx!="JT9") on_pbTxMode_clicked();
   statusChanged();
   m_TRperiod=60;
   m_nsps=6912;
   m_hsymStop=173;
-  soundInThread.setPeriod(m_TRperiod,m_nsps);
-  soundOutThread.setPeriod(m_TRperiod,m_nsps);
-  lab3->setStyleSheet("QLabel{background-color: #ffa500}");
-  lab3->setText(m_mode);
+  m_toneSpacing=0.0;
+  mode_label->setStyleSheet("QLabel{background-color: #ffa500}");
+  mode_label->setText(m_mode);
   ui->actionJT9_JT65->setChecked(true);
-  g_pWideGraph->setPeriod(m_TRperiod,m_nsps);
-  g_pWideGraph->setMode(m_mode);
-  g_pWideGraph->setModeTx(m_modeTx);
+  m_wideGraph->setPeriod(m_TRperiod,m_nsps);
+  m_wideGraph->setMode(m_mode);
+  m_wideGraph->setModeTx(m_modeTx);
   ui->pbTxMode->setEnabled(true);
 }
 
 void MainWindow::on_TxFreqSpinBox_valueChanged(int n)
 {
-  m_txFreq=n;
-  if(g_pWideGraph!=NULL) g_pWideGraph->setTxFreq(n);
+  m_wideGraph->setTxFreq(n);
   if(m_lockTxFreq) ui->RxFreqSpinBox->setValue(n);
-  soundOutThread.setTxFreq(n);
+  Q_EMIT transmitFrequency (n - m_XIT);
 }
 
 void MainWindow::on_RxFreqSpinBox_valueChanged(int n)
 {
-  m_rxFreq=n;
-  if(g_pWideGraph!=NULL) g_pWideGraph->setRxFreq(n);
-  if(m_lockTxFreq) ui->TxFreqSpinBox->setValue(n);
+  m_wideGraph->setRxFreq(n);
+
+  if (m_lockTxFreq && ui->TxFreqSpinBox->isEnabled ())
+    {
+      ui->TxFreqSpinBox->setValue (n);
+    }
 }
 
 void MainWindow::on_actionQuickDecode_triggered()
@@ -2589,18 +2745,13 @@ void MainWindow::on_inGain_valueChanged(int n)
   m_inGain=n;
 }
 
-void MainWindow::on_actionMonitor_OFF_at_startup_triggered()
-{
-  m_monitorStartOFF=!m_monitorStartOFF;
-}
-
 void MainWindow::on_actionErase_ALL_TXT_triggered()          //Erase ALL.TXT
 {
   int ret = QMessageBox::warning(this, "Confirm Erase",
-      "Are you sure you want to erase file ALL.TXT ?",
-       QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
+                                 "Are you sure you want to erase file ALL.TXT ?",
+                                 QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
   if(ret==QMessageBox::Yes) {
-    QFile f("ALL.TXT");
+    QFile f {m_dataDir.absoluteFilePath ("ALL.TXT")};
     f.remove();
     m_RxLog=1;
   }
@@ -2609,153 +2760,99 @@ void MainWindow::on_actionErase_ALL_TXT_triggered()          //Erase ALL.TXT
 void MainWindow::on_actionErase_wsjtx_log_adi_triggered()
 {
   int ret = QMessageBox::warning(this, "Confirm Erase",
-      "Are you sure you want to erase file wsjtx_log.adi ?",
-       QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
+                                 "Are you sure you want to erase file wsjtx_log.adi ?",
+                                 QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
   if(ret==QMessageBox::Yes) {
-    QFile f("wsjtx_log.adi");
+    QFile f {m_dataDir.absoluteFilePath ("wsjtx_log.adi")};
     f.remove();
   }
 }
 
-void MainWindow::showMacros(const QPoint &pos)
-{
-  if(m_macro.length()<10) return;
-  QPoint globalPos = ui->tx5->mapToGlobal(pos);
-  QMenu popupMenu;
-  QAction* popup1 = new QAction(m_macro[0],ui->tx5);
-  QAction* popup2 = new QAction(m_macro[1],ui->tx5);
-  QAction* popup3 = new QAction(m_macro[2],ui->tx5);
-  QAction* popup4 = new QAction(m_macro[3],ui->tx5);
-  QAction* popup5 = new QAction(m_macro[4],ui->tx5);
-  QAction* popup6 = new QAction(m_macro[5],ui->tx5);
-  QAction* popup7 = new QAction(m_macro[6],ui->tx5);
-  QAction* popup8 = new QAction(m_macro[7],ui->tx5);
-  QAction* popup9 = new QAction(m_macro[8],ui->tx5);
-  QAction* popup10 = new QAction(m_macro[9],ui->tx5);
-
-  if(m_macro[0]!="") popupMenu.addAction(popup1);
-  if(m_macro[1]!="") popupMenu.addAction(popup2);
-  if(m_macro[2]!="") popupMenu.addAction(popup3);
-  if(m_macro[3]!="") popupMenu.addAction(popup4);
-  if(m_macro[4]!="") popupMenu.addAction(popup5);
-  if(m_macro[5]!="") popupMenu.addAction(popup6);
-  if(m_macro[6]!="") popupMenu.addAction(popup7);
-  if(m_macro[7]!="") popupMenu.addAction(popup8);
-  if(m_macro[8]!="") popupMenu.addAction(popup9);
-  if(m_macro[9]!="") popupMenu.addAction(popup10);
-
-  connect(popup1,SIGNAL(triggered()), this, SLOT(onPopup1()));
-  connect(popup2,SIGNAL(triggered()), this, SLOT(onPopup2()));
-  connect(popup3,SIGNAL(triggered()), this, SLOT(onPopup3()));
-  connect(popup4,SIGNAL(triggered()), this, SLOT(onPopup4()));
-  connect(popup5,SIGNAL(triggered()), this, SLOT(onPopup5()));
-  connect(popup6,SIGNAL(triggered()), this, SLOT(onPopup6()));
-  connect(popup7,SIGNAL(triggered()), this, SLOT(onPopup7()));
-  connect(popup8,SIGNAL(triggered()), this, SLOT(onPopup8()));
-  connect(popup9,SIGNAL(triggered()), this, SLOT(onPopup9()));
-  connect(popup10,SIGNAL(triggered()), this, SLOT(onPopup10()));
-  popupMenu.exec(globalPos);
-}
-
-void MainWindow::onPopup1() { ui->tx5->setText(m_macro[0]); freeText(); }
-void MainWindow::onPopup2() { ui->tx5->setText(m_macro[1]); freeText(); }
-void MainWindow::onPopup3() { ui->tx5->setText(m_macro[2]); freeText(); }
-void MainWindow::onPopup4() { ui->tx5->setText(m_macro[3]); freeText(); }
-void MainWindow::onPopup5() { ui->tx5->setText(m_macro[4]); freeText(); }
-void MainWindow::onPopup6() { ui->tx5->setText(m_macro[5]); freeText(); }
-void MainWindow::onPopup7() { ui->tx5->setText(m_macro[6]); freeText(); }
-void MainWindow::onPopup8() { ui->tx5->setText(m_macro[7]); freeText(); }
-void MainWindow::onPopup9() { ui->tx5->setText(m_macro[8]); freeText(); }
-void MainWindow::onPopup10() { ui->tx5->setText(m_macro[9]); freeText(); }
-
-void MainWindow::freeText() { ui->freeTextMsg->setText(ui->tx5->text()); }
+void MainWindow::on_actionOpen_log_directory_triggered ()
+{
+  QDesktopServices::openUrl (QUrl::fromLocalFile (m_dataDir.absolutePath ()));
+}
 
 bool MainWindow::gridOK(QString g)
 {
   bool b=g.mid(0,1).compare("A")>=0 and
-      g.mid(0,1).compare("R")<=0 and
-      g.mid(1,1).compare("A")>=0 and
-      g.mid(1,1).compare("R")<=0 and
-      g.mid(2,1).compare("0")>=0 and
-      g.mid(2,1).compare("9")<=0 and
-      g.mid(3,1).compare("0")>=0 and
-      g.mid(3,1).compare("9")<=0;
+    g.mid(0,1).compare("R")<=0 and
+    g.mid(1,1).compare("A")>=0 and
+    g.mid(1,1).compare("R")<=0 and
+    g.mid(2,1).compare("0")>=0 and
+    g.mid(2,1).compare("9")<=0 and
+    g.mid(3,1).compare("0")>=0 and
+    g.mid(3,1).compare("9")<=0;
   return b;
 }
 
-void MainWindow::on_actionConvert_JT9_x_to_RTTY_triggered(bool checked)
+void MainWindow::on_bandComboBox_activated (int index)
 {
-  m_toRTTY=checked;
-}
+  auto frequencies = m_config.frequencies ();
+  auto frequency = frequencies->data (frequencies->index (index, 0));
 
-void MainWindow::on_actionLog_JT9_without_submode_triggered(bool checked)
-{
-  m_noSuffix=checked;
-}
+  // Lookup band
+  auto bands = m_config.bands ();
+  auto band_index = bands->find (frequency);
+  if (band_index.isValid ())
+    {
+      ui->bandComboBox->lineEdit ()->setStyleSheet ({});
+      ui->bandComboBox->setCurrentText (band_index.data ().toString ());
+    }
+  else
+    {
+      ui->bandComboBox->lineEdit ()->setStyleSheet ("QLineEdit {color: yellow; background-color : red;}");
+      ui->bandComboBox->setCurrentText (bands->data (QModelIndex {}).toString ());
+    }
 
-void MainWindow::on_actionLog_dB_reports_to_Comments_triggered(bool checked)
-{
-  m_dBtoComments=checked;
+  auto f = frequency.value<Frequency> ();
+  if (m_plus2kHz)
+    {
+      f += 2000;
+    }
+
+  m_bandEdited = true;
+  band_changed (f);
 }
 
-void MainWindow::on_bandComboBox_activated(int index)
+void MainWindow::band_changed (Frequency f)
 {
-  int ret=0;
-  QString rt;
+  if (m_bandEdited)
+    {
+      m_bandEdited = false;
 
-  m_band=index;
-  QString t=m_dFreq[index];
-  m_dialFreq=t.toDouble();
-  if(m_plus2kHz) m_dialFreq+=0.002;
-  dialFreqChanged2(m_dialFreq);
-  m_repeatMsg=0;
-  m_secBandChanged=QDateTime::currentMSecsSinceEpoch()/1000;
-  if(m_catEnabled) {
-    if(!m_bRigOpen) {
-      rigOpen();
-    }
-    if(m_bRigOpen) {
-      m_dontReadFreq=true;
-      ret=rig->setFreq(MHz(m_dialFreq));
-      if(m_bSplit or m_bXIT) setXIT(m_txFreq);
-
-      if(g_pWideGraph!=NULL) {
-        bumpFqso(11);
-        bumpFqso(12);
-      }
-      if(ret!=RIG_OK) {
-        rt.sprintf("Set rig frequency failed:  %d",ret);
-        msgBox(rt);
-      }
-    }
-  }
-  QFile f2("ALL.TXT");
-  f2.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append);
-  QTextStream out(&f2);
-  out << QDateTime::currentDateTimeUtc().toString("yyyy-MMM-dd hh:mm")
-      << "  " << m_dialFreq << " MHz  " << m_mode << endl;
-  f2.close();
-}
+      // Upload any queued spots before changing band
+      psk_Reporter->sendReport();
 
-void MainWindow::on_actionPrompt_to_log_QSO_triggered(bool checked)
-{
-  m_promptToLog=checked;
-}
+      if (!m_transmitting)
+        {
+          monitor (true);
+        }
 
-void MainWindow::on_actionBlank_line_between_decoding_periods_triggered(bool checked)
-{
-  m_insertBlank=checked;
+      Q_EMIT m_config.transceiver_frequency (f);
+      qsy (f);
+      setXIT (ui->TxFreqSpinBox->value ());
+    }
 }
 
-void MainWindow::on_actionClear_DX_Call_and_Grid_after_logging_triggered(bool checked)
+void MainWindow::enable_DXCC_entity (bool on)
 {
-  m_clearCallGrid=checked;
-}
+  if (on)
+    {
+      // re-read the log and cty.dat files
+      m_logBook.init();
+    }
 
-void MainWindow::on_actionDisplay_distance_in_miles_triggered(bool checked)
-{
-  m_bMiles=checked;
-  on_dxGridEntry_textChanged(m_hisGrid);
+  if (on)  // adjust the proportions between the two text displays
+    {
+      ui->gridLayout->setColumnStretch(0,55);
+      ui->gridLayout->setColumnStretch(1,45);
+    }
+  else
+    {
+      ui->gridLayout->setColumnStretch(0,0);
+      ui->gridLayout->setColumnStretch(1,0);
+    }
 }
 
 void MainWindow::on_pbCallCQ_clicked()
@@ -2770,7 +2867,11 @@ void MainWindow::on_pbCallCQ_clicked()
 void MainWindow::on_pbAnswerCaller_clicked()
 {
   genStdMsgs(m_rpt);
-  ui->genMsg->setText(ui->tx2->text());
+  QString t=ui->tx3->text();
+  int i0=t.indexOf(" R-");
+  if(i0<0) i0=t.indexOf(" R+");
+  t=t.mid(0,i0+1)+t.mid(i0+2,3);
+  ui->genMsg->setText(t);
   m_ntx=7;
   ui->rbGenMsg->setChecked(true);
   if(m_transmitting) m_restart=true;
@@ -2789,6 +2890,10 @@ void MainWindow::on_pbAnswerCQ_clicked()
 {
   genStdMsgs(m_rpt);
   ui->genMsg->setText(ui->tx1->text());
+  QString t=ui->tx2->text();
+  int i0=t.indexOf("/");
+  int i1=t.indexOf(" ");
+  if(i0>0 and i0<i1) ui->genMsg->setText(t);
   m_ntx=7;
   ui->rbGenMsg->setChecked(true);
   if(m_transmitting) m_restart=true;
@@ -2806,22 +2911,22 @@ void MainWindow::on_pbSendReport_clicked()
 void MainWindow::on_pbSend73_clicked()
 {
   genStdMsgs(m_rpt);
-  ui->genMsg->setText(ui->tx5->text());
+  ui->genMsg->setText(ui->tx5->currentText());
   m_ntx=7;
   ui->rbGenMsg->setChecked(true);
   if(m_transmitting) m_restart=true;
 }
 
-void MainWindow::on_rbGenMsg_toggled(bool checked)
+void MainWindow::on_rbGenMsg_clicked(bool checked)
 {
   m_freeText=!checked;
   if(!m_freeText) {
+    if(m_ntx != 7 && m_transmitting) m_restart=true;
     m_ntx=7;
-    if(m_transmitting) m_restart=true;
   }
 }
 
-void MainWindow::on_rbFreeText_toggled(bool checked)
+void MainWindow::on_rbFreeText_clicked(bool checked)
 {
   m_freeText=checked;
   if(m_freeText) {
@@ -2830,24 +2935,18 @@ void MainWindow::on_rbFreeText_toggled(bool checked)
   }
 }
 
-void MainWindow::on_freeTextMsg_editingFinished()
-{
-  QString t=ui->freeTextMsg->text();
-  msgtype(t, ui->freeTextMsg);
-}
-
-void MainWindow::on_actionDouble_click_on_call_sets_Tx_Enable_triggered(bool checked)
+void MainWindow::on_freeTextMsg_currentTextChanged (QString const& text)
 {
-  m_quickCall=checked;
+  msgtype(text, ui->freeTextMsg->lineEdit ());
 }
 
 void MainWindow::on_rptSpinBox_valueChanged(int n)
 {
   m_rpt=QString::number(n);
   int ntx0=m_ntx;
-  QString t=ui->tx5->text();
+  QString t=ui->tx5->currentText();
   genStdMsgs(m_rpt);
-  ui->tx5->setText(t);
+  ui->tx5->setCurrentText(t);
   m_ntx=ntx0;
   if(m_ntx==1) ui->txrb1->setChecked(true);
   if(m_ntx==2) ui->txrb2->setChecked(true);
@@ -2858,132 +2957,79 @@ void MainWindow::on_rptSpinBox_valueChanged(int n)
   statusChanged();
 }
 
-void MainWindow::on_action_73TxDisable_triggered(bool checked)
+void MainWindow::on_tuneButton_clicked (bool checked)
 {
-  m_73TxDisable=checked;
+  if (m_tune)
+    {
+      tuneButtonTimer->start(250);
+    } 
+  else
+    {
+      m_sentFirst73=false;
+      m_repeatMsg=0;
+      on_monitorButton_clicked (true);
+    }
+  m_tune = checked;
+  Q_EMIT tune (checked);
 }
 
-void MainWindow::on_actionRunaway_Tx_watchdog_triggered(bool checked)
+void MainWindow::stop_tuning ()
 {
-  m_runaway=checked;
-}
-
-void MainWindow::on_tuneButton_clicked()
-{
-  if(m_tune) {
-    nc1=1;                                 //disable the countdown timer
-    tuneButtonTimer->start(250);
-  } else {
-    m_tune=true;
-    m_sent73=false;
-    soundOutThread.setTune(m_tune);
-    m_repeatMsg=0;
-    ui->tuneButton->setStyleSheet(m_pbTune_style);
-  }
+  ui->tuneButton->setChecked (false);
+  on_tuneButton_clicked (false);
 }
 
 void MainWindow::on_stopTxButton_clicked()                    //Stop Tx
 {
-  if(m_tune) {
-    m_tune=false;
-    soundOutThread.setTune(m_tune);
-  }
-  if(m_auto) on_autoButton_clicked();
-  btxok=false;
-  m_repeatMsg=0;
-  ui->tuneButton->setStyleSheet("");
-}
-
-void MainWindow::rigOpen()
-{
-  QString t;
-  int ret;
-  rig = new Rig();
-
-  if(m_rig<9900) {
-    if (!rig->init(m_rig)) {
-      msgBox("Rig init failure");
-      return;
+  if (m_tune)
+    {
+      stop_tuning ();
     }
-    QString sCATport=m_catPort;
-#ifdef WIN32
-    sCATport="\\\\.\\" + m_catPort;    //Allow COM ports above 9
-#endif
-    rig->setConf("rig_pathname", sCATport.toLatin1().data());
-    char buf[80];
-    sprintf(buf,"%d",m_serialRate);
-    rig->setConf("serial_speed",buf);
-    sprintf(buf,"%d",m_dataBits);
-    rig->setConf("data_bits",buf);
-    sprintf(buf,"%d",m_stopBits);
-    rig->setConf("stop_bits",buf);
-    rig->setConf("serial_handshake",m_handshake.toLatin1().data());
-    if(m_bDTRoff) {
-      rig->setConf("rts_state","OFF");
-      rig->setConf("dtr_state","OFF");
-    }
-  }
-
-  ret=rig->open(m_rig);
-  if(ret==RIG_OK) {
-    m_bRigOpen=true;
-    if(m_poll==0) ui->readFreq->setEnabled(true);
-    m_CATerror=false;
-  } else {
-    t="Open rig failed";
-    msgBox(t);
-    m_catEnabled=false;
-    m_bRigOpen=false;
-    m_CATerror=true;
-  }
 
-  if(m_bRigOpen) {
-    if(m_poll>0) {
-      ui->readFreq->setStyleSheet("QPushButton{background-color: #00ff00; \
-                                  border-width: 0px; border-radius: 5px;}");
-    } else {
-      ui->readFreq->setStyleSheet("QPushButton{background-color: orange; \
-                                border-width: 0px; border-radius: 5px;}");
+  if (m_auto)
+    {
+      auto_tx_mode (false);
     }
-} else {
-if(m_CATerror) ui->readFreq->setStyleSheet("QPushButton{background-color: red; \
-                                   border-width: 0px; border-radius: 5px;}");
-if(!m_CATerror) ui->readFreq->setStyleSheet("");
-  }
+
+  m_btxok=false;
+  m_repeatMsg=0;
 }
 
-void MainWindow::on_actionAllow_multiple_instances_triggered(bool checked)
+void MainWindow::rigOpen ()
 {
-  m_bMultipleOK=checked;
+  ui->readFreq->setStyleSheet ("");
+  ui->readFreq->setText ("");
+  m_config.transceiver_online (true);
+  Q_EMIT m_config.sync_transceiver (true);
+  ui->readFreq->setStyleSheet("QPushButton{background-color: orange;"
+                              "border-width: 0px; border-radius: 5px;}");
 }
 
 void MainWindow::on_pbR2T_clicked()
 {
-  int n=g_pWideGraph->rxFreq();
-  ui->TxFreqSpinBox->setValue(n);
+  if (ui->TxFreqSpinBox->isEnabled ())
+    {
+      ui->TxFreqSpinBox->setValue(ui->RxFreqSpinBox->value ());
+    }
 }
 
 void MainWindow::on_pbT2R_clicked()
 {
-  g_pWideGraph->setRxFreq(m_txFreq);
+  if (ui->RxFreqSpinBox->isEnabled ())
+    {
+      ui->RxFreqSpinBox->setValue (ui->TxFreqSpinBox->value ());
+    }
 }
 
 
 void MainWindow::on_readFreq_clicked()
 {
-  if(m_transmitting) return;
-  m_dontReadFreq=false;
-  double fMHz=rig->getFreq(RIG_VFO_CURR)/1000000.0;
-  if(fMHz<0.0) {
-    QString rt;
-    rt.sprintf("Rig control error %d\nFailed to read frequency.",
-               int(1000000.0*fMHz));
-    msgBox(rt);
-    m_catEnabled=false;
-  }
-  if(fMHz<0.01 or fMHz>1300.0) fMHz=0;
-  int ndiff=1000000.0*(fMHz-m_dialFreq);
-  if(ndiff!=0) dialFreqChanged2(fMHz);
+  if (m_transmitting) return;
+
+  if (m_config.transceiver_online (true))
+    {
+      Q_EMIT m_config.sync_transceiver (true);
+    }
 }
 
 void MainWindow::on_pbTxMode_clicked()
@@ -2995,58 +3041,407 @@ void MainWindow::on_pbTxMode_clicked()
     m_modeTx="JT9";
     ui->pbTxMode->setText("Tx JT9  @");
   }
-  g_pWideGraph->setModeTx(m_modeTx);
+  m_wideGraph->setModeTx(m_modeTx);
   statusChanged();
 }
 
 void MainWindow::setXIT(int n)
 {
-  int ret;
-  int xit=0;
-  if(m_bRigOpen) {
-    xit=-1000;
-    if(n>1000) xit=0;
-    if(n>2000) xit=1000;
-    if(n>3000) xit=2000;
-    if(n>4000) xit=3000;
-    if(m_bXIT) {
-      ret=rig->setXit((shortfreq_t)xit,RIG_VFO_TX);
-      if(ret!=RIG_OK) {
-        QString rt;
-        rt.sprintf("Setting RIG_VFO_TX failed:  %d",ret);
-        msgBox(rt);
-      }
+  m_XIT = 0;
+  if (m_config.split_mode ())
+    {
+      m_XIT=(n/500)*500 - 1500;
     }
-    if(m_bSplit) {
-      ret=rig->setSplitFreq(MHz(m_dialFreq)+xit,RIG_VFO_B);
+
+  if (m_monitoring || m_transmitting)
+    {
+      if (m_config.transceiver_online ())
+        {
+          if (m_config.split_mode ())
+            {
+              Q_EMIT m_config.transceiver_tx_frequency (m_dialFreq + m_XIT);
+            }
+        }
     }
-  }
-  if(m_bSplit) soundOutThread.setXIT(xit);
-  if(!m_bSplit) soundOutThread.setXIT(0);
+
+  Q_EMIT transmitFrequency (ui->TxFreqSpinBox->value () - m_XIT);
 }
 
 void MainWindow::setFreq4(int rxFreq, int txFreq)
 {
-  m_rxFreq=rxFreq;
-  m_txFreq=txFreq;
-  ui->RxFreqSpinBox->setValue(m_rxFreq);
-  ui->TxFreqSpinBox->setValue(m_txFreq);
+  if (ui->RxFreqSpinBox->isEnabled ())
+    {
+      ui->RxFreqSpinBox->setValue(rxFreq);
+    }
+
+  if (ui->TxFreqSpinBox->isEnabled ())
+    {
+      ui->TxFreqSpinBox->setValue(txFreq);
+    }
 }
 
 void MainWindow::on_cbTxLock_clicked(bool checked)
 {
   m_lockTxFreq=checked;
-  g_pWideGraph->setLockTxFreq(m_lockTxFreq);
+  m_wideGraph->setLockTxFreq(m_lockTxFreq);
   if(m_lockTxFreq) on_pbR2T_clicked();
 }
 
-void MainWindow::on_actionTx2QSO_triggered(bool checked)
+void MainWindow::on_cbPlus2kHz_toggled(bool checked)
 {
-  m_tx2QSO=checked;
+  m_plus2kHz = checked;
+
+  if (m_config.transceiver_online (false)) // only update state if not
+                                           // starting up
+    {
+      // Upload any queued spots before changing band
+      psk_Reporter->sendReport();
+
+      auto f = m_dialFreq;
+
+      if (m_plus2kHz)
+        {
+          f += 2000;
+        }
+      else
+        {
+          f -= 2000;
+        }
+
+      m_bandEdited = true;
+      band_changed (f);
+    }
 }
 
-void MainWindow::on_cbPlus2kHz_toggled(bool checked)
+void MainWindow::handle_transceiver_update (Transceiver::TransceiverState s)
+{
+  transmitDisplay (s.ptt ());
+
+  if ((s.frequency () - m_dialFreq) || s.split () != m_splitMode)
+    {
+      m_splitMode = s.split ();
+      qsy (s.frequency ());
+    }
+
+  ui->readFreq->setStyleSheet("QPushButton{background-color: #00ff00;"
+                              "border-width: 0px; border-radius: 5px;}");
+  ui->readFreq->setText (s.split () ? "S" : "");
+}
+
+void MainWindow::handle_transceiver_failure (QString reason)
+{
+  ui->readFreq->setStyleSheet("QPushButton{background-color: red;"
+                              "border-width: 0px; border-radius: 5px;}");
+  on_stopTxButton_clicked ();
+  rigFailure ("Rig Control Error", reason);
+}
+
+void MainWindow::rigFailure (QString const& reason, QString const& detail)
+{
+  static bool first_error {true};
+  if (first_error)
+    {
+      // one automatic retry
+      QTimer::singleShot (0, this, SLOT (rigOpen ()));
+      first_error = false;
+    }
+  else
+    {
+      m_rigErrorMessageBox.setText (reason);
+      m_rigErrorMessageBox.setDetailedText (detail);
+
+      // don't call slot functions directly to avoid recursion
+      switch (m_rigErrorMessageBox.exec ())
+        {
+        case QMessageBox::Ok:
+          QTimer::singleShot (0, this, SLOT (on_actionSettings_triggered ()));
+          break;
+
+        case QMessageBox::Retry:
+          QTimer::singleShot (0, this, SLOT (rigOpen ()));
+          break;
+
+        case QMessageBox::Cancel:
+          QTimer::singleShot (0, this, SLOT (close ()));
+          break;
+        }
+      first_error = true;       // reset
+    }
+}
+
+void MainWindow::transmit (double snr)
+{
+  if (m_modeTx == "JT65")
+    {
+      Q_EMIT sendMessage (NUM_JT65_SYMBOLS, 4096.0 * 12000.0 / 11025.0, ui->TxFreqSpinBox->value () - m_XIT, m_toneSpacing, &m_soundOutput, m_config.audio_output_channel (), true, snr);
+    }
+  else
+    {
+      Q_EMIT sendMessage (NUM_JT9_SYMBOLS, m_nsps, ui->TxFreqSpinBox->value () - m_XIT, m_toneSpacing, &m_soundOutput, m_config.audio_output_channel (), true, snr);
+    }
+}
+
+void MainWindow::on_outAttenuation_valueChanged (int a)
+{
+  qreal dBAttn (a / 10.);      // slider interpreted as hundredths of a dB
+  ui->outAttenuation->setToolTip (tr ("Transmit digital gain ") + (a ? QString::number (-dBAttn, 'f', 1) : "0") + "dB");
+  Q_EMIT outAttenuationChanged (dBAttn);
+}
+
+void MainWindow::on_actionShort_list_of_add_on_prefixes_and_suffixes_triggered()
+{
+  if (!m_prefixes)
+    {
+      QFile f(":/prefixes.txt");
+      if(!f.open(QIODevice::ReadOnly | QIODevice::Text)) {
+        msgBox("Cannot open \"" + f.fileName () + "\" for reading:" + f.errorString ());
+        return;
+      }
+      m_prefixes.reset (new QTextEdit);
+      m_prefixes->setReadOnly(true);
+      m_prefixes->setFontPointSize(10);
+      m_prefixes->setWindowTitle(QApplication::applicationName () + " - " + tr ("Prefixes"));
+      m_prefixes->setGeometry(QRect(45,50,565,450));
+      Qt::WindowFlags flags = Qt::WindowCloseButtonHint |
+        Qt::WindowMinimizeButtonHint;
+      m_prefixes->setWindowFlags(flags);
+      QTextStream s(&f);
+      QString t;
+      for(int i=0; i<100; i++) {
+        t=s.readLine();
+        m_prefixes->append(t);
+        if(s.atEnd()) break;
+      }
+    }
+  m_prefixes->showNormal();
+}
+
+void MainWindow::getpfx()
+{
+  m_prefix <<"1A" <<"1S" <<"3A" <<"3B6" <<"3B8" <<"3B9" <<"3C" <<"3C0" \
+           <<"3D2" <<"3D2C" <<"3D2R" <<"3DA" <<"3V" <<"3W" <<"3X" <<"3Y" \
+           <<"3YB" <<"3YP" <<"4J" <<"4L" <<"4S" <<"4U1I" <<"4U1U" <<"4W" \
+           <<"4X" <<"5A" <<"5B" <<"5H" <<"5N" <<"5R" <<"5T" <<"5U" \
+           <<"5V" <<"5W" <<"5X" <<"5Z" <<"6W" <<"6Y" <<"7O" <<"7P" \
+           <<"7Q" <<"7X" <<"8P" <<"8Q" <<"8R" <<"9A" <<"9G" <<"9H" \
+           <<"9J" <<"9K" <<"9L" <<"9M2" <<"9M6" <<"9N" <<"9Q" <<"9U" \
+           <<"9V" <<"9X" <<"9Y" <<"A2" <<"A3" <<"A4" <<"A5" <<"A6" \
+           <<"A7" <<"A9" <<"AP" <<"BS7" <<"BV" <<"BV9" <<"BY" <<"C2" \
+           <<"C3" <<"C5" <<"C6" <<"C9" <<"CE" <<"CE0X" <<"CE0Y" <<"CE0Z" \
+           <<"CE9" <<"CM" <<"CN" <<"CP" <<"CT" <<"CT3" <<"CU" <<"CX" \
+           <<"CY0" <<"CY9" <<"D2" <<"D4" <<"D6" <<"DL" <<"DU" <<"E3" \
+           <<"E4" <<"EA" <<"EA6" <<"EA8" <<"EA9" <<"EI" <<"EK" <<"EL" \
+           <<"EP" <<"ER" <<"ES" <<"ET" <<"EU" <<"EX" <<"EY" <<"EZ" \
+           <<"F" <<"FG" <<"FH" <<"FJ" <<"FK" <<"FKC" <<"FM" <<"FO" \
+           <<"FOA" <<"FOC" <<"FOM" <<"FP" <<"FR" <<"FRG" <<"FRJ" <<"FRT" \
+           <<"FT5W" <<"FT5X" <<"FT5Z" <<"FW" <<"FY" <<"M" <<"MD" <<"MI" \
+           <<"MJ" <<"MM" <<"MU" <<"MW" <<"H4" <<"H40" <<"HA" \
+           <<"HB" <<"HB0" <<"HC" <<"HC8" <<"HH" <<"HI" <<"HK" <<"HK0A" \
+           <<"HK0M" <<"HL" <<"HM" <<"HP" <<"HR" <<"HS" <<"HV" <<"HZ" \
+           <<"I" <<"IS" <<"IS0" <<"J2" <<"J3" <<"J5" <<"J6" \
+           <<"J7" <<"J8" <<"JA" <<"JDM" <<"JDO" <<"JT" <<"JW" \
+           <<"JX" <<"JY" <<"K" <<"KG4" <<"KH0" <<"KH1" <<"KH2" <<"KH3" \
+           <<"KH4" <<"KH5" <<"KH5K" <<"KH6" <<"KH7" <<"KH8" <<"KH9" <<"KL" \
+           <<"KP1" <<"KP2" <<"KP4" <<"KP5" <<"LA" <<"LU" <<"LX" <<"LY" \
+           <<"LZ" <<"OA" <<"OD" <<"OE" <<"OH" <<"OH0" <<"OJ0" <<"OK" \
+           <<"OM" <<"ON" <<"OX" <<"OY" <<"OZ" <<"P2" <<"P4" <<"PA" \
+           <<"PJ2" <<"PJ7" <<"PY" <<"PY0F" <<"PT0S" <<"PY0T" <<"PZ" <<"R1F" \
+           <<"R1M" <<"S0" <<"S2" <<"S5" <<"S7" <<"S9" <<"SM" <<"SP" \
+           <<"ST" <<"SU" <<"SV" <<"SVA" <<"SV5" <<"SV9" <<"T2" <<"T30" \
+           <<"T31" <<"T32" <<"T33" <<"T5" <<"T7" <<"T8" <<"T9" <<"TA" \
+           <<"TF" <<"TG" <<"TI" <<"TI9" <<"TJ" <<"TK" <<"TL" \
+           <<"TN" <<"TR" <<"TT" <<"TU" <<"TY" <<"TZ" <<"UA" <<"UA2" \
+           <<"UA9" <<"UK" <<"UN" <<"UR" <<"V2" <<"V3" <<"V4" <<"V5" \
+           <<"V6" <<"V7" <<"V8" <<"VE" <<"VK" <<"VK0H" <<"VK0M" <<"VK9C" \
+           <<"VK9L" <<"VK9M" <<"VK9N" <<"VK9W" <<"VK9X" <<"VP2E" <<"VP2M" <<"VP2V" \
+           <<"VP5" <<"VP6" <<"VP6D" <<"VP8" <<"VP8G" <<"VP8H" <<"VP8O" <<"VP8S" \
+           <<"VP9" <<"VQ9" <<"VR" <<"VU" <<"VU4" <<"VU7" <<"XE" <<"XF4" \
+           <<"XT" <<"XU" <<"XW" <<"XX9" <<"XZ" <<"YA" <<"YB" <<"YI" \
+           <<"YJ" <<"YK" <<"YL" <<"YN" <<"YO" <<"YS" <<"YU" <<"YV" \
+           <<"YV0" <<"Z2" <<"Z3" <<"ZA" <<"ZB" <<"ZC4" <<"ZD7" <<"ZD8" \
+           <<"ZD9" <<"ZF" <<"ZK1N" <<"ZK1S" <<"ZK2" <<"ZK3" <<"ZL" <<"ZL7" \
+           <<"ZL8" <<"ZL9" <<"ZP" <<"ZS" <<"ZS8" <<"KC4" <<"E5";
+
+  m_suffix << "P" << "0" << "1" << "2" << "3" << "4" << "5" << "6" \
+           << "7" << "8" << "9" << "A";
+
+  for(int i=0; i<12; i++) {
+    m_sfx.insert(m_suffix[i],true);
+  }
+  for(int i=0; i<339; i++) {
+    m_pfx.insert(m_prefix[i],true);
+  }
+}
+
+bool MainWindow::shortList(QString callsign)
+{
+  int n=callsign.length();
+  int i1=callsign.indexOf("/");
+  Q_ASSERT(i1>0 and i1<n);
+  QString t1=callsign.mid(0,i1);
+  QString t2=callsign.mid(i1+1,n-i1-1);
+  bool b=(m_pfx.contains(t1) or m_sfx.contains(t2));
+  return b;
+}
+
+void MainWindow::pskSetLocal ()
+{
+  // find the station row, if any, that matches the band we are on
+  auto stations = m_config.stations ();
+  auto matches = stations->match (stations->index (0, 0)
+                                  , Qt::DisplayRole
+                                  , ui->bandComboBox->currentText ()
+                                  , 1
+                                  , Qt::MatchExactly);
+  QString antenna_description;
+  if (!matches.isEmpty ())
+    {
+      antenna_description = stations->index (matches.first ().row (), 2).data ().toString ();
+    }
+  psk_Reporter->setLocalStation(
+                                m_config.my_callsign ()
+                                , m_config.my_grid ()
+                                , antenna_description, QString {"WSJT-X v" + version() + " " + m_revision}.simplified ());
+}
+
+void MainWindow::transmitDisplay (bool transmitting)
+{
+
+  if (transmitting == m_transmitting)
+    {
+      if (transmitting)
+        {
+          signalMeter->setValue(0);
+
+          if (m_monitoring)
+            {
+              monitor (false);
+            }
+
+          m_btxok=true;
+        }
+
+      auto QSY_allowed = !transmitting || m_config.tx_QSY_allowed () || !m_config.split_mode ();
+      if (ui->cbTxLock->isChecked ())
+        {
+          ui->RxFreqSpinBox->setEnabled (QSY_allowed);
+          ui->pbT2R->setEnabled (QSY_allowed);
+        }
+      ui->TxFreqSpinBox->setEnabled (QSY_allowed);
+      ui->pbR2T->setEnabled (QSY_allowed);
+      ui->cbTxLock->setEnabled (QSY_allowed);
+
+      // only allow +2kHz when not transmitting or if TX QSYs are allowed
+      ui->cbPlus2kHz->setEnabled (!transmitting || m_config.tx_QSY_allowed ());
+
+      // the following are always disallowed in transmit
+      ui->menuMode->setEnabled (!transmitting);
+      ui->bandComboBox->setEnabled (!transmitting);
+      if (!transmitting)
+        {
+          if ("JT9+JT65" == m_mode)
+            {
+              // allow mode switch in Rx when in dual mode
+              ui->pbTxMode->setEnabled (true);
+            }
+        }
+      else
+        {
+          ui->pbTxMode->setEnabled (false);
+        }
+    }
+}
+
+// Takes a decoded CQ line and sets it up for reply
+void MainWindow::replyToCQ (QTime time, qint32 snr, float delta_time, quint32 delta_frequency, QString const& mode, QString const& message_text)
 {
-  m_plus2kHz=checked;
-  on_bandComboBox_activated(m_band);
+  if (!m_config.accept_udp_requests ())
+    {
+      return;
+    }
+
+  auto decode_parts = message_text.split (' ', QString::SkipEmptyParts);
+
+  if (decode_parts.contains ("CQ") || decode_parts.contains ("QRZ"))
+    {
+      // a message we are willing to accept
+      auto cqtext = QString {"%1 %2 %3 %4 %5 %6"}.arg (time.toString ("hhmm"))
+                                                    .arg (snr, 3)
+                                                    .arg (delta_time, 4, 'f', 1)
+                                                    .arg (delta_frequency, 4)
+                                                    .arg (mode)
+                                                    .arg (message_text);
+      auto messages = ui->decodedTextBrowser->toPlainText ();
+      auto position = messages.lastIndexOf (cqtext);
+      if (position >= 0)
+        {
+          if (m_config.udpWindowToFront ())
+            {
+              show ();
+              raise ();
+              activateWindow ();
+            }
+          if (m_config.udpWindowRestore () && isMinimized ())
+            {
+              showNormal ();
+              raise ();
+            }
+          // find the linefeed at the end of the line
+          position = ui->decodedTextBrowser->toPlainText().indexOf("\n",position);
+          processMessage (messages, position, false);
+        }
+      else
+        {
+          qDebug () << "reply to CQ request ignored, decode not found:" << cqtext;
+        }
+    }
+  else
+    {
+      qDebug () << "rejecting UDP request to reply as decode is not a CQ or QRZ";
+    }
+}
+
+void MainWindow::replayDecodes ()
+{
+  // we accept this request even if the setting to accept UDP requests
+  // is not checked
+  Q_FOREACH (auto const& message, ui->decodedTextBrowser->toPlainText ().split ('\n', QString::SkipEmptyParts))
+    {
+      if (message.size() >= 4 && message.left (4) != "----")
+        {
+          auto eom_pos = message.indexOf (' ', 35);
+          // we always want at least the characters to position 35
+          if (eom_pos < 35)
+            {
+              eom_pos = message.size () - 1;
+            }
+          postDecode (false, message.left (eom_pos + 1));
+        }
+    }
+  statusChanged ();
+}
+
+void MainWindow::postDecode (bool is_new, QString const& message)
+{
+  auto decode = message.trimmed ();
+  auto parts = decode.left (21).split (' ', QString::SkipEmptyParts);
+  if (parts.size () >= 5)
+    {
+      m_messageClient->decode (is_new, QTime::fromString (parts[0], "hhmm"), parts[1].toInt ()
+                               , parts[2].toFloat (), parts[3].toUInt (), parts[4], decode.mid (21));
+    }
+}
+
+void MainWindow::networkError (QString const& e)
+{
+  if (QMessageBox::Retry == QMessageBox::warning (this, tr ("Network Error")
+                                                  , tr ("Error: %1\nUDP server %2:%3")
+                                                  .arg (e)
+                                                  .arg (m_config.udp_server_name ())
+                                                  .arg (m_config.udp_server_port ())
+                                                  , QMessageBox::Cancel | QMessageBox::Retry, QMessageBox::Cancel))
+    {
+      // retry server lookup
+      m_messageClient->set_server (m_config.udp_server_name ());
+    }
 }
diff --git a/mainwindow.h b/mainwindow.h
index 51e0b41..0cfcbc5 100644
--- a/mainwindow.h
+++ b/mainwindow.h
@@ -1,3 +1,4 @@
+// -*- Mode: C++ -*-
 #ifndef MAINWINDOW_H
 #define MAINWINDOW_H
 #ifdef QT5
@@ -5,37 +6,74 @@
 #else
 #include <QtGui>
 #endif
+#include <QThread>
 #include <QTimer>
 #include <QDateTime>
+#include <QList>
+#include <QAudioDeviceInfo>
+#include <QScopedPointer>
+#include <QDir>
+#include <QProgressDialog>
+#include <QAbstractSocket>
+#include <QHostAddress>
+
 #include "soundin.h"
+#include "AudioDevice.hpp"
 #include "soundout.h"
 #include "commons.h"
+#include "Radio.hpp"
+#include "Configuration.hpp"
+#include "Transceiver.hpp"
 #include "psk_reporter.h"
-#include "rigclass.h"
 #include "signalmeter.h"
+#include "logbook/logbook.h"
+#include "Detector.hpp"
+#include "Modulator.hpp"
+#include "decodedtext.h"
+
+
+#define NUM_JT65_SYMBOLS 126
+#define NUM_JT9_SYMBOLS 85
+#define NUM_CW_SYMBOLS 250
+#define TX_SAMPLE_RATE 48000
+
+extern int volatile itone[NUM_JT65_SYMBOLS]; //Audio tones for all Tx symbols
+extern int volatile icw[NUM_CW_SYMBOLS];	    //Dits for CW ID
 
-#ifdef WIN32
-#include "PSKReporter.h"
-#endif
 
 //--------------------------------------------------------------- MainWindow
 namespace Ui {
-    class MainWindow;
+  class MainWindow;
 }
 
+class QSettings;
+class QLineEdit;
+class QFont;
+class QHostInfo;
+class WideGraph;
+class LogQSO;
+class Transceiver;
+class Astro;
+class MessageClient;
+class QTime;
+
 class MainWindow : public QMainWindow
 {
-  Q_OBJECT
+  Q_OBJECT;
 
-// Multiple instances: call MainWindow() with *thekey
 public:
-  explicit MainWindow(QSharedMemory *shdmem, QString *thekey, QWidget *parent = 0);
+  using Frequency = Radio::Frequency;
+
+  // Multiple instances: call MainWindow() with *thekey
+  explicit MainWindow(bool multiple, QSettings *, QSharedMemory *shdmem,
+                      unsigned downSampleFactor, QWidget *parent = 0);
   ~MainWindow();
 
 public slots:
   void showSoundInError(const QString& errorMsg);
+  void showSoundOutError(const QString& errorMsg);
   void showStatusMessage(const QString& statusMsg);
-  void dataSink(int k);
+  void dataSink(qint64 frames);
   void diskDat();
   void diskWriteFinished();
   void freezeDecode(int n);
@@ -44,7 +82,7 @@ public slots:
   void doubleClickOnCall2(bool shift, bool ctrl);
   void readFromStdout();
   void readFromStderr();
-  void jt9_error();
+  void jt9_error(QProcess::ProcessError);
   void setXIT(int n);
   void setFreq4(int rxFreq, int txFreq);
 
@@ -58,29 +96,27 @@ private slots:
   void on_tx2_editingFinished();
   void on_tx3_editingFinished();
   void on_tx4_editingFinished();
-  void on_tx5_editingFinished();
+  void on_tx5_currentTextChanged (QString const&);
   void on_tx6_editingFinished();
-  void on_actionDeviceSetup_triggered();
-  void on_monitorButton_clicked();
-  void on_actionExit_triggered();
+  void on_actionSettings_triggered();
+  void on_monitorButton_clicked (bool);
   void on_actionAbout_triggered();
-  void OnExit();
-  void on_actionLinrad_triggered();
-  void on_actionCuteSDR_triggered();
-  void on_autoButton_clicked();
+  void on_autoButton_clicked (bool);
   void on_stopTxButton_clicked();
   void on_stopButton_clicked();
-  void on_actionOnline_Users_Guide_triggered();
+  void on_actionOnline_User_Guide_triggered();
+  void on_actionLocal_User_Guide_triggered();
   void on_actionWide_Waterfall_triggered();
   void on_actionOpen_triggered();
   void on_actionOpen_next_in_directory_triggered();
   void on_actionDecode_remaining_files_in_directory_triggered();
   void on_actionDelete_all_wav_files_in_SaveDir_triggered();
+  void on_actionOpen_log_directory_triggered ();
   void on_actionNone_triggered();
   void on_actionSave_all_triggered();
   void on_actionKeyboard_shortcuts_triggered();
   void on_actionSpecial_mouse_commands_triggered();
-  void on_DecodeButton_clicked();
+  void on_DecodeButton_clicked (bool);
   void decode();
   void decodeBusy(bool b);
   void on_EraseButton_clicked();
@@ -98,8 +134,6 @@ private slots:
   void on_dxGridEntry_textChanged(const QString &arg1);
   void on_genStdMsgsPushButton_clicked();
   void on_logQSOButton_clicked();
-  void on_actionAFMHot_triggered();
-  void on_actionBlue_triggered();
   void on_actionJT9_1_triggered();
   void on_actionJT65_triggered();
   void on_actionJT9_JT65_triggered();
@@ -110,252 +144,273 @@ private slots:
   void on_actionDeepestDecode_triggered();
   void on_inGain_valueChanged(int n);
   void bumpFqso(int n);
-  void on_actionMonitor_OFF_at_startup_triggered();
   void on_actionErase_ALL_TXT_triggered();
   void on_actionErase_wsjtx_log_adi_triggered();
-  void showMacros(const QPoint& pos);
-  void onPopup1();
-  void onPopup2();
-  void onPopup3();
-  void onPopup4();
-  void onPopup5();
-  void onPopup6();
-  void onPopup7();
-  void onPopup8();
-  void onPopup9();
-  void onPopup10();
-  void on_actionConvert_JT9_x_to_RTTY_triggered(bool checked);
-  void on_actionLog_JT9_without_submode_triggered(bool checked);
-  void on_actionLog_dB_reports_to_Comments_triggered(bool checked);
   void startTx2();
   void stopTx();
   void stopTx2();
-  void on_actionPrompt_to_log_QSO_triggered(bool checked);
-  void on_actionBlank_line_between_decoding_periods_triggered(bool checked);
-  void on_actionClear_DX_Call_and_Grid_after_logging_triggered(bool checked);
-  void on_actionDisplay_distance_in_miles_triggered(bool checked);
   void on_pbCallCQ_clicked();
   void on_pbAnswerCaller_clicked();
   void on_pbSendRRR_clicked();
   void on_pbAnswerCQ_clicked();
   void on_pbSendReport_clicked();
   void on_pbSend73_clicked();
-  void on_rbGenMsg_toggled(bool checked);
-  void on_rbFreeText_toggled(bool checked);
-  void on_freeTextMsg_editingFinished();
-  void on_actionDouble_click_on_call_sets_Tx_Enable_triggered(bool checked);
+  void on_rbGenMsg_clicked(bool checked);
+  void on_rbFreeText_clicked(bool checked);
+  void on_freeTextMsg_currentTextChanged (QString const&);
   void on_rptSpinBox_valueChanged(int n);
-  void on_action_73TxDisable_triggered(bool checked);
-  void on_actionRunaway_Tx_watchdog_triggered(bool checked);
   void killFile();
-  void on_tuneButton_clicked();
-  void on_actionAllow_multiple_instances_triggered(bool checked);
+  void on_tuneButton_clicked (bool);
   void on_pbR2T_clicked();
   void on_pbT2R_clicked();
-  void acceptQSO2(bool accepted);
-  void on_bandComboBox_activated(int index);
+  void acceptQSO2(QDateTime const&, QString const& call, QString const& grid
+                  , Frequency dial_freq, QString const& mode
+                  , QString const& rpt_sent, QString const& rpt_received
+                  , QString const& tx_power, QString const& comments
+                  , QString const& name);
+  void on_bandComboBox_activated (int index);
   void on_readFreq_clicked();
   void on_pbTxMode_clicked();
   void on_RxFreqSpinBox_valueChanged(int n);
   void on_cbTxLock_clicked(bool checked);
-  void on_actionTx2QSO_triggered(bool checked);  
   void on_cbPlus2kHz_toggled(bool checked);
+  void on_outAttenuation_valueChanged (int);
+  void rigOpen ();
+  void handle_transceiver_update (Transceiver::TransceiverState);
+  void handle_transceiver_failure (QString reason);
+  void on_actionAstronomical_data_triggered();
+  void on_actionShort_list_of_add_on_prefixes_and_suffixes_triggered();
+  void getpfx();
+  void on_actionJT9W_1_triggered();
+
+  void band_changed (Frequency);
+  void monitor (bool);
+  void stop_tuning ();
+  void auto_tx_mode (bool);
+  void networkError (QString const&);
 
 private:
-    Ui::MainWindow *ui;
-
-    double  m_dialFreq;
-
-    qint64  m_msErase;
-    qint64  m_secBandChanged;
-
-    qint32  m_idInt;
-    qint32  m_waterfallAvg;
-    qint32  m_pttMethodIndex;
-    qint32  m_ntx;
-    qint32  m_pttPort;
-    qint32  m_timeout;
-    qint32  m_rxFreq;
-    qint32  m_txFreq;
-    qint32  m_setftx;
-    qint32  m_ndepth;
-    qint32  m_sec0;
-    qint32  m_RxLog;
-    qint32  m_nutc0;
-    qint32  m_nrx;
-    qint32  m_hsym;
-    qint32  m_paInDevice;
-    qint32  m_paOutDevice;
-    qint32  m_TRperiod;
-    qint32  m_nsps;
-    qint32  m_hsymStop;
-    qint32  m_len1;
-    qint32  m_inGain;
-    qint32  m_nsave;
-    qint32  m_catPortIndex;
-    qint32  m_rig;
-    qint32  m_rigIndex;
-    qint32  m_serialRate;
-    qint32  m_serialRateIndex;
-    qint32  m_dataBits;
-    qint32  m_dataBitsIndex;
-    qint32  m_stopBits;
-    qint32  m_stopBitsIndex;
-    qint32  m_handshakeIndex;
-    qint32  m_ncw;
-    qint32  m_secID;
-    qint32  m_band;
-    qint32  m_repeatMsg;
-    qint32  m_watchdogLimit;
-    qint32  m_poll;
-    qint32  m_fMin;
-    qint32  m_fMax;
-
-    bool    m_monitoring;
-    bool    m_transmitting;
-    bool    m_diskData;
-    bool    m_loopall;
-    bool    m_decoderBusy;
-    bool    m_txFirst;
-    bool    m_auto;
-    bool    m_restart;
-    bool    m_startAnother;
-    bool    m_saveDecoded;
-    bool    m_saveAll;
-    bool    m_widebandDecode;
-    bool    m_call3Modified;
-    bool    m_dataAvailable;
-    bool    m_killAll;
-    bool    m_bdecoded;
-    bool    m_monitorStartOFF;
-    bool    m_pskReporter;
-    bool    m_pskReporterInit;
-    bool    m_noSuffix;
-    bool    m_toRTTY;
-    bool    m_dBtoComments;
-    bool    m_catEnabled;
-    bool    m_After73;
-    bool    m_promptToLog;
-    bool    m_blankLine;
-    bool    m_insertBlank;
-    bool    m_clearCallGrid;
-    bool    m_bMiles;
-    bool    m_decodedText2;
-    bool    m_freeText;
-    bool    m_quickCall;
-    bool    m_73TxDisable;
-    bool    m_sent73;
-    bool    m_runaway;
-    bool    m_tune;
-    bool    m_bRigOpen;
-    bool    m_bMultipleOK;
-    bool    m_bDTRoff;
-    bool    m_pttData;
-    bool    m_dontReadFreq;
-    bool    m_lockTxFreq;
-    bool    m_saveTxPower;
-    bool    m_saveComments;
-    bool    m_tx2QSO;
-    bool    m_CATerror;
-    bool    m_bSplit;
-    bool    m_bXIT;
-    bool    m_plus2kHz;
-
-    char    m_decoded[80];
-
-    float   m_pctZap;
-
-    QRect   m_wideGraphGeom;
-    QRect   m_logQSOgeom;
-
-    QLabel* lab1;                            // labels in status bar
-    QLabel* lab2;
-    QLabel* lab3;
-    QLabel* lab4;
-    QLabel* lab5;
-    QLabel* lab6;
-
-    QMessageBox msgBox0;
-
-    QFuture<void>* future1;
-    QFuture<void>* future2;
-    QFuture<void>* future3;
-    QFutureWatcher<void>* watcher1;
-    QFutureWatcher<void>* watcher2;
-    QFutureWatcher<void>* watcher3;
-
-    QProcess proc_jt9;
-
-    QTimer* ptt1Timer;                 //StartTx delay
-    QTimer* ptt0Timer;                 //StopTx delay
-    QTimer* logQSOTimer;
-    QTimer* killFileTimer;
-    QTimer* tuneButtonTimer;
-
-    QString m_path;
-    QString m_pbdecoding_style1;
-    QString m_pbmonitor_style;
-    QString m_pbAutoOn_style;
-    QString m_pbTune_style;
-    QString m_myCall;
-    QString m_myGrid;
-    QString m_baseCall;
-    QString m_hisCall;
-    QString m_hisGrid;
-    QString m_appDir;
-    QString m_saveDir;
-    QString m_dxccPfx;
-    QString m_palette;
-    QString m_dateTime;
-    QString m_mode;
-    QString m_modeTx;
-    QString m_fname;
-    QString m_rpt;
-    QString m_rptSent;
-    QString m_rptRcvd;
-    QString m_qsoStart;
-    QString m_qsoStop;
-    QString m_catPort;
-    QString m_handshake;
-    QString m_cmnd;
-    QString m_msgSent0;
-    QString m_fileToSave;
-    QString m_QSOmsg;
-    QString m_txPower;
-    QString m_logComments;
-    QString m_pskAntenna;
-
-    QStringList m_macro;
-    QStringList m_dFreq;
-
-    QDateTime m_dateTimeQSO;
-
-    SoundInThread soundInThread;             //Instantiate the audio threads
-    SoundOutThread soundOutThread;
-    QSharedMemory *mem_jt9;
- // Multiple instances:
-    QString       *mykey_jt9;
-    PSK_Reporter *psk_Reporter;
-    SignalMeter *signalMeter;
-
-//---------------------------------------------------- private functions
-    void readSettings();
-    void writeSettings();
-    void createStatusBar();
-    void updateStatusBar();
-    void msgBox(QString t);
-    void genStdMsgs(QString rpt);
-    void lookup();
-    void ba2msg(QByteArray ba, char* message);
-    void msgtype(QString t, QLineEdit* tx);
-    void stub();
-    void statusChanged();
-    void dialFreqChanged2(double f);
-    void freeText();
-    void displayTxMsg(QString t);
-    void rigOpen();
-    bool gridOK(QString g);
-    QString baseCall(QString t);
+  void enable_DXCC_entity (bool on);
+
+  Q_SIGNAL void initializeAudioOutputStream (QAudioDeviceInfo, unsigned channels, unsigned msBuffered) const;
+  Q_SIGNAL void stopAudioOutputStream () const;
+
+  Q_SIGNAL void startAudioInputStream (QAudioDeviceInfo const&, int framesPerBuffer, AudioDevice * sink, unsigned downSampleFactor, AudioDevice::Channel) const;
+  Q_SIGNAL void suspendAudioInputStream () const;
+  Q_SIGNAL void resumeAudioInputStream () const;
+
+  Q_SIGNAL void startDetector (AudioDevice::Channel) const;
+  Q_SIGNAL void detectorClose () const;
+
+  Q_SIGNAL void finished () const;
+  Q_SIGNAL void transmitFrequency (unsigned) const;
+  Q_SIGNAL void endTransmitMessage (bool quick = false) const;
+  Q_SIGNAL void tune (bool = true) const;
+  Q_SIGNAL void sendMessage (unsigned symbolsLength, double framesPerSymbol, unsigned frequency, double toneSpacing, SoundOutput *, AudioDevice::Channel = AudioDevice::Mono, bool synchronize = true, double dBSNR = 99.) const;
+  Q_SIGNAL void outAttenuationChanged (qreal) const;
+
+private:
+  QDir m_dataDir;
+  QString m_revision;
+  bool m_multiple;
+  QSettings * m_settings;
+
+  Ui::MainWindow * ui;
+
+  // other windows
+  Configuration m_config;
+  QMessageBox m_rigErrorMessageBox;
+
+  QScopedPointer<WideGraph> m_wideGraph;
+  QScopedPointer<LogQSO> m_logDlg;
+  QScopedPointer<Astro> m_astroWidget;
+  QScopedPointer<QTextEdit> m_shortcuts;
+  QScopedPointer<QTextEdit> m_prefixes;
+  QScopedPointer<QTextEdit> m_mouseCmnds;
+
+  Frequency  m_dialFreq;
+
+  Detector m_detector;
+  SoundInput m_soundInput;
+  Modulator m_modulator;
+  SoundOutput m_soundOutput;
+  QThread * m_audioThread;
+
+  qint64  m_msErase;
+  qint64  m_secBandChanged;
+
+  qint32  m_waterfallAvg;
+  qint32  m_ntx;
+  qint32  m_timeout;
+  qint32  m_XIT;
+  qint32  m_setftx;
+  qint32  m_ndepth;
+  qint32  m_sec0;
+  qint32  m_RxLog;
+  qint32  m_nutc0;
+  qint32  m_nrx;
+  qint32  m_hsym;
+  qint32  m_TRperiod;
+  qint32  m_nsps;
+  qint32  m_hsymStop;
+  qint32  m_len1;
+  qint32  m_inGain;
+  qint32  m_nsave;
+  qint32  m_ncw;
+  qint32  m_secID;
+  qint32  m_repeatMsg;
+  qint32  m_watchdogLimit;
+  qint32  m_astroFont;
+
+  bool    m_btxok;		//True if OK to transmit
+  bool    m_diskData;
+  bool    m_loopall;
+  bool    m_decoderBusy;
+  bool    m_txFirst;
+  bool    m_auto;
+  bool    m_restart;
+  bool    m_startAnother;
+  bool    m_saveDecoded;
+  bool    m_saveAll;
+  bool    m_widebandDecode;
+  bool    m_call3Modified;
+  bool    m_dataAvailable;
+  bool    m_killAll;
+  bool    m_bdecoded;
+  bool    m_monitorStartOFF;
+  bool    m_pskReporterInit;
+  bool    m_noSuffix;
+  bool    m_toRTTY;
+  bool    m_dBtoComments;
+  bool    m_promptToLog;
+  bool    m_blankLine;
+  bool    m_insertBlank;
+  bool    m_displayDXCCEntity;
+  bool    m_clearCallGrid;
+  bool    m_bMiles;
+  bool    m_decodedText2;
+  bool    m_freeText;
+  bool    m_quickCall;
+  bool    m_73TxDisable;
+  bool    m_sentFirst73;
+  int     m_currentMessageType;
+  QString m_currentMessage;
+  int     m_lastMessageType;
+  QString m_lastMessageSent;
+  bool    m_runaway;
+  bool    m_bMultipleOK;
+  bool    m_lockTxFreq;
+  bool    m_tx2QSO;
+  bool    m_CATerror;
+  bool    m_plus2kHz;
+  bool    m_bAstroData;
+
+  float   m_pctZap;
+
+  // labels in status bar
+  QLabel * tx_status_label;
+  QLabel * mode_label;
+  QLabel * last_tx_label;
+  QLabel * auto_tx_label;
+
+  QMessageBox msgBox0;
+
+  QFuture<void>* future1;
+  QFuture<void>* future2;
+  QFuture<void>* future3;
+  QFutureWatcher<void>* watcher1;
+  QFutureWatcher<void>* watcher2;
+  QFutureWatcher<void>* watcher3;
+
+  QProcess proc_jt9;
+
+  QTimer m_guiTimer;
+  QTimer* ptt1Timer;                 //StartTx delay
+  QTimer* ptt0Timer;                 //StopTx delay
+  QTimer* logQSOTimer;
+  QTimer* killFileTimer;
+  QTimer* tuneButtonTimer;
+
+  QString m_path;
+  QString m_pbdecoding_style1;
+  QString m_pbmonitor_style;
+  QString m_pbAutoOn_style;
+  QString m_pbTune_style;
+  QString m_baseCall;
+  QString m_hisCall;
+  QString m_hisGrid;
+  QString m_appDir;
+  QString m_dxccPfx;
+  QString m_palette;
+  QString m_dateTime;
+  QString m_mode;
+  QString m_modeTx;
+  QString m_fname;
+  QString m_rpt;
+  QString m_rptSent;
+  QString m_rptRcvd;
+  QString m_qsoStart;
+  QString m_qsoStop;
+  QString m_cmnd;
+  QString m_msgSent0;
+  QString m_fileToSave;
+  QString  m_band;
+
+  QStringList m_prefix;
+  QStringList m_suffix;
+
+  QHash<QString,bool> m_pfx;
+  QHash<QString,bool> m_sfx;
+
+  QDateTime m_dateTimeQSO;
+  QRect   m_astroGeom;
+
+  QSharedMemory *mem_jt9;
+  SignalMeter *signalMeter;
+  LogBook m_logBook;
+  DecodedText m_QSOText;
+  unsigned m_msAudioOutputBuffered;
+  unsigned m_framesAudioInputBuffered;
+  unsigned m_downSampleFactor;
+  QThread::Priority m_audioThreadPriority;
+  bool m_bandEdited;
+  bool m_splitMode;
+  bool m_monitoring;
+  bool m_transmitting;
+  bool m_tune;
+  Frequency m_lastMonitoredFrequency;
+  double m_toneSpacing;
+  int m_firstDecode;
+  QProgressDialog m_optimizingProgress;
+  QTimer m_heartbeat;
+  MessageClient * m_messageClient;
+  PSK_Reporter *psk_Reporter;
+
+  //---------------------------------------------------- private functions
+  void readSettings();
+  void setDecodedTextFont (QFont const&);
+  void writeSettings();
+  void createStatusBar();
+  void updateStatusBar();
+  void msgBox(QString t);
+  void genStdMsgs(QString rpt);
+  void lookup();
+  void ba2msg(QByteArray ba, char* message);
+  void msgtype(QString t, QLineEdit* tx);
+  void stub();
+  void statusChanged();
+  void qsy(Frequency f);
+  bool gridOK(QString g);
+  bool shortList(QString callsign);
+  void transmit (double snr = 99.);
+  void rigFailure (QString const& reason, QString const& detail);
+  void pskSetLocal ();
+  void displayDialFrequency ();
+  void transmitDisplay (bool);
+  void processMessage(QString const& messages, qint32 position, bool ctrl);
+  void replyToCQ (QTime, qint32 snr, float delta_time, quint32 delta_frequency, QString const& mode, QString const& message_text);
+  void replayDecodes ();
+  void postDecode (bool is_new, QString const& message);
 };
 
 extern void getfile(QString fname, int ntrperiod);
@@ -367,25 +422,28 @@ extern void getDev(int* numDevices,char hostAPI_DeviceName[][50],
 extern int ptt(int nport, int ntx, int* iptt, int* nopen);
 
 extern "C" {
-//----------------------------------------------------- C and Fortran routines
-void symspec_(int* k, int* ntrperiod, int* nsps, int* ingain, float* slope,
-              float* px, float s[], float* df3, int* nhsym, int* npts8);
+  //----------------------------------------------------- C and Fortran routines
+  void symspec_(int* k, int* ntrperiod, int* nsps, int* ingain, int* nflatten,
+                float* px, float s[], float* df3, int* nhsym, int* npts8);
+
+  void genjt9_(char* msg, int* ichk, char* msgsent, int itone[],
+               int* itext, int len1, int len2);
 
-void genjt9_(char* msg, int* ichk, char* msgsent, int itone[],
-             int* itext, int len1, int len2);
+  void gen65_(char* msg, int* ichk, char* msgsent, int itone[],
+              int* itext, int len1, int len2);
 
-void gen65_(char* msg, int* ichk, char* msgsent, int itone[],
-             int* itext, int len1, int len2);
+  bool stdmsg_(const char* msg, int len);
 
-bool stdmsg_(const char* msg, int len);
+  void azdist_(char* MyGrid, char* HisGrid, double* utch, int* nAz, int* nEl,
+               int* nDmiles, int* nDkm, int* nHotAz, int* nHotABetter,
+               int len1, int len2);
 
-void azdist_(char* MyGrid, char* HisGrid, double* utch, int* nAz, int* nEl,
-             int* nDmiles, int* nDkm, int* nHotAz, int* nHotABetter,
-             int len1, int len2);
+  void morse_(char* msg, int* icw, int* ncw, int len);
 
-void morse_(char* msg, int* icw, int* ncw, int len);
+  int ptt_(int nport, int ntx, int* iptt, int* nopen);
 
-int ptt_(int nport, int ntx, int* iptt, int* nopen);
+  int fftwf_import_wisdom_from_filename(const char *);
+  int fftwf_export_wisdom_to_filename(const char *);
 
 }
 
diff --git a/mainwindow.ui b/mainwindow.ui
index 5c58f21..ec973b5 100644
--- a/mainwindow.ui
+++ b/mainwindow.ui
@@ -6,8 +6,8 @@
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>760</width>
-    <height>552</height>
+    <width>770</width>
+    <height>541</height>
    </rect>
   </property>
   <property name="sizePolicy">
@@ -18,24 +18,39 @@
   </property>
   <property name="minimumSize">
    <size>
-    <width>760</width>
-    <height>475</height>
+    <width>770</width>
+    <height>440</height>
    </size>
   </property>
   <property name="maximumSize">
    <size>
-    <width>936</width>
+    <width>1280</width>
     <height>1028</height>
    </size>
   </property>
   <property name="windowTitle">
-   <string>SpecJT   by K1JT</string>
+   <string>WSJT-X   by K1JT</string>
   </property>
   <property name="styleSheet">
    <string notr="true"/>
   </property>
   <widget class="QWidget" name="centralWidget">
    <layout class="QVBoxLayout" name="verticalLayout">
+    <property name="spacing">
+     <number>0</number>
+    </property>
+    <property name="leftMargin">
+     <number>0</number>
+    </property>
+    <property name="topMargin">
+     <number>0</number>
+    </property>
+    <property name="rightMargin">
+     <number>0</number>
+    </property>
+    <property name="bottomMargin">
+     <number>0</number>
+    </property>
     <item>
      <layout class="QGridLayout" name="gridLayout">
       <property name="horizontalSpacing">
@@ -44,56 +59,6 @@
       <property name="verticalSpacing">
        <number>1</number>
       </property>
-      <item row="4" column="0">
-       <widget class="DisplayText" name="decodedTextBrowser">
-        <property name="sizePolicy">
-         <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
-          <horstretch>0</horstretch>
-          <verstretch>0</verstretch>
-         </sizepolicy>
-        </property>
-        <property name="minimumSize">
-         <size>
-          <width>200</width>
-          <height>100</height>
-         </size>
-        </property>
-        <property name="maximumSize">
-         <size>
-          <width>500</width>
-          <height>1000</height>
-         </size>
-        </property>
-        <property name="font">
-         <font>
-          <family>Courier New</family>
-          <pointsize>10</pointsize>
-         </font>
-        </property>
-        <property name="frameShape">
-         <enum>QFrame::Panel</enum>
-        </property>
-        <property name="verticalScrollBarPolicy">
-         <enum>Qt::ScrollBarAlwaysOn</enum>
-        </property>
-        <property name="horizontalScrollBarPolicy">
-         <enum>Qt::ScrollBarAlwaysOff</enum>
-        </property>
-        <property name="html">
-         <string notr="true"><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
-<html><head><meta name="qrichtext" content="1" /><style type="text/css">
-p, li { white-space: pre-wrap; }
-</style></head><body style=" font-family:'Courier New'; font-size:10pt; font-weight:400; font-style:normal;">
-<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html></string>
-        </property>
-        <property name="acceptRichText">
-         <bool>false</bool>
-        </property>
-        <property name="openLinks">
-         <bool>false</bool>
-        </property>
-       </widget>
-      </item>
       <item row="3" column="1">
        <widget class="QLabel" name="decodedTextLabel2">
         <property name="minimumSize">
@@ -104,7 +69,7 @@ p, li { white-space: pre-wrap; }
         </property>
         <property name="maximumSize">
          <size>
-          <width>500</width>
+          <width>600</width>
           <height>20</height>
          </size>
         </property>
@@ -178,6 +143,9 @@ p, li { white-space: pre-wrap; }
         <property name="text">
          <string>UTC           dB            DT           Freq          Dr </string>
         </property>
+        <property name="textFormat">
+         <enum>Qt::PlainText</enum>
+        </property>
         <property name="indent">
          <number>5</number>
         </property>
@@ -193,7 +161,7 @@ p, li { white-space: pre-wrap; }
         </property>
         <property name="maximumSize">
          <size>
-          <width>500</width>
+          <width>600</width>
           <height>20</height>
          </size>
         </property>
@@ -267,45 +235,14 @@ p, li { white-space: pre-wrap; }
         <property name="text">
          <string>UTC           dB            DT           Freq          Dr </string>
         </property>
+        <property name="textFormat">
+         <enum>Qt::PlainText</enum>
+        </property>
         <property name="indent">
          <number>5</number>
         </property>
        </widget>
       </item>
-      <item row="4" column="1">
-       <widget class="DisplayText" name="decodedTextBrowser2">
-        <property name="sizePolicy">
-         <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
-          <horstretch>0</horstretch>
-          <verstretch>0</verstretch>
-         </sizepolicy>
-        </property>
-        <property name="minimumSize">
-         <size>
-          <width>200</width>
-          <height>100</height>
-         </size>
-        </property>
-        <property name="maximumSize">
-         <size>
-          <width>500</width>
-          <height>1000</height>
-         </size>
-        </property>
-        <property name="font">
-         <font>
-          <family>Courier New</family>
-          <pointsize>10</pointsize>
-         </font>
-        </property>
-        <property name="verticalScrollBarPolicy">
-         <enum>Qt::ScrollBarAlwaysOn</enum>
-        </property>
-        <property name="horizontalScrollBarPolicy">
-         <enum>Qt::ScrollBarAlwaysOff</enum>
-        </property>
-       </widget>
-      </item>
       <item row="1" column="1">
        <widget class="QLabel" name="label_7">
         <property name="maximumSize">
@@ -372,6 +309,65 @@ p, li { white-space: pre-wrap; }
         </property>
        </widget>
       </item>
+      <item row="4" column="0">
+       <widget class="DisplayText" name="decodedTextBrowser">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+          <horstretch>0</horstretch>
+          <verstretch>1</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="minimumSize">
+         <size>
+          <width>200</width>
+          <height>100</height>
+         </size>
+        </property>
+        <property name="frameShape">
+         <enum>QFrame::Panel</enum>
+        </property>
+        <property name="verticalScrollBarPolicy">
+         <enum>Qt::ScrollBarAlwaysOn</enum>
+        </property>
+        <property name="horizontalScrollBarPolicy">
+         <enum>Qt::ScrollBarAsNeeded</enum>
+        </property>
+        <property name="cursorWidth">
+         <number>0</number>
+        </property>
+        <property name="textInteractionFlags">
+         <set>Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+        </property>
+       </widget>
+      </item>
+      <item row="4" column="1">
+       <widget class="DisplayText" name="decodedTextBrowser2">
+        <property name="enabled">
+         <bool>true</bool>
+        </property>
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+          <horstretch>0</horstretch>
+          <verstretch>1</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="minimumSize">
+         <size>
+          <width>200</width>
+          <height>100</height>
+         </size>
+        </property>
+        <property name="verticalScrollBarPolicy">
+         <enum>Qt::ScrollBarAlwaysOn</enum>
+        </property>
+        <property name="cursorWidth">
+         <number>0</number>
+        </property>
+        <property name="textInteractionFlags">
+         <set>Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+        </property>
+       </widget>
+      </item>
      </layout>
     </item>
     <item>
@@ -410,30 +406,35 @@ p, li { white-space: pre-wrap; }
       </item>
       <item>
        <widget class="QPushButton" name="monitorButton">
-        <property name="sizePolicy">
-         <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
-          <horstretch>0</horstretch>
-          <verstretch>0</verstretch>
-         </sizepolicy>
-        </property>
         <property name="minimumSize">
          <size>
           <width>50</width>
           <height>0</height>
          </size>
         </property>
-        <property name="maximumSize">
-         <size>
-          <width>16777215</width>
-          <height>16777215</height>
-         </size>
-        </property>
         <property name="toolTip">
          <string>Start monitoring</string>
         </property>
+        <property name="styleSheet">
+         <string notr="true">QPushButton:checked {
+	background-color: #00ff00;
+    border-style: outset;
+	border-width: 1px;
+	border-radius: 5px;
+    border-color: black;
+	min-width: 5em;
+	padding: 3px;
+}</string>
+        </property>
         <property name="text">
          <string>&Monitor</string>
         </property>
+        <property name="checkable">
+         <bool>true</bool>
+        </property>
+        <property name="checked">
+         <bool>false</bool>
+        </property>
        </widget>
       </item>
       <item>
@@ -461,21 +462,29 @@ p, li { white-space: pre-wrap; }
          </size>
         </property>
         <property name="toolTip">
-         <string>Decode most recent Rx period at QSO Frequency (use shift for all freqs)</string>
+         <string><html><head/><body><p>Decode most recent Rx period at QSO Frequency</p></body></html></string>
+        </property>
+        <property name="styleSheet">
+         <string notr="true">QPushButton:checked {
+	background-color: cyan;
+	border-style: outset;
+	border-width: 1px;
+	border-radius: 5px;
+	border-color: black;
+	min-width: 5em;
+	padding: 3px;
+}</string>
         </property>
         <property name="text">
          <string>&Decode</string>
         </property>
+        <property name="checkable">
+         <bool>true</bool>
+        </property>
        </widget>
       </item>
       <item>
        <widget class="QPushButton" name="autoButton">
-        <property name="sizePolicy">
-         <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
-          <horstretch>0</horstretch>
-          <verstretch>0</verstretch>
-         </sizepolicy>
-        </property>
         <property name="minimumSize">
          <size>
           <width>50</width>
@@ -485,19 +494,27 @@ p, li { white-space: pre-wrap; }
         <property name="toolTip">
          <string>Toggle Tx Enable On/Off</string>
         </property>
+        <property name="styleSheet">
+         <string notr="true">QPushButton:checked {
+	background-color: red;
+	border-style: outset;
+	border-width: 1px;
+	border-radius: 5px;
+	border-color: black;
+	min-width: 5em;
+	padding: 3px;
+}</string>
+        </property>
         <property name="text">
          <string>E&nable Tx</string>
         </property>
+        <property name="checkable">
+         <bool>true</bool>
+        </property>
        </widget>
       </item>
       <item>
        <widget class="QPushButton" name="stopTxButton">
-        <property name="sizePolicy">
-         <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
-          <horstretch>0</horstretch>
-          <verstretch>0</verstretch>
-         </sizepolicy>
-        </property>
         <property name="minimumSize">
          <size>
           <width>50</width>
@@ -515,30 +532,77 @@ p, li { white-space: pre-wrap; }
       <item>
        <widget class="QPushButton" name="tuneButton">
         <property name="toolTip">
-         <string>Assert PTT and emit a pure tone</string>
+         <string><html><head/><body><p>Transmit a pure tone</p></body></html></string>
+        </property>
+        <property name="styleSheet">
+         <string notr="true">QPushButton:checked {
+	background-color: red;
+	border-style: outset;
+	border-width: 1px;
+	border-radius: 5px;
+	border-color: black;
+	min-width: 5em;
+	padding: 3px;
+}</string>
         </property>
         <property name="text">
          <string>&Tune</string>
         </property>
+        <property name="checkable">
+         <bool>true</bool>
+        </property>
        </widget>
       </item>
      </layout>
     </item>
     <item>
      <layout class="QGridLayout" name="gridLayout_3">
-      <item row="2" column="0" rowspan="5">
-       <widget class="QFrame" name="meterFrame">
+      <property name="leftMargin">
+       <number>9</number>
+      </property>
+      <property name="rightMargin">
+       <number>9</number>
+      </property>
+      <property name="verticalSpacing">
+       <number>0</number>
+      </property>
+      <item row="2" column="6">
+       <widget class="QSpinBox" name="TxFreqSpinBox">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
         <property name="minimumSize">
          <size>
-          <width>50</width>
+          <width>113</width>
           <height>0</height>
          </size>
         </property>
-        <property name="frameShape">
-         <enum>QFrame::StyledPanel</enum>
+        <property name="maximumSize">
+         <size>
+          <width>105</width>
+          <height>16777215</height>
+         </size>
         </property>
-        <property name="frameShadow">
-         <enum>QFrame::Raised</enum>
+        <property name="toolTip">
+         <string>Audio Tx frequency</string>
+        </property>
+        <property name="suffix">
+         <string>  Hz</string>
+        </property>
+        <property name="prefix">
+         <string>Tx  </string>
+        </property>
+        <property name="minimum">
+         <number>200</number>
+        </property>
+        <property name="maximum">
+         <number>5000</number>
+        </property>
+        <property name="value">
+         <number>1500</number>
         </property>
        </widget>
       </item>
@@ -576,114 +640,92 @@ p, li { white-space: pre-wrap; }
         </property>
        </widget>
       </item>
-      <item row="0" column="0" colspan="2">
-       <widget class="QComboBox" name="bandComboBox">
+      <item row="4" column="4">
+       <widget class="QPushButton" name="addButton">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="maximumSize">
+         <size>
+          <width>74</width>
+          <height>16777215</height>
+         </size>
+        </property>
         <property name="toolTip">
-         <string>Select operating band</string>
+         <string>Add callsign and locator to database</string>
         </property>
-        <property name="currentIndex">
-         <number>7</number>
+        <property name="text">
+         <string>Add</string>
         </property>
-        <item>
-         <property name="text">
-          <string>2200 m</string>
-         </property>
-        </item>
-        <item>
-         <property name="text">
-          <string>630 m</string>
-         </property>
-        </item>
-        <item>
-         <property name="text">
-          <string>160 m</string>
-         </property>
-        </item>
-        <item>
-         <property name="text">
-          <string>80 m</string>
-         </property>
-        </item>
-        <item>
-         <property name="text">
-          <string>60 m</string>
-         </property>
-        </item>
-        <item>
-         <property name="text">
-          <string>40 m</string>
-         </property>
-        </item>
-        <item>
-         <property name="text">
-          <string>30 m</string>
-         </property>
-        </item>
-        <item>
-         <property name="text">
-          <string>20 m</string>
-         </property>
-        </item>
-        <item>
-         <property name="text">
-          <string>17 m</string>
-         </property>
-        </item>
-        <item>
-         <property name="text">
-          <string>15 m</string>
-         </property>
-        </item>
-        <item>
-         <property name="text">
-          <string>12 m</string>
-         </property>
-        </item>
-        <item>
-         <property name="text">
-          <string>10 m</string>
-         </property>
-        </item>
-        <item>
-         <property name="text">
-          <string>6 m</string>
-         </property>
-        </item>
-        <item>
-         <property name="text">
-          <string>4 m</string>
-         </property>
-        </item>
-        <item>
-         <property name="text">
-          <string>2 m</string>
-         </property>
-        </item>
-        <item>
-         <property name="text">
-          <string>Other</string>
-         </property>
-        </item>
        </widget>
       </item>
-      <item row="0" column="2">
-       <widget class="QPushButton" name="readFreq">
-        <property name="maximumSize">
+      <item row="3" column="4">
+       <widget class="QLabel" name="labDist">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Preferred" vsizetype="Minimum">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="minimumSize">
          <size>
-          <width>15</width>
-          <height>15</height>
+          <width>0</width>
+          <height>23</height>
          </size>
         </property>
-        <property name="toolTip">
-         <string>If orange, click to read dial frequency once</string>
+        <property name="maximumSize">
+         <size>
+          <width>16777215</width>
+          <height>23</height>
+         </size>
         </property>
         <property name="text">
          <string/>
         </property>
+        <property name="alignment">
+         <set>Qt::AlignCenter</set>
+        </property>
        </widget>
       </item>
-      <item row="0" column="3" colspan="2">
-       <widget class="QLabel" name="labDialFreq">
+      <item row="3" column="6">
+       <widget class="QSpinBox" name="RxFreqSpinBox">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="minimumSize">
+         <size>
+          <width>113</width>
+          <height>20</height>
+         </size>
+        </property>
+        <property name="toolTip">
+         <string>Audio Rx frequency</string>
+        </property>
+        <property name="suffix">
+         <string>  Hz</string>
+        </property>
+        <property name="prefix">
+         <string>Rx  </string>
+        </property>
+        <property name="minimum">
+         <number>200</number>
+        </property>
+        <property name="maximum">
+         <number>5000</number>
+        </property>
+        <property name="value">
+         <number>1500</number>
+        </property>
+       </widget>
+      </item>
+      <item row="1" column="4">
+       <widget class="QLabel" name="label_4">
         <property name="sizePolicy">
          <sizepolicy hsizetype="Preferred" vsizetype="Minimum">
           <horstretch>0</horstretch>
@@ -692,958 +734,261 @@ p, li { white-space: pre-wrap; }
         </property>
         <property name="minimumSize">
          <size>
-          <width>140</width>
-          <height>30</height>
+          <width>0</width>
+          <height>23</height>
          </size>
         </property>
         <property name="maximumSize">
          <size>
-          <width>158</width>
+          <width>16777215</width>
           <height>16777215</height>
          </size>
         </property>
-        <property name="font">
-         <font>
-          <pointsize>16</pointsize>
-          <weight>50</weight>
-          <bold>false</bold>
-         </font>
+        <property name="palette">
+         <palette>
+          <active>
+           <colorrole role="Base">
+            <brush brushstyle="SolidPattern">
+             <color alpha="255">
+              <red>252</red>
+              <green>252</green>
+              <blue>252</blue>
+             </color>
+            </brush>
+           </colorrole>
+           <colorrole role="Window">
+            <brush brushstyle="SolidPattern">
+             <color alpha="255">
+              <red>159</red>
+              <green>175</green>
+              <blue>213</blue>
+             </color>
+            </brush>
+           </colorrole>
+          </active>
+          <inactive>
+           <colorrole role="Base">
+            <brush brushstyle="SolidPattern">
+             <color alpha="255">
+              <red>252</red>
+              <green>252</green>
+              <blue>252</blue>
+             </color>
+            </brush>
+           </colorrole>
+           <colorrole role="Window">
+            <brush brushstyle="SolidPattern">
+             <color alpha="255">
+              <red>159</red>
+              <green>175</green>
+              <blue>213</blue>
+             </color>
+            </brush>
+           </colorrole>
+          </inactive>
+          <disabled>
+           <colorrole role="Base">
+            <brush brushstyle="SolidPattern">
+             <color alpha="255">
+              <red>159</red>
+              <green>175</green>
+              <blue>213</blue>
+             </color>
+            </brush>
+           </colorrole>
+           <colorrole role="Window">
+            <brush brushstyle="SolidPattern">
+             <color alpha="255">
+              <red>159</red>
+              <green>175</green>
+              <blue>213</blue>
+             </color>
+            </brush>
+           </colorrole>
+          </disabled>
+         </palette>
         </property>
-        <property name="toolTip">
-         <string>USB dial frequency</string>
+        <property name="autoFillBackground">
+         <bool>true</bool>
         </property>
         <property name="text">
-         <string>14.078</string>
+         <string>DX Grid</string>
         </property>
         <property name="alignment">
          <set>Qt::AlignCenter</set>
         </property>
+        <property name="indent">
+         <number>2</number>
+        </property>
        </widget>
       </item>
-      <item row="0" column="6">
-       <widget class="QCheckBox" name="txFirstCheckBox">
+      <item row="2" column="3">
+       <widget class="QLineEdit" name="dxCallEntry">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
         <property name="minimumSize">
          <size>
-          <width>105</width>
-          <height>23</height>
+          <width>70</width>
+          <height>27</height>
          </size>
         </property>
         <property name="maximumSize">
          <size>
-          <width>105</width>
+          <width>74</width>
           <height>16777215</height>
          </size>
         </property>
         <property name="toolTip">
-         <string>Check to Tx in even minutes, uncheck for odd minutes</string>
+         <string>Callsign of station to be worked</string>
         </property>
         <property name="text">
-         <string>Tx even</string>
+         <string/>
+        </property>
+        <property name="alignment">
+         <set>Qt::AlignCenter</set>
         </property>
        </widget>
       </item>
-      <item row="0" column="8" rowspan="7">
-       <widget class="QFrame" name="frame_2">
+      <item row="4" column="3">
+       <widget class="QPushButton" name="lookupButton">
         <property name="sizePolicy">
-         <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+         <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
           <horstretch>0</horstretch>
           <verstretch>0</verstretch>
          </sizepolicy>
         </property>
+        <property name="maximumSize">
+         <size>
+          <width>74</width>
+          <height>16777215</height>
+         </size>
+        </property>
+        <property name="toolTip">
+         <string>Search for callsign in database</string>
+        </property>
+        <property name="text">
+         <string>&Lookup</string>
+        </property>
+       </widget>
+      </item>
+      <item row="2" column="0" rowspan="5">
+       <widget class="QFrame" name="meterFrame">
         <property name="minimumSize">
          <size>
-          <width>283</width>
-          <height>222</height>
+          <width>50</width>
+          <height>0</height>
          </size>
         </property>
         <property name="frameShape">
-         <enum>QFrame::NoFrame</enum>
+         <enum>QFrame::StyledPanel</enum>
         </property>
         <property name="frameShadow">
-         <enum>QFrame::Plain</enum>
+         <enum>QFrame::Raised</enum>
         </property>
-        <property name="lineWidth">
-         <number>0</number>
+       </widget>
+      </item>
+      <item row="0" column="3" colspan="2">
+       <widget class="QLabel" name="labDialFreq">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Preferred" vsizetype="Minimum">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="minimumSize">
+         <size>
+          <width>140</width>
+          <height>30</height>
+         </size>
+        </property>
+        <property name="maximumSize">
+         <size>
+          <width>158</width>
+          <height>16777215</height>
+         </size>
+        </property>
+        <property name="toolTip">
+         <string>USB dial frequency</string>
+        </property>
+        <property name="styleSheet">
+         <string notr="true">QLabel {
+  font-family: MS Shell Dlg 2;
+  font-size: 16pt;
+   color : yellow;
+   background-color : black;
+}
+QLabel[oob="true"] {
+  background-color: red;
+}
+</string>
         </property>
-        <layout class="QVBoxLayout" name="verticalLayout_2">
-         <property name="spacing">
-          <number>0</number>
-         </property>
-         <property name="margin">
-          <number>0</number>
-         </property>
-         <item>
-          <widget class="QTabWidget" name="tabWidget">
-           <property name="sizePolicy">
-            <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
-             <horstretch>0</horstretch>
-             <verstretch>0</verstretch>
-            </sizepolicy>
-           </property>
-           <property name="minimumSize">
-            <size>
-             <width>0</width>
-             <height>200</height>
-            </size>
-           </property>
-           <property name="tabPosition">
-            <enum>QTabWidget::West</enum>
-           </property>
-           <property name="tabShape">
-            <enum>QTabWidget::Triangular</enum>
-           </property>
-           <property name="currentIndex">
-            <number>0</number>
-           </property>
-           <widget class="QWidget" name="tab">
-            <attribute name="title">
-             <string>1</string>
-            </attribute>
-            <layout class="QVBoxLayout" name="verticalLayout_4">
-             <property name="spacing">
-              <number>6</number>
-             </property>
-             <property name="leftMargin">
-              <number>4</number>
-             </property>
-             <property name="topMargin">
-              <number>1</number>
-             </property>
-             <property name="rightMargin">
-              <number>0</number>
-             </property>
-             <property name="bottomMargin">
-              <number>0</number>
-             </property>
-             <item>
-              <layout class="QGridLayout" name="gridLayout_2">
-               <property name="horizontalSpacing">
-                <number>6</number>
-               </property>
-               <property name="verticalSpacing">
-                <number>5</number>
-               </property>
-               <item row="1" column="2">
-                <widget class="QPushButton" name="txb1">
-                 <property name="maximumSize">
-                  <size>
-                   <width>40</width>
-                   <height>16777215</height>
-                  </size>
-                 </property>
-                 <property name="toolTip">
-                  <string>Switch to this Tx message NOW</string>
-                 </property>
-                 <property name="layoutDirection">
-                  <enum>Qt::LeftToRight</enum>
-                 </property>
-                 <property name="text">
-                  <string>Tx 1</string>
-                 </property>
-                </widget>
-               </item>
-               <item row="4" column="1">
-                <widget class="QRadioButton" name="txrb4">
-                 <property name="sizePolicy">
-                  <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-                   <horstretch>16</horstretch>
-                   <verstretch>0</verstretch>
-                  </sizepolicy>
-                 </property>
-                 <property name="minimumSize">
-                  <size>
-                   <width>0</width>
-                   <height>20</height>
-                  </size>
-                 </property>
-                 <property name="maximumSize">
-                  <size>
-                   <width>20</width>
-                   <height>16777215</height>
-                  </size>
-                 </property>
-                 <property name="toolTip">
-                  <string>Send this message in next Tx interval</string>
-                 </property>
-                 <property name="text">
-                  <string/>
-                 </property>
-                 <attribute name="buttonGroup">
-                  <string>buttonGroup</string>
-                 </attribute>
-                </widget>
-               </item>
-               <item row="1" column="1">
-                <widget class="QRadioButton" name="txrb1">
-                 <property name="sizePolicy">
-                  <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
-                   <horstretch>16</horstretch>
-                   <verstretch>0</verstretch>
-                  </sizepolicy>
-                 </property>
-                 <property name="minimumSize">
-                  <size>
-                   <width>0</width>
-                   <height>20</height>
-                  </size>
-                 </property>
-                 <property name="maximumSize">
-                  <size>
-                   <width>20</width>
-                   <height>16777215</height>
-                  </size>
-                 </property>
-                 <property name="toolTip">
-                  <string>Send this message in next Tx interval</string>
-                 </property>
-                 <property name="text">
-                  <string/>
-                 </property>
-                 <property name="checked">
-                  <bool>true</bool>
-                 </property>
-                 <attribute name="buttonGroup">
-                  <string>buttonGroup</string>
-                 </attribute>
-                </widget>
-               </item>
-               <item row="3" column="1">
-                <widget class="QRadioButton" name="txrb3">
-                 <property name="sizePolicy">
-                  <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-                   <horstretch>16</horstretch>
-                   <verstretch>0</verstretch>
-                  </sizepolicy>
-                 </property>
-                 <property name="minimumSize">
-                  <size>
-                   <width>0</width>
-                   <height>20</height>
-                  </size>
-                 </property>
-                 <property name="maximumSize">
-                  <size>
-                   <width>20</width>
-                   <height>16777215</height>
-                  </size>
-                 </property>
-                 <property name="toolTip">
-                  <string>Send this message in next Tx interval</string>
-                 </property>
-                 <property name="text">
-                  <string/>
-                 </property>
-                 <attribute name="buttonGroup">
-                  <string>buttonGroup</string>
-                 </attribute>
-                </widget>
-               </item>
-               <item row="1" column="0">
-                <widget class="QLineEdit" name="tx1">
-                 <property name="sizePolicy">
-                  <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
-                   <horstretch>200</horstretch>
-                   <verstretch>0</verstretch>
-                  </sizepolicy>
-                 </property>
-                 <property name="minimumSize">
-                  <size>
-                   <width>150</width>
-                   <height>24</height>
-                  </size>
-                 </property>
-                 <property name="maximumSize">
-                  <size>
-                   <width>150</width>
-                   <height>16777215</height>
-                  </size>
-                 </property>
-                 <property name="font">
-                  <font>
-                   <family>Droid Sans</family>
-                   <weight>50</weight>
-                   <bold>false</bold>
-                  </font>
-                 </property>
-                 <property name="text">
-                  <string/>
-                 </property>
-                </widget>
-               </item>
-               <item row="3" column="2">
-                <widget class="QPushButton" name="txb3">
-                 <property name="maximumSize">
-                  <size>
-                   <width>40</width>
-                   <height>16777215</height>
-                  </size>
-                 </property>
-                 <property name="toolTip">
-                  <string>Switch to this Tx message NOW</string>
-                 </property>
-                 <property name="text">
-                  <string>Tx 3</string>
-                 </property>
-                </widget>
-               </item>
-               <item row="4" column="2">
-                <widget class="QPushButton" name="txb4">
-                 <property name="maximumSize">
-                  <size>
-                   <width>40</width>
-                   <height>16777215</height>
-                  </size>
-                 </property>
-                 <property name="toolTip">
-                  <string>Switch to this Tx message NOW</string>
-                 </property>
-                 <property name="text">
-                  <string>Tx 4</string>
-                 </property>
-                </widget>
-               </item>
-               <item row="0" column="1">
-                <widget class="QLabel" name="label_5">
-                 <property name="toolTip">
-                  <string>Queue up the next Tx message</string>
-                 </property>
-                 <property name="text">
-                  <string>Next</string>
-                 </property>
-                </widget>
-               </item>
-               <item row="6" column="0">
-                <widget class="QLineEdit" name="tx6">
-                 <property name="sizePolicy">
-                  <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
-                   <horstretch>200</horstretch>
-                   <verstretch>0</verstretch>
-                  </sizepolicy>
-                 </property>
-                 <property name="minimumSize">
-                  <size>
-                   <width>150</width>
-                   <height>24</height>
-                  </size>
-                 </property>
-                 <property name="maximumSize">
-                  <size>
-                   <width>150</width>
-                   <height>16777215</height>
-                  </size>
-                 </property>
-                </widget>
-               </item>
-               <item row="5" column="0">
-                <widget class="QLineEdit" name="tx5">
-                 <property name="sizePolicy">
-                  <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
-                   <horstretch>200</horstretch>
-                   <verstretch>0</verstretch>
-                  </sizepolicy>
-                 </property>
-                 <property name="minimumSize">
-                  <size>
-                   <width>150</width>
-                   <height>24</height>
-                  </size>
-                 </property>
-                 <property name="maximumSize">
-                  <size>
-                   <width>150</width>
-                   <height>16777215</height>
-                  </size>
-                 </property>
-                 <property name="toolTip">
-                  <string>Right-click to select a macro message</string>
-                 </property>
-                </widget>
-               </item>
-               <item row="5" column="2">
-                <widget class="QPushButton" name="txb5">
-                 <property name="maximumSize">
-                  <size>
-                   <width>40</width>
-                   <height>16777215</height>
-                  </size>
-                 </property>
-                 <property name="toolTip">
-                  <string>Switch to this Tx message NOW</string>
-                 </property>
-                 <property name="text">
-                  <string>Tx 5</string>
-                 </property>
-                </widget>
-               </item>
-               <item row="2" column="1">
-                <widget class="QRadioButton" name="txrb2">
-                 <property name="sizePolicy">
-                  <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-                   <horstretch>16</horstretch>
-                   <verstretch>0</verstretch>
-                  </sizepolicy>
-                 </property>
-                 <property name="minimumSize">
-                  <size>
-                   <width>0</width>
-                   <height>20</height>
-                  </size>
-                 </property>
-                 <property name="maximumSize">
-                  <size>
-                   <width>20</width>
-                   <height>16777215</height>
-                  </size>
-                 </property>
-                 <property name="toolTip">
-                  <string>Send this message in next Tx interval</string>
-                 </property>
-                 <property name="text">
-                  <string/>
-                 </property>
-                 <attribute name="buttonGroup">
-                  <string>buttonGroup</string>
-                 </attribute>
-                </widget>
-               </item>
-               <item row="0" column="2">
-                <widget class="QLabel" name="label_2">
-                 <property name="toolTip">
-                  <string>Switch to this Tx message NOW</string>
-                 </property>
-                 <property name="text">
-                  <string>Now</string>
-                 </property>
-                 <property name="alignment">
-                  <set>Qt::AlignCenter</set>
-                 </property>
-                </widget>
-               </item>
-               <item row="0" column="0">
-                <widget class="QPushButton" name="genStdMsgsPushButton">
-                 <property name="sizePolicy">
-                  <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
-                   <horstretch>200</horstretch>
-                   <verstretch>0</verstretch>
-                  </sizepolicy>
-                 </property>
-                 <property name="minimumSize">
-                  <size>
-                   <width>150</width>
-                   <height>0</height>
-                  </size>
-                 </property>
-                 <property name="maximumSize">
-                  <size>
-                   <width>150</width>
-                   <height>16777215</height>
-                  </size>
-                 </property>
-                 <property name="toolTip">
-                  <string>Generate standard messages for minimal QSO</string>
-                 </property>
-                 <property name="text">
-                  <string>Generate Std Msgs</string>
-                 </property>
-                </widget>
-               </item>
-               <item row="2" column="0">
-                <widget class="QLineEdit" name="tx2">
-                 <property name="sizePolicy">
-                  <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
-                   <horstretch>200</horstretch>
-                   <verstretch>0</verstretch>
-                  </sizepolicy>
-                 </property>
-                 <property name="minimumSize">
-                  <size>
-                   <width>150</width>
-                   <height>24</height>
-                  </size>
-                 </property>
-                 <property name="maximumSize">
-                  <size>
-                   <width>150</width>
-                   <height>16777215</height>
-                  </size>
-                 </property>
-                </widget>
-               </item>
-               <item row="3" column="0">
-                <widget class="QLineEdit" name="tx3">
-                 <property name="sizePolicy">
-                  <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
-                   <horstretch>200</horstretch>
-                   <verstretch>0</verstretch>
-                  </sizepolicy>
-                 </property>
-                 <property name="minimumSize">
-                  <size>
-                   <width>150</width>
-                   <height>24</height>
-                  </size>
-                 </property>
-                 <property name="maximumSize">
-                  <size>
-                   <width>150</width>
-                   <height>16777215</height>
-                  </size>
-                 </property>
-                </widget>
-               </item>
-               <item row="6" column="2">
-                <widget class="QPushButton" name="txb6">
-                 <property name="maximumSize">
-                  <size>
-                   <width>40</width>
-                   <height>16777215</height>
-                  </size>
-                 </property>
-                 <property name="toolTip">
-                  <string>Switch to this Tx message NOW</string>
-                 </property>
-                 <property name="text">
-                  <string>Tx 6</string>
-                 </property>
-                </widget>
-               </item>
-               <item row="2" column="2">
-                <widget class="QPushButton" name="txb2">
-                 <property name="maximumSize">
-                  <size>
-                   <width>40</width>
-                   <height>16777215</height>
-                  </size>
-                 </property>
-                 <property name="toolTip">
-                  <string>Switch to this Tx message NOW</string>
-                 </property>
-                 <property name="text">
-                  <string>Tx 2</string>
-                 </property>
-                </widget>
-               </item>
-               <item row="6" column="1">
-                <widget class="QRadioButton" name="txrb6">
-                 <property name="sizePolicy">
-                  <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-                   <horstretch>16</horstretch>
-                   <verstretch>0</verstretch>
-                  </sizepolicy>
-                 </property>
-                 <property name="minimumSize">
-                  <size>
-                   <width>0</width>
-                   <height>20</height>
-                  </size>
-                 </property>
-                 <property name="maximumSize">
-                  <size>
-                   <width>20</width>
-                   <height>16777215</height>
-                  </size>
-                 </property>
-                 <property name="toolTip">
-                  <string>Send this message in next Tx interval</string>
-                 </property>
-                 <property name="text">
-                  <string/>
-                 </property>
-                 <attribute name="buttonGroup">
-                  <string>buttonGroup</string>
-                 </attribute>
-                </widget>
-               </item>
-               <item row="5" column="1">
-                <widget class="QRadioButton" name="txrb5">
-                 <property name="sizePolicy">
-                  <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-                   <horstretch>16</horstretch>
-                   <verstretch>0</verstretch>
-                  </sizepolicy>
-                 </property>
-                 <property name="minimumSize">
-                  <size>
-                   <width>0</width>
-                   <height>20</height>
-                  </size>
-                 </property>
-                 <property name="maximumSize">
-                  <size>
-                   <width>20</width>
-                   <height>16777215</height>
-                  </size>
-                 </property>
-                 <property name="toolTip">
-                  <string>Send this message in next Tx interval</string>
-                 </property>
-                 <property name="text">
-                  <string/>
-                 </property>
-                 <attribute name="buttonGroup">
-                  <string>buttonGroup</string>
-                 </attribute>
-                </widget>
-               </item>
-               <item row="4" column="0">
-                <widget class="QLineEdit" name="tx4">
-                 <property name="sizePolicy">
-                  <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
-                   <horstretch>200</horstretch>
-                   <verstretch>0</verstretch>
-                  </sizepolicy>
-                 </property>
-                 <property name="minimumSize">
-                  <size>
-                   <width>150</width>
-                   <height>24</height>
-                  </size>
-                 </property>
-                 <property name="maximumSize">
-                  <size>
-                   <width>150</width>
-                   <height>16777215</height>
-                  </size>
-                 </property>
-                </widget>
-               </item>
-              </layout>
-             </item>
-            </layout>
-           </widget>
-           <widget class="QWidget" name="tab_2">
-            <attribute name="title">
-             <string>2</string>
-            </attribute>
-            <layout class="QVBoxLayout" name="verticalLayout_9">
-             <property name="spacing">
-              <number>0</number>
-             </property>
-             <property name="margin">
-              <number>0</number>
-             </property>
-             <item>
-              <layout class="QVBoxLayout" name="verticalLayout_7">
-               <property name="spacing">
-                <number>6</number>
-               </property>
-               <property name="leftMargin">
-                <number>2</number>
-               </property>
-               <property name="rightMargin">
-                <number>2</number>
-               </property>
-               <item>
-                <layout class="QGridLayout" name="gridLayout_4">
-                 <property name="spacing">
-                  <number>2</number>
-                 </property>
-                 <item row="0" column="0">
-                  <widget class="QLabel" name="label_9">
-                   <property name="minimumSize">
-                    <size>
-                     <width>0</width>
-                     <height>30</height>
-                    </size>
-                   </property>
-                   <property name="maximumSize">
-                    <size>
-                     <width>16777215</width>
-                     <height>30</height>
-                    </size>
-                   </property>
-                   <property name="text">
-                    <string>Calling CQ </string>
-                   </property>
-                   <property name="alignment">
-                    <set>Qt::AlignCenter</set>
-                   </property>
-                  </widget>
-                 </item>
-                 <item row="1" column="0">
-                  <widget class="QPushButton" name="pbCallCQ">
-                   <property name="toolTip">
-                    <string>Generate a CQ message</string>
-                   </property>
-                   <property name="text">
-                    <string>CQ</string>
-                   </property>
-                  </widget>
-                 </item>
-                 <item row="3" column="0">
-                  <widget class="QPushButton" name="pbSendRRR">
-                   <property name="toolTip">
-                    <string>Generate message with RRR</string>
-                   </property>
-                   <property name="text">
-                    <string>RRR</string>
-                   </property>
-                  </widget>
-                 </item>
-                 <item row="2" column="0">
-                  <widget class="QPushButton" name="pbAnswerCaller">
-                   <property name="toolTip">
-                    <string>Generate message with report</string>
-                   </property>
-                   <property name="text">
-                    <string>dB</string>
-                   </property>
-                  </widget>
-                 </item>
-                 <item row="0" column="1">
-                  <widget class="QLabel" name="label_10">
-                   <property name="minimumSize">
-                    <size>
-                     <width>0</width>
-                     <height>30</height>
-                    </size>
-                   </property>
-                   <property name="maximumSize">
-                    <size>
-                     <width>16777215</width>
-                     <height>30</height>
-                    </size>
-                   </property>
-                   <property name="text">
-                    <string>Answering CQ</string>
-                   </property>
-                   <property name="alignment">
-                    <set>Qt::AlignCenter</set>
-                   </property>
-                  </widget>
-                 </item>
-                 <item row="1" column="1">
-                  <widget class="QPushButton" name="pbAnswerCQ">
-                   <property name="toolTip">
-                    <string>Generate message for replying to a CQ</string>
-                   </property>
-                   <property name="text">
-                    <string>Grid</string>
-                   </property>
-                  </widget>
-                 </item>
-                 <item row="2" column="1">
-                  <widget class="QPushButton" name="pbSendReport">
-                   <property name="toolTip">
-                    <string>Generate message with R+report</string>
-                   </property>
-                   <property name="text">
-                    <string>R+dB</string>
-                   </property>
-                  </widget>
-                 </item>
-                 <item row="3" column="1">
-                  <widget class="QPushButton" name="pbSend73">
-                   <property name="toolTip">
-                    <string>Generate message with 73</string>
-                   </property>
-                   <property name="text">
-                    <string>73</string>
-                   </property>
-                  </widget>
-                 </item>
-                </layout>
-               </item>
-               <item>
-                <layout class="QHBoxLayout" name="horizontalLayout_3">
-                 <item>
-                  <widget class="QLineEdit" name="genMsg">
-                   <property name="sizePolicy">
-                    <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
-                     <horstretch>0</horstretch>
-                     <verstretch>0</verstretch>
-                    </sizepolicy>
-                   </property>
-                   <property name="minimumSize">
-                    <size>
-                     <width>150</width>
-                     <height>0</height>
-                    </size>
-                   </property>
-                   <property name="readOnly">
-                    <bool>true</bool>
-                   </property>
-                  </widget>
-                 </item>
-                 <item>
-                  <widget class="QRadioButton" name="rbGenMsg">
-                   <property name="sizePolicy">
-                    <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
-                     <horstretch>0</horstretch>
-                     <verstretch>0</verstretch>
-                    </sizepolicy>
-                   </property>
-                   <property name="minimumSize">
-                    <size>
-                     <width>0</width>
-                     <height>26</height>
-                    </size>
-                   </property>
-                   <property name="toolTip">
-                    <string>Send this standard (generated) message</string>
-                   </property>
-                   <property name="text">
-                    <string>Gen msg</string>
-                   </property>
-                   <property name="checked">
-                    <bool>true</bool>
-                   </property>
-                  </widget>
-                 </item>
-                </layout>
-               </item>
-               <item>
-                <layout class="QHBoxLayout" name="horizontalLayout">
-                 <item>
-                  <widget class="QLineEdit" name="freeTextMsg">
-                   <property name="sizePolicy">
-                    <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
-                     <horstretch>0</horstretch>
-                     <verstretch>0</verstretch>
-                    </sizepolicy>
-                   </property>
-                   <property name="minimumSize">
-                    <size>
-                     <width>150</width>
-                     <height>0</height>
-                    </size>
-                   </property>
-                  </widget>
-                 </item>
-                 <item>
-                  <widget class="QRadioButton" name="rbFreeText">
-                   <property name="sizePolicy">
-                    <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
-                     <horstretch>0</horstretch>
-                     <verstretch>0</verstretch>
-                    </sizepolicy>
-                   </property>
-                   <property name="minimumSize">
-                    <size>
-                     <width>0</width>
-                     <height>26</height>
-                    </size>
-                   </property>
-                   <property name="toolTip">
-                    <string>Send this free-text message (max 13 characters)</string>
-                   </property>
-                   <property name="text">
-                    <string>Free msg</string>
-                   </property>
-                  </widget>
-                 </item>
-                </layout>
-               </item>
-              </layout>
-             </item>
-            </layout>
-           </widget>
-          </widget>
-         </item>
-        </layout>
-       </widget>
-      </item>
-      <item row="1" column="0" colspan="3">
-       <widget class="QCheckBox" name="cbPlus2kHz">
         <property name="text">
-         <string>  +2 kHz</string>
+         <string>14.078</string>
+        </property>
+        <property name="alignment">
+         <set>Qt::AlignCenter</set>
         </property>
        </widget>
       </item>
-      <item row="1" column="3">
-       <widget class="QLabel" name="label_3">
+      <item row="2" column="4">
+       <widget class="QLineEdit" name="dxGridEntry">
         <property name="sizePolicy">
-         <sizepolicy hsizetype="Preferred" vsizetype="Minimum">
+         <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
           <horstretch>0</horstretch>
           <verstretch>0</verstretch>
          </sizepolicy>
         </property>
         <property name="minimumSize">
          <size>
-          <width>0</width>
-          <height>23</height>
+          <width>70</width>
+          <height>27</height>
          </size>
         </property>
-        <property name="palette">
-         <palette>
-          <active>
-           <colorrole role="Base">
-            <brush brushstyle="SolidPattern">
-             <color alpha="255">
-              <red>252</red>
-              <green>252</green>
-              <blue>252</blue>
-             </color>
-            </brush>
-           </colorrole>
-           <colorrole role="Window">
-            <brush brushstyle="SolidPattern">
-             <color alpha="255">
-              <red>159</red>
-              <green>175</green>
-              <blue>213</blue>
-             </color>
-            </brush>
-           </colorrole>
-          </active>
-          <inactive>
-           <colorrole role="Base">
-            <brush brushstyle="SolidPattern">
-             <color alpha="255">
-              <red>252</red>
-              <green>252</green>
-              <blue>252</blue>
-             </color>
-            </brush>
-           </colorrole>
-           <colorrole role="Window">
-            <brush brushstyle="SolidPattern">
-             <color alpha="255">
-              <red>159</red>
-              <green>175</green>
-              <blue>213</blue>
-             </color>
-            </brush>
-           </colorrole>
-          </inactive>
-          <disabled>
-           <colorrole role="Base">
-            <brush brushstyle="SolidPattern">
-             <color alpha="255">
-              <red>159</red>
-              <green>175</green>
-              <blue>213</blue>
-             </color>
-            </brush>
-           </colorrole>
-           <colorrole role="Window">
-            <brush brushstyle="SolidPattern">
-             <color alpha="255">
-              <red>159</red>
-              <green>175</green>
-              <blue>213</blue>
-             </color>
-            </brush>
-           </colorrole>
-          </disabled>
-         </palette>
+        <property name="maximumSize">
+         <size>
+          <width>74</width>
+          <height>16777215</height>
+         </size>
         </property>
-        <property name="autoFillBackground">
-         <bool>true</bool>
+        <property name="toolTip">
+         <string>Locator of station to be worked</string>
         </property>
         <property name="text">
-         <string>DX Call</string>
+         <string/>
         </property>
         <property name="alignment">
          <set>Qt::AlignCenter</set>
         </property>
-        <property name="indent">
-         <number>2</number>
+       </widget>
+      </item>
+      <item row="0" column="6">
+       <widget class="QCheckBox" name="txFirstCheckBox">
+        <property name="minimumSize">
+         <size>
+          <width>105</width>
+          <height>23</height>
+         </size>
+        </property>
+        <property name="maximumSize">
+         <size>
+          <width>105</width>
+          <height>16777215</height>
+         </size>
+        </property>
+        <property name="toolTip">
+         <string>Check to Tx in even minutes, uncheck for odd minutes</string>
+        </property>
+        <property name="text">
+         <string>Tx even</string>
         </property>
        </widget>
       </item>
-      <item row="1" column="4">
-       <widget class="QLabel" name="label_4">
+      <item row="1" column="3">
+       <widget class="QLabel" name="label_3">
         <property name="sizePolicy">
          <sizepolicy hsizetype="Preferred" vsizetype="Minimum">
           <horstretch>0</horstretch>
@@ -1656,12 +1001,6 @@ p, li { white-space: pre-wrap; }
           <height>23</height>
          </size>
         </property>
-        <property name="maximumSize">
-         <size>
-          <width>16777215</width>
-          <height>16777215</height>
-         </size>
-        </property>
         <property name="palette">
          <palette>
           <active>
@@ -1730,7 +1069,7 @@ p, li { white-space: pre-wrap; }
          <bool>true</bool>
         </property>
         <property name="text">
-         <string>DX Grid</string>
+         <string>DX Call</string>
         </property>
         <property name="alignment">
          <set>Qt::AlignCenter</set>
@@ -1745,47 +1084,26 @@ p, li { white-space: pre-wrap; }
         <property name="enabled">
          <bool>false</bool>
         </property>
+        <property name="toolTip">
+         <string>Toggle Tx mode</string>
+        </property>
         <property name="text">
          <string>Tx JT9</string>
         </property>
        </widget>
       </item>
-      <item row="2" column="1" rowspan="5">
-       <widget class="QSlider" name="inGain">
-        <property name="sizePolicy">
-         <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-          <horstretch>0</horstretch>
-          <verstretch>0</verstretch>
-         </sizepolicy>
-        </property>
-        <property name="minimumSize">
-         <size>
-          <width>0</width>
-          <height>160</height>
-         </size>
-        </property>
-        <property name="maximumSize">
-         <size>
-          <width>20</width>
-          <height>160</height>
-         </size>
-        </property>
+      <item row="1" column="0" colspan="2">
+       <widget class="QCheckBox" name="cbPlus2kHz">
         <property name="toolTip">
-         <string>Digital gain for audio input</string>
-        </property>
-        <property name="minimum">
-         <number>-50</number>
-        </property>
-        <property name="maximum">
-         <number>50</number>
+         <string>Add 2 kHz to requested dial frequency</string>
         </property>
-        <property name="orientation">
-         <enum>Qt::Vertical</enum>
+        <property name="text">
+         <string>+2 kHz</string>
         </property>
        </widget>
       </item>
-      <item row="2" column="3">
-       <widget class="QLineEdit" name="dxCallEntry">
+      <item row="5" column="3" rowspan="2" colspan="2">
+       <widget class="QLabel" name="labUTC">
         <property name="sizePolicy">
          <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
           <horstretch>0</horstretch>
@@ -1794,60 +1112,62 @@ p, li { white-space: pre-wrap; }
         </property>
         <property name="minimumSize">
          <size>
-          <width>70</width>
-          <height>27</height>
+          <width>130</width>
+          <height>60</height>
          </size>
         </property>
         <property name="maximumSize">
          <size>
-          <width>74</width>
-          <height>16777215</height>
+          <width>158</width>
+          <height>60</height>
          </size>
         </property>
-        <property name="toolTip">
-         <string>Callsign of station to be worked</string>
+        <property name="styleSheet">
+         <string notr="true">QLabel {
+  font-family: MS Shell Dlg 2;
+  font-size: 16pt;
+  background-color : black;
+  color : yellow;
+}</string>
         </property>
-        <property name="text">
-         <string/>
+        <property name="frameShape">
+         <enum>QFrame::StyledPanel</enum>
         </property>
-        <property name="alignment">
-         <set>Qt::AlignCenter</set>
+        <property name="frameShadow">
+         <enum>QFrame::Sunken</enum>
         </property>
-       </widget>
-      </item>
-      <item row="2" column="4">
-       <widget class="QLineEdit" name="dxGridEntry">
-        <property name="sizePolicy">
-         <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
-          <horstretch>0</horstretch>
-          <verstretch>0</verstretch>
-         </sizepolicy>
+        <property name="lineWidth">
+         <number>2</number>
         </property>
-        <property name="minimumSize">
-         <size>
-          <width>70</width>
-          <height>27</height>
-         </size>
+        <property name="midLineWidth">
+         <number>0</number>
+        </property>
+        <property name="text">
+         <string> 01:23:45 </string>
+        </property>
+        <property name="alignment">
+         <set>Qt::AlignCenter</set>
         </property>
+       </widget>
+      </item>
+      <item row="1" column="2">
+       <widget class="QPushButton" name="readFreq">
         <property name="maximumSize">
          <size>
-          <width>74</width>
-          <height>16777215</height>
+          <width>15</width>
+          <height>15</height>
          </size>
         </property>
         <property name="toolTip">
-         <string>Locator of station to be worked</string>
+         <string><html><head/><body><p>If orange, click to read dial frequency</p></body></html></string>
         </property>
         <property name="text">
          <string/>
         </property>
-        <property name="alignment">
-         <set>Qt::AlignCenter</set>
-        </property>
        </widget>
       </item>
-      <item row="2" column="6">
-       <widget class="QSpinBox" name="TxFreqSpinBox">
+      <item row="0" column="8" rowspan="7">
+       <widget class="QFrame" name="frame_2">
         <property name="sizePolicy">
          <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
           <horstretch>0</horstretch>
@@ -1856,61 +1176,863 @@ p, li { white-space: pre-wrap; }
         </property>
         <property name="minimumSize">
          <size>
-          <width>113</width>
-          <height>0</height>
-         </size>
-        </property>
-        <property name="maximumSize">
-         <size>
-          <width>105</width>
-          <height>16777215</height>
+          <width>283</width>
+          <height>222</height>
          </size>
         </property>
-        <property name="toolTip">
-         <string>Audio Tx frequency</string>
-        </property>
-        <property name="suffix">
-         <string>  Hz</string>
-        </property>
-        <property name="prefix">
-         <string>Tx  </string>
-        </property>
-        <property name="minimum">
-         <number>200</number>
+        <property name="frameShape">
+         <enum>QFrame::NoFrame</enum>
         </property>
-        <property name="maximum">
-         <number>5000</number>
+        <property name="frameShadow">
+         <enum>QFrame::Plain</enum>
         </property>
-        <property name="value">
-         <number>1500</number>
+        <property name="lineWidth">
+         <number>0</number>
         </property>
+        <layout class="QVBoxLayout" name="verticalLayout_2">
+         <property name="spacing">
+          <number>0</number>
+         </property>
+         <property name="leftMargin">
+          <number>0</number>
+         </property>
+         <property name="topMargin">
+          <number>0</number>
+         </property>
+         <property name="rightMargin">
+          <number>0</number>
+         </property>
+         <property name="bottomMargin">
+          <number>0</number>
+         </property>
+         <item>
+          <widget class="QTabWidget" name="tabWidget">
+           <property name="sizePolicy">
+            <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
+             <horstretch>0</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+           <property name="minimumSize">
+            <size>
+             <width>0</width>
+             <height>200</height>
+            </size>
+           </property>
+           <property name="tabPosition">
+            <enum>QTabWidget::West</enum>
+           </property>
+           <property name="tabShape">
+            <enum>QTabWidget::Triangular</enum>
+           </property>
+           <property name="currentIndex">
+            <number>1</number>
+           </property>
+           <widget class="QWidget" name="tab">
+            <attribute name="title">
+             <string>1</string>
+            </attribute>
+            <layout class="QVBoxLayout" name="verticalLayout_4">
+             <property name="spacing">
+              <number>0</number>
+             </property>
+             <property name="leftMargin">
+              <number>4</number>
+             </property>
+             <property name="topMargin">
+              <number>1</number>
+             </property>
+             <property name="rightMargin">
+              <number>0</number>
+             </property>
+             <property name="bottomMargin">
+              <number>0</number>
+             </property>
+             <item>
+              <layout class="QGridLayout" name="gridLayout_2">
+               <property name="horizontalSpacing">
+                <number>6</number>
+               </property>
+               <property name="verticalSpacing">
+                <number>5</number>
+               </property>
+               <item row="1" column="2">
+                <widget class="QPushButton" name="txb1">
+                 <property name="maximumSize">
+                  <size>
+                   <width>40</width>
+                   <height>16777215</height>
+                  </size>
+                 </property>
+                 <property name="toolTip">
+                  <string>Switch to this Tx message NOW</string>
+                 </property>
+                 <property name="layoutDirection">
+                  <enum>Qt::LeftToRight</enum>
+                 </property>
+                 <property name="text">
+                  <string>Tx &1</string>
+                 </property>
+                 <property name="shortcut">
+                  <string>Alt+1</string>
+                 </property>
+                </widget>
+               </item>
+               <item row="4" column="1">
+                <widget class="QRadioButton" name="txrb4">
+                 <property name="sizePolicy">
+                  <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+                   <horstretch>16</horstretch>
+                   <verstretch>0</verstretch>
+                  </sizepolicy>
+                 </property>
+                 <property name="minimumSize">
+                  <size>
+                   <width>0</width>
+                   <height>20</height>
+                  </size>
+                 </property>
+                 <property name="maximumSize">
+                  <size>
+                   <width>20</width>
+                   <height>16777215</height>
+                  </size>
+                 </property>
+                 <property name="toolTip">
+                  <string>Send this message in next Tx interval</string>
+                 </property>
+                 <property name="text">
+                  <string/>
+                 </property>
+                 <property name="shortcut">
+                  <string>Ctrl+4</string>
+                 </property>
+                 <attribute name="buttonGroup">
+                  <string notr="true">buttonGroup</string>
+                 </attribute>
+                </widget>
+               </item>
+               <item row="1" column="1">
+                <widget class="QRadioButton" name="txrb1">
+                 <property name="sizePolicy">
+                  <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+                   <horstretch>16</horstretch>
+                   <verstretch>0</verstretch>
+                  </sizepolicy>
+                 </property>
+                 <property name="minimumSize">
+                  <size>
+                   <width>0</width>
+                   <height>20</height>
+                  </size>
+                 </property>
+                 <property name="maximumSize">
+                  <size>
+                   <width>20</width>
+                   <height>16777215</height>
+                  </size>
+                 </property>
+                 <property name="toolTip">
+                  <string>Send this message in next Tx interval</string>
+                 </property>
+                 <property name="text">
+                  <string/>
+                 </property>
+                 <property name="shortcut">
+                  <string>Ctrl+1</string>
+                 </property>
+                 <property name="checked">
+                  <bool>false</bool>
+                 </property>
+                 <attribute name="buttonGroup">
+                  <string notr="true">buttonGroup</string>
+                 </attribute>
+                </widget>
+               </item>
+               <item row="3" column="1">
+                <widget class="QRadioButton" name="txrb3">
+                 <property name="sizePolicy">
+                  <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+                   <horstretch>16</horstretch>
+                   <verstretch>0</verstretch>
+                  </sizepolicy>
+                 </property>
+                 <property name="minimumSize">
+                  <size>
+                   <width>0</width>
+                   <height>20</height>
+                  </size>
+                 </property>
+                 <property name="maximumSize">
+                  <size>
+                   <width>20</width>
+                   <height>16777215</height>
+                  </size>
+                 </property>
+                 <property name="toolTip">
+                  <string>Send this message in next Tx interval</string>
+                 </property>
+                 <property name="text">
+                  <string/>
+                 </property>
+                 <property name="shortcut">
+                  <string>Ctrl+3</string>
+                 </property>
+                 <attribute name="buttonGroup">
+                  <string notr="true">buttonGroup</string>
+                 </attribute>
+                </widget>
+               </item>
+               <item row="1" column="0">
+                <widget class="QLineEdit" name="tx1">
+                 <property name="sizePolicy">
+                  <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+                   <horstretch>200</horstretch>
+                   <verstretch>0</verstretch>
+                  </sizepolicy>
+                 </property>
+                 <property name="minimumSize">
+                  <size>
+                   <width>150</width>
+                   <height>24</height>
+                  </size>
+                 </property>
+                 <property name="maximumSize">
+                  <size>
+                   <width>150</width>
+                   <height>16777215</height>
+                  </size>
+                 </property>
+                 <property name="text">
+                  <string/>
+                 </property>
+                </widget>
+               </item>
+               <item row="3" column="2">
+                <widget class="QPushButton" name="txb3">
+                 <property name="maximumSize">
+                  <size>
+                   <width>40</width>
+                   <height>16777215</height>
+                  </size>
+                 </property>
+                 <property name="toolTip">
+                  <string>Switch to this Tx message NOW</string>
+                 </property>
+                 <property name="text">
+                  <string>Tx &3</string>
+                 </property>
+                 <property name="shortcut">
+                  <string>Alt+3</string>
+                 </property>
+                </widget>
+               </item>
+               <item row="4" column="2">
+                <widget class="QPushButton" name="txb4">
+                 <property name="maximumSize">
+                  <size>
+                   <width>40</width>
+                   <height>16777215</height>
+                  </size>
+                 </property>
+                 <property name="toolTip">
+                  <string>Switch to this Tx message NOW</string>
+                 </property>
+                 <property name="text">
+                  <string>Tx &4</string>
+                 </property>
+                 <property name="shortcut">
+                  <string>Alt+4</string>
+                 </property>
+                </widget>
+               </item>
+               <item row="0" column="1">
+                <widget class="QLabel" name="label_5">
+                 <property name="toolTip">
+                  <string>Queue up the next Tx message</string>
+                 </property>
+                 <property name="text">
+                  <string>Next</string>
+                 </property>
+                </widget>
+               </item>
+               <item row="6" column="0">
+                <widget class="QLineEdit" name="tx6">
+                 <property name="sizePolicy">
+                  <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+                   <horstretch>200</horstretch>
+                   <verstretch>0</verstretch>
+                  </sizepolicy>
+                 </property>
+                 <property name="minimumSize">
+                  <size>
+                   <width>150</width>
+                   <height>24</height>
+                  </size>
+                 </property>
+                 <property name="maximumSize">
+                  <size>
+                   <width>150</width>
+                   <height>16777215</height>
+                  </size>
+                 </property>
+                </widget>
+               </item>
+               <item row="5" column="2">
+                <widget class="QPushButton" name="txb5">
+                 <property name="maximumSize">
+                  <size>
+                   <width>40</width>
+                   <height>16777215</height>
+                  </size>
+                 </property>
+                 <property name="toolTip">
+                  <string>Switch to this Tx message NOW</string>
+                 </property>
+                 <property name="text">
+                  <string>Tx &5</string>
+                 </property>
+                 <property name="shortcut">
+                  <string>Alt+5</string>
+                 </property>
+                </widget>
+               </item>
+               <item row="2" column="1">
+                <widget class="QRadioButton" name="txrb2">
+                 <property name="sizePolicy">
+                  <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+                   <horstretch>16</horstretch>
+                   <verstretch>0</verstretch>
+                  </sizepolicy>
+                 </property>
+                 <property name="minimumSize">
+                  <size>
+                   <width>0</width>
+                   <height>20</height>
+                  </size>
+                 </property>
+                 <property name="maximumSize">
+                  <size>
+                   <width>20</width>
+                   <height>16777215</height>
+                  </size>
+                 </property>
+                 <property name="toolTip">
+                  <string>Send this message in next Tx interval</string>
+                 </property>
+                 <property name="text">
+                  <string/>
+                 </property>
+                 <property name="shortcut">
+                  <string>Ctrl+2</string>
+                 </property>
+                 <attribute name="buttonGroup">
+                  <string notr="true">buttonGroup</string>
+                 </attribute>
+                </widget>
+               </item>
+               <item row="0" column="2">
+                <widget class="QLabel" name="label_2">
+                 <property name="toolTip">
+                  <string>Switch to this Tx message NOW</string>
+                 </property>
+                 <property name="text">
+                  <string>Now</string>
+                 </property>
+                 <property name="alignment">
+                  <set>Qt::AlignCenter</set>
+                 </property>
+                </widget>
+               </item>
+               <item row="0" column="0">
+                <widget class="QPushButton" name="genStdMsgsPushButton">
+                 <property name="sizePolicy">
+                  <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+                   <horstretch>200</horstretch>
+                   <verstretch>0</verstretch>
+                  </sizepolicy>
+                 </property>
+                 <property name="minimumSize">
+                  <size>
+                   <width>150</width>
+                   <height>0</height>
+                  </size>
+                 </property>
+                 <property name="maximumSize">
+                  <size>
+                   <width>150</width>
+                   <height>16777215</height>
+                  </size>
+                 </property>
+                 <property name="toolTip">
+                  <string>Generate standard messages for minimal QSO</string>
+                 </property>
+                 <property name="text">
+                  <string>Generate Std Msgs</string>
+                 </property>
+                </widget>
+               </item>
+               <item row="2" column="0">
+                <widget class="QLineEdit" name="tx2">
+                 <property name="sizePolicy">
+                  <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+                   <horstretch>200</horstretch>
+                   <verstretch>0</verstretch>
+                  </sizepolicy>
+                 </property>
+                 <property name="minimumSize">
+                  <size>
+                   <width>150</width>
+                   <height>24</height>
+                  </size>
+                 </property>
+                 <property name="maximumSize">
+                  <size>
+                   <width>150</width>
+                   <height>16777215</height>
+                  </size>
+                 </property>
+                </widget>
+               </item>
+               <item row="3" column="0">
+                <widget class="QLineEdit" name="tx3">
+                 <property name="sizePolicy">
+                  <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+                   <horstretch>200</horstretch>
+                   <verstretch>0</verstretch>
+                  </sizepolicy>
+                 </property>
+                 <property name="minimumSize">
+                  <size>
+                   <width>150</width>
+                   <height>24</height>
+                  </size>
+                 </property>
+                 <property name="maximumSize">
+                  <size>
+                   <width>150</width>
+                   <height>16777215</height>
+                  </size>
+                 </property>
+                </widget>
+               </item>
+               <item row="6" column="2">
+                <widget class="QPushButton" name="txb6">
+                 <property name="maximumSize">
+                  <size>
+                   <width>40</width>
+                   <height>16777215</height>
+                  </size>
+                 </property>
+                 <property name="toolTip">
+                  <string>Switch to this Tx message NOW</string>
+                 </property>
+                 <property name="text">
+                  <string>Tx &6</string>
+                 </property>
+                 <property name="shortcut">
+                  <string>Alt+6</string>
+                 </property>
+                </widget>
+               </item>
+               <item row="2" column="2">
+                <widget class="QPushButton" name="txb2">
+                 <property name="maximumSize">
+                  <size>
+                   <width>40</width>
+                   <height>16777215</height>
+                  </size>
+                 </property>
+                 <property name="toolTip">
+                  <string>Switch to this Tx message NOW</string>
+                 </property>
+                 <property name="text">
+                  <string>Tx &2</string>
+                 </property>
+                 <property name="shortcut">
+                  <string>Alt+2</string>
+                 </property>
+                </widget>
+               </item>
+               <item row="6" column="1">
+                <widget class="QRadioButton" name="txrb6">
+                 <property name="sizePolicy">
+                  <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+                   <horstretch>16</horstretch>
+                   <verstretch>0</verstretch>
+                  </sizepolicy>
+                 </property>
+                 <property name="minimumSize">
+                  <size>
+                   <width>0</width>
+                   <height>20</height>
+                  </size>
+                 </property>
+                 <property name="maximumSize">
+                  <size>
+                   <width>20</width>
+                   <height>16777215</height>
+                  </size>
+                 </property>
+                 <property name="toolTip">
+                  <string>Send this message in next Tx interval</string>
+                 </property>
+                 <property name="text">
+                  <string/>
+                 </property>
+                 <property name="shortcut">
+                  <string>Ctrl+6</string>
+                 </property>
+                 <property name="checked">
+                  <bool>true</bool>
+                 </property>
+                 <attribute name="buttonGroup">
+                  <string notr="true">buttonGroup</string>
+                 </attribute>
+                </widget>
+               </item>
+               <item row="5" column="1">
+                <widget class="QRadioButton" name="txrb5">
+                 <property name="sizePolicy">
+                  <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+                   <horstretch>16</horstretch>
+                   <verstretch>0</verstretch>
+                  </sizepolicy>
+                 </property>
+                 <property name="minimumSize">
+                  <size>
+                   <width>0</width>
+                   <height>20</height>
+                  </size>
+                 </property>
+                 <property name="maximumSize">
+                  <size>
+                   <width>20</width>
+                   <height>16777215</height>
+                  </size>
+                 </property>
+                 <property name="toolTip">
+                  <string>Send this message in next Tx interval</string>
+                 </property>
+                 <property name="text">
+                  <string/>
+                 </property>
+                 <property name="shortcut">
+                  <string>Ctrl+5</string>
+                 </property>
+                 <attribute name="buttonGroup">
+                  <string notr="true">buttonGroup</string>
+                 </attribute>
+                </widget>
+               </item>
+               <item row="4" column="0">
+                <widget class="QLineEdit" name="tx4">
+                 <property name="sizePolicy">
+                  <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+                   <horstretch>200</horstretch>
+                   <verstretch>0</verstretch>
+                  </sizepolicy>
+                 </property>
+                 <property name="minimumSize">
+                  <size>
+                   <width>150</width>
+                   <height>24</height>
+                  </size>
+                 </property>
+                 <property name="maximumSize">
+                  <size>
+                   <width>150</width>
+                   <height>16777215</height>
+                  </size>
+                 </property>
+                </widget>
+               </item>
+               <item row="5" column="0">
+                <widget class="QComboBox" name="tx5">
+                 <property name="sizePolicy">
+                  <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+                   <horstretch>0</horstretch>
+                   <verstretch>200</verstretch>
+                  </sizepolicy>
+                 </property>
+                 <property name="minimumSize">
+                  <size>
+                   <width>150</width>
+                   <height>24</height>
+                  </size>
+                 </property>
+                 <property name="maximumSize">
+                  <size>
+                   <width>150</width>
+                   <height>16777215</height>
+                  </size>
+                 </property>
+                 <property name="toolTip">
+                  <string>Enter a free text message (maximum 13 characters)
+or select a predefined macro from the dropdown list.
+Press ENTER to add the current text to the predefined
+list. The list can be maintained in Settings (F2).</string>
+                 </property>
+                 <property name="editable">
+                  <bool>true</bool>
+                 </property>
+                 <property name="insertPolicy">
+                  <enum>QComboBox::InsertAtBottom</enum>
+                 </property>
+                </widget>
+               </item>
+              </layout>
+             </item>
+            </layout>
+           </widget>
+           <widget class="QWidget" name="tab_2">
+            <attribute name="title">
+             <string>2</string>
+            </attribute>
+            <layout class="QVBoxLayout" name="verticalLayout_9">
+             <property name="spacing">
+              <number>0</number>
+             </property>
+             <property name="leftMargin">
+              <number>0</number>
+             </property>
+             <property name="topMargin">
+              <number>0</number>
+             </property>
+             <property name="rightMargin">
+              <number>0</number>
+             </property>
+             <property name="bottomMargin">
+              <number>0</number>
+             </property>
+             <item>
+              <layout class="QVBoxLayout" name="verticalLayout_7">
+               <property name="spacing">
+                <number>6</number>
+               </property>
+               <property name="leftMargin">
+                <number>2</number>
+               </property>
+               <property name="rightMargin">
+                <number>2</number>
+               </property>
+               <item>
+                <layout class="QGridLayout" name="gridLayout_4">
+                 <property name="spacing">
+                  <number>2</number>
+                 </property>
+                 <item row="0" column="0">
+                  <widget class="QLabel" name="label_9">
+                   <property name="minimumSize">
+                    <size>
+                     <width>0</width>
+                     <height>30</height>
+                    </size>
+                   </property>
+                   <property name="maximumSize">
+                    <size>
+                     <width>16777215</width>
+                     <height>30</height>
+                    </size>
+                   </property>
+                   <property name="text">
+                    <string>Calling CQ </string>
+                   </property>
+                   <property name="alignment">
+                    <set>Qt::AlignCenter</set>
+                   </property>
+                  </widget>
+                 </item>
+                 <item row="1" column="0">
+                  <widget class="QPushButton" name="pbCallCQ">
+                   <property name="toolTip">
+                    <string>Generate a CQ message</string>
+                   </property>
+                   <property name="text">
+                    <string>CQ</string>
+                   </property>
+                  </widget>
+                 </item>
+                 <item row="3" column="0">
+                  <widget class="QPushButton" name="pbSendRRR">
+                   <property name="toolTip">
+                    <string>Generate message with RRR</string>
+                   </property>
+                   <property name="text">
+                    <string>RRR</string>
+                   </property>
+                  </widget>
+                 </item>
+                 <item row="2" column="0">
+                  <widget class="QPushButton" name="pbAnswerCaller">
+                   <property name="toolTip">
+                    <string>Generate message with report</string>
+                   </property>
+                   <property name="text">
+                    <string>dB</string>
+                   </property>
+                  </widget>
+                 </item>
+                 <item row="0" column="1">
+                  <widget class="QLabel" name="label_10">
+                   <property name="minimumSize">
+                    <size>
+                     <width>0</width>
+                     <height>30</height>
+                    </size>
+                   </property>
+                   <property name="maximumSize">
+                    <size>
+                     <width>16777215</width>
+                     <height>30</height>
+                    </size>
+                   </property>
+                   <property name="text">
+                    <string>Answering CQ</string>
+                   </property>
+                   <property name="alignment">
+                    <set>Qt::AlignCenter</set>
+                   </property>
+                  </widget>
+                 </item>
+                 <item row="1" column="1">
+                  <widget class="QPushButton" name="pbAnswerCQ">
+                   <property name="toolTip">
+                    <string>Generate message for replying to a CQ</string>
+                   </property>
+                   <property name="text">
+                    <string>Grid</string>
+                   </property>
+                  </widget>
+                 </item>
+                 <item row="2" column="1">
+                  <widget class="QPushButton" name="pbSendReport">
+                   <property name="toolTip">
+                    <string>Generate message with R+report</string>
+                   </property>
+                   <property name="text">
+                    <string>R+dB</string>
+                   </property>
+                  </widget>
+                 </item>
+                 <item row="3" column="1">
+                  <widget class="QPushButton" name="pbSend73">
+                   <property name="toolTip">
+                    <string>Generate message with 73</string>
+                   </property>
+                   <property name="text">
+                    <string>73</string>
+                   </property>
+                  </widget>
+                 </item>
+                </layout>
+               </item>
+               <item>
+                <layout class="QHBoxLayout" name="horizontalLayout_3">
+                 <item>
+                  <widget class="QLineEdit" name="genMsg">
+                   <property name="sizePolicy">
+                    <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+                     <horstretch>0</horstretch>
+                     <verstretch>0</verstretch>
+                    </sizepolicy>
+                   </property>
+                   <property name="minimumSize">
+                    <size>
+                     <width>150</width>
+                     <height>0</height>
+                    </size>
+                   </property>
+                  </widget>
+                 </item>
+                 <item>
+                  <widget class="QRadioButton" name="rbGenMsg">
+                   <property name="sizePolicy">
+                    <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+                     <horstretch>0</horstretch>
+                     <verstretch>0</verstretch>
+                    </sizepolicy>
+                   </property>
+                   <property name="minimumSize">
+                    <size>
+                     <width>0</width>
+                     <height>26</height>
+                    </size>
+                   </property>
+                   <property name="toolTip">
+                    <string>Send this standard (generated) message</string>
+                   </property>
+                   <property name="text">
+                    <string>Gen msg</string>
+                   </property>
+                   <property name="checked">
+                    <bool>true</bool>
+                   </property>
+                  </widget>
+                 </item>
+                </layout>
+               </item>
+               <item>
+                <layout class="QHBoxLayout" name="horizontalLayout">
+                 <item>
+                  <widget class="QComboBox" name="freeTextMsg">
+                   <property name="minimumSize">
+                    <size>
+                     <width>150</width>
+                     <height>0</height>
+                    </size>
+                   </property>
+                   <property name="toolTip">
+                    <string>Enter a free text message (maximum 13 characters)
+or select a predefined macro from the dropdown list.
+Press ENTER to add the current text to the predefined
+list. The list can be maintained in Settings (F2).</string>
+                   </property>
+                   <property name="editable">
+                    <bool>true</bool>
+                   </property>
+                   <property name="insertPolicy">
+                    <enum>QComboBox::InsertAtBottom</enum>
+                   </property>
+                  </widget>
+                 </item>
+                 <item>
+                  <widget class="QRadioButton" name="rbFreeText">
+                   <property name="sizePolicy">
+                    <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+                     <horstretch>0</horstretch>
+                     <verstretch>0</verstretch>
+                    </sizepolicy>
+                   </property>
+                   <property name="minimumSize">
+                    <size>
+                     <width>0</width>
+                     <height>26</height>
+                    </size>
+                   </property>
+                   <property name="toolTip">
+                    <string>Send this free-text message (max 13 characters)</string>
+                   </property>
+                   <property name="text">
+                    <string>Free msg</string>
+                   </property>
+                  </widget>
+                 </item>
+                </layout>
+               </item>
+              </layout>
+             </item>
+            </layout>
+           </widget>
+          </widget>
+         </item>
+        </layout>
        </widget>
       </item>
-      <item row="3" column="4">
-       <widget class="QLabel" name="labDist">
-        <property name="sizePolicy">
-         <sizepolicy hsizetype="Preferred" vsizetype="Minimum">
-          <horstretch>0</horstretch>
-          <verstretch>0</verstretch>
-         </sizepolicy>
-        </property>
-        <property name="minimumSize">
-         <size>
-          <width>0</width>
-          <height>23</height>
-         </size>
-        </property>
-        <property name="maximumSize">
-         <size>
-          <width>16777215</width>
-          <height>23</height>
-         </size>
-        </property>
+      <item row="0" column="9">
+       <widget class="QLabel" name="label">
         <property name="text">
-         <string/>
-        </property>
-        <property name="alignment">
-         <set>Qt::AlignCenter</set>
+         <string> Pwr</string>
         </property>
        </widget>
       </item>
@@ -1930,204 +2052,120 @@ p, li { white-space: pre-wrap; }
         </property>
        </spacer>
       </item>
-      <item row="3" column="6">
-       <widget class="QSpinBox" name="RxFreqSpinBox">
-        <property name="sizePolicy">
-         <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-          <horstretch>0</horstretch>
-          <verstretch>0</verstretch>
-         </sizepolicy>
-        </property>
-        <property name="minimumSize">
-         <size>
-          <width>113</width>
-          <height>20</height>
-         </size>
-        </property>
-        <property name="suffix">
-         <string>  Hz</string>
-        </property>
-        <property name="prefix">
-         <string>Rx  </string>
-        </property>
-        <property name="minimum">
-         <number>200</number>
+      <item row="1" column="9" rowspan="6">
+       <widget class="QSlider" name="outAttenuation">
+        <property name="toolTip">
+         <string>Adjust Tx audio level</string>
         </property>
         <property name="maximum">
-         <number>5000</number>
+         <number>300</number>
         </property>
         <property name="value">
-         <number>1500</number>
+         <number>0</number>
         </property>
-       </widget>
-      </item>
-      <item row="3" column="7">
-       <spacer name="horizontalSpacer_3">
         <property name="orientation">
-         <enum>Qt::Horizontal</enum>
+         <enum>Qt::Vertical</enum>
         </property>
-        <property name="sizeType">
-         <enum>QSizePolicy::Expanding</enum>
+        <property name="invertedAppearance">
+         <bool>true</bool>
         </property>
-        <property name="sizeHint" stdset="0">
-         <size>
-          <width>13</width>
-          <height>20</height>
-         </size>
+        <property name="invertedControls">
+         <bool>true</bool>
         </property>
-       </spacer>
+        <property name="tickPosition">
+         <enum>QSlider::TicksBelow</enum>
+        </property>
+        <property name="tickInterval">
+         <number>10</number>
+        </property>
+       </widget>
       </item>
-      <item row="4" column="3">
-       <widget class="QPushButton" name="lookupButton">
+      <item row="0" column="0" colspan="3">
+       <widget class="QComboBox" name="bandComboBox">
         <property name="sizePolicy">
-         <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+         <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
           <horstretch>0</horstretch>
           <verstretch>0</verstretch>
          </sizepolicy>
         </property>
+        <property name="minimumSize">
+         <size>
+          <width>100</width>
+          <height>0</height>
+         </size>
+        </property>
         <property name="maximumSize">
          <size>
-          <width>74</width>
+          <width>100</width>
           <height>16777215</height>
          </size>
         </property>
         <property name="toolTip">
-         <string>Search for callsign in database</string>
+         <string>Select operating band or frequency in MHz</string>
         </property>
-        <property name="text">
-         <string>&Lookup</string>
+        <property name="editable">
+         <bool>true</bool>
+        </property>
+        <property name="insertPolicy">
+         <enum>QComboBox::NoInsert</enum>
         </property>
        </widget>
       </item>
-      <item row="4" column="4">
-       <widget class="QPushButton" name="addButton">
+      <item row="3" column="7">
+       <widget class="QPushButton" name="pbT2R">
         <property name="sizePolicy">
-         <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+         <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
           <horstretch>0</horstretch>
           <verstretch>0</verstretch>
          </sizepolicy>
         </property>
         <property name="maximumSize">
          <size>
-          <width>74</width>
+          <width>48</width>
           <height>16777215</height>
          </size>
         </property>
         <property name="toolTip">
-         <string>Add callsign and locator to database</string>
+         <string>Set Rx frequency to Tx Frequency</string>
         </property>
         <property name="text">
-         <string>Add</string>
+         <string>Rx<Tx</string>
         </property>
        </widget>
       </item>
-      <item row="4" column="6">
-       <layout class="QHBoxLayout" name="horizontalLayout_5">
-        <property name="spacing">
-         <number>5</number>
-        </property>
-        <property name="sizeConstraint">
-         <enum>QLayout::SetFixedSize</enum>
-        </property>
-        <item>
-         <widget class="QPushButton" name="pbR2T">
-          <property name="sizePolicy">
-           <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-            <horstretch>0</horstretch>
-            <verstretch>0</verstretch>
-           </sizepolicy>
-          </property>
-          <property name="maximumSize">
-           <size>
-            <width>48</width>
-            <height>16777215</height>
-           </size>
-          </property>
-          <property name="toolTip">
-           <string>Set Tx frequency to Rx Frequency</string>
-          </property>
-          <property name="text">
-           <string>Tx=Rx</string>
-          </property>
-         </widget>
-        </item>
-        <item>
-         <widget class="QPushButton" name="pbT2R">
-          <property name="sizePolicy">
-           <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-            <horstretch>0</horstretch>
-            <verstretch>0</verstretch>
-           </sizepolicy>
-          </property>
-          <property name="maximumSize">
-           <size>
-            <width>48</width>
-            <height>16777215</height>
-           </size>
-          </property>
-          <property name="toolTip">
-           <string>Set Rx frequency to Tx Frequency</string>
-          </property>
-          <property name="text">
-           <string>Rx=Tx</string>
-          </property>
-         </widget>
-        </item>
-       </layout>
-      </item>
-      <item row="5" column="3" rowspan="2" colspan="2">
-       <widget class="QLabel" name="labUTC">
+      <item row="2" column="7">
+       <widget class="QPushButton" name="pbR2T">
         <property name="sizePolicy">
-         <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+         <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
           <horstretch>0</horstretch>
           <verstretch>0</verstretch>
          </sizepolicy>
         </property>
-        <property name="minimumSize">
-         <size>
-          <width>130</width>
-          <height>60</height>
-         </size>
-        </property>
         <property name="maximumSize">
          <size>
-          <width>158</width>
-          <height>60</height>
+          <width>48</width>
+          <height>16777215</height>
          </size>
         </property>
-        <property name="font">
-         <font>
-          <pointsize>16</pointsize>
-         </font>
-        </property>
-        <property name="frameShape">
-         <enum>QFrame::StyledPanel</enum>
-        </property>
-        <property name="frameShadow">
-         <enum>QFrame::Sunken</enum>
-        </property>
-        <property name="lineWidth">
-         <number>2</number>
-        </property>
-        <property name="midLineWidth">
-         <number>0</number>
+        <property name="toolTip">
+         <string>Set Tx frequency to Rx Frequency</string>
         </property>
         <property name="text">
-         <string> 01:23:45 </string>
-        </property>
-        <property name="alignment">
-         <set>Qt::AlignCenter</set>
+         <string>Tx<Rx</string>
         </property>
        </widget>
       </item>
-      <item row="5" column="6">
+      <item row="4" column="6">
        <widget class="QCheckBox" name="cbTxLock">
+        <property name="toolTip">
+         <string><html><head/><body><p>Tx frequency tracks Rx frequency</p></body></html></string>
+        </property>
         <property name="text">
          <string>Lock Tx=Rx</string>
         </property>
        </widget>
       </item>
-      <item row="6" column="6">
+      <item row="5" column="6">
        <layout class="QHBoxLayout" name="horizontalLayout_4">
         <property name="spacing">
          <number>5</number>
@@ -2166,7 +2204,7 @@ p, li { white-space: pre-wrap; }
            </size>
           </property>
           <property name="toolTip">
-           <string>Signal report (dB0</string>
+           <string><html><head/><body><p>Signal report (dB)</p></body></html></string>
           </property>
           <property name="minimum">
            <number>-50</number>
@@ -2181,6 +2219,52 @@ p, li { white-space: pre-wrap; }
         </item>
        </layout>
       </item>
+      <item row="2" column="1" rowspan="5">
+       <widget class="QSlider" name="inGain">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="minimumSize">
+         <size>
+          <width>0</width>
+          <height>160</height>
+         </size>
+        </property>
+        <property name="maximumSize">
+         <size>
+          <width>20</width>
+          <height>160</height>
+         </size>
+        </property>
+        <property name="toolTip">
+         <string>Digital gain for audio input</string>
+        </property>
+        <property name="minimum">
+         <number>-50</number>
+        </property>
+        <property name="maximum">
+         <number>50</number>
+        </property>
+        <property name="value">
+         <number>20</number>
+        </property>
+        <property name="orientation">
+         <enum>Qt::Vertical</enum>
+        </property>
+        <property name="invertedAppearance">
+         <bool>false</bool>
+        </property>
+        <property name="invertedControls">
+         <bool>false</bool>
+        </property>
+        <property name="tickPosition">
+         <enum>QSlider::TicksBelow</enum>
+        </property>
+       </widget>
+      </item>
      </layout>
     </item>
    </layout>
@@ -2190,7 +2274,7 @@ p, li { white-space: pre-wrap; }
     <rect>
      <x>0</x>
      <y>0</y>
-     <width>760</width>
+     <width>770</width>
      <height>21</height>
     </rect>
    </property>
@@ -2205,54 +2289,19 @@ p, li { white-space: pre-wrap; }
     <addaction name="actionDelete_all_wav_files_in_SaveDir"/>
     <addaction name="actionErase_ALL_TXT"/>
     <addaction name="actionErase_wsjtx_log_adi"/>
+    <addaction name="actionOpen_log_directory"/>
     <addaction name="separator"/>
-    <addaction name="actionExit"/>
-   </widget>
-   <widget class="QMenu" name="menuSetup">
-    <property name="title">
-     <string>Setup</string>
-    </property>
-    <widget class="QMenu" name="menuAdvanced">
-     <property name="enabled">
-      <bool>true</bool>
-     </property>
-     <property name="title">
-      <string>Advanced</string>
-     </property>
-     <addaction name="actionAllow_multiple_instances"/>
-    </widget>
-    <addaction name="actionDeviceSetup"/>
-    <addaction name="separator"/>
-    <addaction name="actionMonitor_OFF_at_startup"/>
-    <addaction name="actionConvert_JT9_x_to_RTTY"/>
-    <addaction name="actionLog_dB_reports_to_Comments"/>
-    <addaction name="actionPrompt_to_log_QSO"/>
-    <addaction name="actionBlank_line_between_decoding_periods"/>
-    <addaction name="actionClear_DX_Call_and_Grid_after_logging"/>
-    <addaction name="actionDisplay_distance_in_miles"/>
-    <addaction name="actionDouble_click_on_call_sets_Tx_Enable"/>
-    <addaction name="action_73TxDisable"/>
-    <addaction name="actionRunaway_Tx_watchdog"/>
-    <addaction name="actionTx2QSO"/>
+    <addaction name="actionSettings"/>
     <addaction name="separator"/>
-    <addaction name="menuAdvanced"/>
+    <addaction name="actionExit"/>
    </widget>
    <widget class="QMenu" name="menuView">
     <property name="title">
      <string>View</string>
     </property>
-    <widget class="QMenu" name="menuWaterfall_palette">
-     <property name="title">
-      <string>Waterfall palette</string>
-     </property>
-     <addaction name="actionLinrad"/>
-     <addaction name="actionCuteSDR"/>
-     <addaction name="actionAFMHot"/>
-     <addaction name="actionBlue"/>
-    </widget>
     <addaction name="actionWide_Waterfall"/>
     <addaction name="separator"/>
-    <addaction name="menuWaterfall_palette"/>
+    <addaction name="actionAstronomical_data"/>
    </widget>
    <widget class="QMenu" name="menuDecode">
     <property name="title">
@@ -2274,9 +2323,13 @@ p, li { white-space: pre-wrap; }
     <property name="title">
      <string>Help</string>
     </property>
-    <addaction name="actionOnline_Users_Guide"/>
+    <addaction name="actionOnline_User_Guide"/>
+    <addaction name="actionLocal_User_Guide"/>
+    <addaction name="separator"/>
     <addaction name="actionKeyboard_shortcuts"/>
     <addaction name="actionSpecial_mouse_commands"/>
+    <addaction name="actionShort_list_of_add_on_prefixes_and_suffixes"/>
+    <addaction name="separator"/>
     <addaction name="actionAbout"/>
    </widget>
    <widget class="QMenu" name="menuMode">
@@ -2286,9 +2339,9 @@ p, li { white-space: pre-wrap; }
     <addaction name="actionJT9_1"/>
     <addaction name="actionJT65"/>
     <addaction name="actionJT9_JT65"/>
+    <addaction name="actionJT9W_1"/>
    </widget>
    <addaction name="menuFile"/>
-   <addaction name="menuSetup"/>
    <addaction name="menuView"/>
    <addaction name="menuMode"/>
    <addaction name="menuDecode"/>
@@ -2300,6 +2353,9 @@ p, li { white-space: pre-wrap; }
    <property name="text">
     <string>Exit</string>
    </property>
+   <property name="menuRole">
+    <enum>QAction::QuitRole</enum>
+   </property>
   </action>
   <action name="actionDeviceSetup">
    <property name="checkable">
@@ -2314,30 +2370,12 @@ p, li { white-space: pre-wrap; }
   </action>
   <action name="actionAbout">
    <property name="text">
-    <string> About WSJT-X</string>
+    <string>About WSJT-X</string>
    </property>
    <property name="shortcut">
     <string>Ctrl+F1</string>
    </property>
   </action>
-  <action name="actionAstro_Data">
-   <property name="text">
-    <string>Astro Data</string>
-   </property>
-   <property name="shortcut">
-    <string>Shift+F10</string>
-   </property>
-  </action>
-  <action name="actionBand_Map">
-   <property name="text">
-    <string>Band Map</string>
-   </property>
-  </action>
-  <action name="actionMessages">
-   <property name="text">
-    <string>Messages</string>
-   </property>
-  </action>
   <action name="actionWide_Waterfall">
    <property name="text">
     <string>Waterfall</string>
@@ -2347,6 +2385,9 @@ p, li { white-space: pre-wrap; }
    <property name="text">
     <string>Open</string>
    </property>
+   <property name="shortcut">
+    <string>Ctrl+O</string>
+   </property>
   </action>
   <action name="actionOpen_next_in_directory">
    <property name="text">
@@ -2369,54 +2410,6 @@ p, li { white-space: pre-wrap; }
     <string>Delete all *.wav files in SaveDir</string>
    </property>
   </action>
-  <action name="actionErase_Band_Map_and_Messages">
-   <property name="text">
-    <string>Erase Band Map and Messages</string>
-   </property>
-  </action>
-  <action name="actionLinrad">
-   <property name="checkable">
-    <bool>true</bool>
-   </property>
-   <property name="checked">
-    <bool>true</bool>
-   </property>
-   <property name="text">
-    <string>Linrad</string>
-   </property>
-  </action>
-  <action name="actionCuteSDR">
-   <property name="checkable">
-    <bool>true</bool>
-   </property>
-   <property name="checked">
-    <bool>false</bool>
-   </property>
-   <property name="text">
-    <string>CuteSDR</string>
-   </property>
-  </action>
-  <action name="actionFind_Delta_Phi">
-   <property name="text">
-    <string>Find Delta Phi</string>
-   </property>
-  </action>
-  <action name="actionF4_sets_Tx6">
-   <property name="checkable">
-    <bool>true</bool>
-   </property>
-   <property name="text">
-    <string>F4 sets Tx6</string>
-   </property>
-  </action>
-  <action name="actionNo_shorthands_if_Tx1">
-   <property name="checkable">
-    <bool>true</bool>
-   </property>
-   <property name="text">
-    <string>No shorthand decodes if Tx1</string>
-   </property>
-  </action>
   <action name="actionQuickDecode">
    <property name="checkable">
     <bool>true</bool>
@@ -2447,60 +2440,9 @@ p, li { white-space: pre-wrap; }
     <string>Save all</string>
    </property>
   </action>
-  <action name="action50">
-   <property name="checkable">
-    <bool>true</bool>
-   </property>
-   <property name="text">
-    <string>50</string>
-   </property>
-  </action>
-  <action name="action144">
-   <property name="checkable">
-    <bool>true</bool>
-   </property>
-   <property name="checked">
-    <bool>true</bool>
-   </property>
-   <property name="text">
-    <string>144</string>
-   </property>
-  </action>
-  <action name="action222">
-   <property name="checkable">
-    <bool>true</bool>
-   </property>
-   <property name="text">
-    <string>222</string>
-   </property>
-  </action>
-  <action name="action432">
-   <property name="checkable">
-    <bool>true</bool>
-   </property>
-   <property name="text">
-    <string>432</string>
-   </property>
-  </action>
-  <action name="action1296">
-   <property name="checkable">
-    <bool>true</bool>
-   </property>
-   <property name="text">
-    <string>1296</string>
-   </property>
-  </action>
-  <action name="action2304">
-   <property name="checkable">
-    <bool>true</bool>
-   </property>
-   <property name="text">
-    <string>2304</string>
-   </property>
-  </action>
-  <action name="actionOnline_Users_Guide">
+  <action name="actionOnline_User_Guide">
    <property name="text">
-    <string>Online User's Guide</string>
+    <string>Online User Guide</string>
    </property>
    <property name="shortcut">
     <string>F1</string>
@@ -2522,80 +2464,6 @@ p, li { white-space: pre-wrap; }
     <string>F5</string>
    </property>
   </action>
-  <action name="actionAvailable_suffixes_and_add_on_prefixes">
-   <property name="text">
-    <string>Available suffixes and add-on-prefixes</string>
-   </property>
-  </action>
-  <action name="actionJT65A">
-   <property name="checkable">
-    <bool>true</bool>
-   </property>
-   <property name="text">
-    <string>JT65A</string>
-   </property>
-  </action>
-  <action name="actionJT65B">
-   <property name="checkable">
-    <bool>true</bool>
-   </property>
-   <property name="checked">
-    <bool>true</bool>
-   </property>
-   <property name="text">
-    <string>JT65B</string>
-   </property>
-  </action>
-  <action name="actionJT65C">
-   <property name="checkable">
-    <bool>true</bool>
-   </property>
-   <property name="text">
-    <string>JT65C</string>
-   </property>
-  </action>
-  <action name="actionI_Q_Calibration">
-   <property name="text">
-    <string>I/Q Calibration</string>
-   </property>
-   <property name="shortcut">
-    <string>F7</string>
-   </property>
-  </action>
-  <action name="actionAdjust_IQ_Calibration">
-   <property name="text">
-    <string>Adjust I/Q Calibration</string>
-   </property>
-  </action>
-  <action name="actionApply_IQ_Calibration">
-   <property name="checkable">
-    <bool>true</bool>
-   </property>
-   <property name="text">
-    <string>Apply I/Q Calibration</string>
-   </property>
-  </action>
-  <action name="actionAFMHot">
-   <property name="checkable">
-    <bool>true</bool>
-   </property>
-   <property name="text">
-    <string>AFMHot</string>
-   </property>
-  </action>
-  <action name="actionBlue">
-   <property name="checkable">
-    <bool>true</bool>
-   </property>
-   <property name="text">
-    <string>Blue</string>
-   </property>
-  </action>
-  <action name="actionFUNcube_Dongle">
-   <property name="text">
-    <string>FUNcube Dongle Settings</string>
-   </property>
-  </action>
   <action name="actionJT9_1">
    <property name="checkable">
     <bool>true</bool>
@@ -2607,58 +2475,6 @@ p, li { white-space: pre-wrap; }
     <string>JT9</string>
    </property>
   </action>
-  <action name="actionJT9_2">
-   <property name="checkable">
-    <bool>true</bool>
-   </property>
-   <property name="text">
-    <string>JT9-2</string>
-   </property>
-  </action>
-  <action name="actionJT9_5">
-   <property name="checkable">
-    <bool>true</bool>
-   </property>
-   <property name="enabled">
-    <bool>false</bool>
-   </property>
-   <property name="text">
-    <string>JT9-5</string>
-   </property>
-  </action>
-  <action name="actionJT9_10">
-   <property name="checkable">
-    <bool>true</bool>
-   </property>
-   <property name="enabled">
-    <bool>false</bool>
-   </property>
-   <property name="text">
-    <string>JT9-10</string>
-   </property>
-  </action>
-  <action name="actionJT9_30">
-   <property name="checkable">
-    <bool>true</bool>
-   </property>
-   <property name="enabled">
-    <bool>false</bool>
-   </property>
-   <property name="text">
-    <string>JT9-30</string>
-   </property>
-  </action>
-  <action name="actionSave_synced">
-   <property name="checkable">
-    <bool>true</bool>
-   </property>
-   <property name="enabled">
-    <bool>false</bool>
-   </property>
-   <property name="text">
-    <string>Save synced</string>
-   </property>
-  </action>
   <action name="actionSave_decoded">
    <property name="checkable">
     <bool>true</bool>
@@ -2710,14 +2526,6 @@ p, li { white-space: pre-wrap; }
     <string>Erase wsjtx_log.adi</string>
    </property>
   </action>
-  <action name="actionLog_JT9_without_submode">
-   <property name="checkable">
-    <bool>true</bool>
-   </property>
-   <property name="text">
-    <string>Log JT9 without submode</string>
-   </property>
-  </action>
   <action name="actionConvert_JT9_x_to_RTTY">
    <property name="checkable">
     <bool>true</bool>
@@ -2758,11 +2566,6 @@ p, li { white-space: pre-wrap; }
     <string>Clear DX Call and Grid after logging</string>
    </property>
   </action>
-  <action name="actionDistance_in_miles">
-   <property name="text">
-    <string>Distance in miles</string>
-   </property>
-  </action>
   <action name="actionDisplay_distance_in_miles">
    <property name="checkable">
     <bool>true</bool>
@@ -2778,6 +2581,9 @@ p, li { white-space: pre-wrap; }
    <property name="text">
     <string>Double-click on call sets Tx Enable</string>
    </property>
+   <property name="shortcut">
+    <string>F7</string>
+   </property>
   </action>
   <action name="action_73TxDisable">
    <property name="checkable">
@@ -2835,12 +2641,64 @@ p, li { white-space: pre-wrap; }
     <string>Tx messages to Rx Frequency window</string>
    </property>
   </action>
+  <action name="actionGray1">
+   <property name="checkable">
+    <bool>true</bool>
+   </property>
+   <property name="text">
+    <string>Gray1</string>
+   </property>
+  </action>
+  <action name="actionEnable_DXCC_entity">
+   <property name="checkable">
+    <bool>true</bool>
+   </property>
+   <property name="text">
+    <string>Show DXCC entity and worked B4 status</string>
+   </property>
+  </action>
+  <action name="actionAstronomical_data">
+   <property name="text">
+    <string>Astronomical data</string>
+   </property>
+  </action>
+  <action name="actionJT9W_1">
+   <property name="checkable">
+    <bool>true</bool>
+   </property>
+   <property name="text">
+    <string>JT9W-1</string>
+   </property>
+  </action>
+  <action name="actionShort_list_of_add_on_prefixes_and_suffixes">
+   <property name="text">
+    <string>Short list of add-on prefixes and suffixes</string>
+   </property>
+  </action>
+  <action name="actionSettings">
+   <property name="text">
+    <string>Settings...</string>
+   </property>
+   <property name="shortcut">
+    <string>F2</string>
+   </property>
+  </action>
+  <action name="actionLocal_User_Guide">
+   <property name="text">
+    <string>Local User Guide</string>
+   </property>
+  </action>
+  <action name="actionOpen_log_directory">
+   <property name="text">
+    <string>Open log directory</string>
+   </property>
+  </action>
  </widget>
  <layoutdefault spacing="6" margin="11"/>
  <customwidgets>
   <customwidget>
    <class>DisplayText</class>
-   <extends>QTextBrowser</extends>
+   <extends>QTextEdit</extends>
    <header>displaytext.h</header>
   </customwidget>
  </customwidgets>
@@ -2854,14 +2712,11 @@ p, li { white-space: pre-wrap; }
   <tabstop>stopTxButton</tabstop>
   <tabstop>tuneButton</tabstop>
   <tabstop>bandComboBox</tabstop>
-  <tabstop>readFreq</tabstop>
   <tabstop>inGain</tabstop>
   <tabstop>dxCallEntry</tabstop>
   <tabstop>dxGridEntry</tabstop>
   <tabstop>txFirstCheckBox</tabstop>
   <tabstop>TxFreqSpinBox</tabstop>
-  <tabstop>pbR2T</tabstop>
-  <tabstop>pbT2R</tabstop>
   <tabstop>rptSpinBox</tabstop>
   <tabstop>tabWidget</tabstop>
   <tabstop>genStdMsgsPushButton</tabstop>
@@ -2869,7 +2724,6 @@ p, li { white-space: pre-wrap; }
   <tabstop>tx2</tabstop>
   <tabstop>tx3</tabstop>
   <tabstop>tx4</tabstop>
-  <tabstop>tx5</tabstop>
   <tabstop>tx6</tabstop>
   <tabstop>txrb1</tabstop>
   <tabstop>txrb2</tabstop>
@@ -2883,13 +2737,10 @@ p, li { white-space: pre-wrap; }
   <tabstop>txb4</tabstop>
   <tabstop>txb5</tabstop>
   <tabstop>txb6</tabstop>
-  <tabstop>decodedTextBrowser</tabstop>
-  <tabstop>decodedTextBrowser2</tabstop>
   <tabstop>genMsg</tabstop>
   <tabstop>pbAnswerCaller</tabstop>
   <tabstop>rbFreeText</tabstop>
   <tabstop>pbSendRRR</tabstop>
-  <tabstop>freeTextMsg</tabstop>
   <tabstop>pbAnswerCQ</tabstop>
   <tabstop>pbSendReport</tabstop>
   <tabstop>pbSend73</tabstop>
diff --git a/manpages/CMakeLists.txt b/manpages/CMakeLists.txt
new file mode 100644
index 0000000..1576ad5
--- /dev/null
+++ b/manpages/CMakeLists.txt
@@ -0,0 +1,81 @@
+set (ASCIIDOC_MANS
+  man1/wsjtx.1.txt
+  man1/jt65code.1.txt
+  man1/rigctl-wsjtx.1.txt
+  man1/rigctld-wsjtx.1.txt
+  )
+
+find_program (A2X_EXECUTABLE NAMES a2x a2x.py)
+if (NOT A2X_EXECUTABLE)
+  if (NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
+    message (SEND_ERROR "Failed to find a2x which is an optional requirement for non-debug
+builds on *nix platforms.
+
+You can choose to skip manpage generation and this error by setting
+the CMake option WSJT_SKIP_MANPAGES to ON. This option is designed for
+those that are building for their own use, package builders should not
+opt to skip manpage generation since package building requires the
+manpages.")
+
+  else (NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
+    message (WARNING "Failed to find a2x skipping manpage generation.")
+  endif (NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
+endif ()
+find_program (GZIP_EXECUTABLE NAMES gzip)
+find_program (SED_EXECUTABLE NAMES sed)
+
+set (XSLTPROC_OPTS 
+  "-param man.endnotes.list.enabled 0 -param man.endnotes.are.numbered 0"
+  )
+set (A2X_OPTS
+  --format=manpage
+  --xsltproc-opts=${XSLTPROC_OPTS}
+  --doctype=manpage
+  --no-xmllint
+  )
+
+set (MANPAGES)
+if (A2X_EXECUTABLE AND GZIP_EXECUTABLE AND SED_EXECUTABLE)
+  foreach (f IN LISTS ASCIIDOC_MANS)
+    get_filename_component (d "${f}" PATH)
+    string (SUBSTRING "${d}" 3 -1 section)
+    if (NOT section MATCHES "[1-9]")
+      message (SEND_ERROR "Invalid man section ${section} in ${f}")
+    endif (NOT section MATCHES "[1-9]")
+    get_filename_component (filename "${f}" NAME)
+    get_filename_component (filename_we "${f}" NAME_WE)
+    set (f "${CMAKE_CURRENT_SOURCE_DIR}/${f}")
+    set (d "man/${d}")
+    set (o "${d}/${filename_we}.${section}.gz")
+    add_custom_command (OUTPUT "${o}"
+      COMMAND ${CMAKE_COMMAND} ARGS -E make_directory "${d}"
+      COMMAND ${CMAKE_COMMAND} ARGS -E copy "${f}" "${d}"
+      COMMAND ${A2X_EXECUTABLE} ARGS ${A2X_OPTS} "${d}/${filename}"
+      COMMAND ${CMAKE_COMMAND} ARGS -E remove "${d}/${filename}"
+#
+# the following edit command is used to make the alias manpages
+# compatible with Debian packaging rules when a2x generates alias
+# pages baseed in the section directory instead of the man parent
+# directory
+#
+      COMMAND ${SED_EXECUTABLE} ARGS -e '/^.so [^\\/]*$$/s at .so @&man${section}\\/@' -i.orig "${d}/*.${section}"
+      COMMAND ${GZIP_EXECUTABLE} ARGS -f9 "${d}/*.${section}"
+      DEPENDS "${f}" "${previous_output}"
+      COMMENT "Generating ${o}"
+      )
+    list (APPEND MANPAGES "${o}")
+
+    # use this as a dependency in the next iteration to serialize so
+    # that gzips don't overlap in parallel builds
+    set (previous_output "${o}")
+  endforeach ()
+
+  install (
+    DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/man
+    DESTINATION ${WSJT_MANPAGE_DESTINATION}
+    PATTERN "*.orig" EXCLUDE
+    #COMPONENT Runtime
+    )
+endif (A2X_EXECUTABLE AND GZIP_EXECUTABLE AND SED_EXECUTABLE)
+
+add_custom_target (manpages DEPENDS ${MANPAGES})
diff --git a/manpages/man1/jt65code.1.txt b/manpages/man1/jt65code.1.txt
new file mode 100644
index 0000000..0c3dc37
--- /dev/null
+++ b/manpages/man1/jt65code.1.txt
@@ -0,0 +1,104 @@
+:doctype: manpage
+:man source: AsciiDoc
+:man version: {revnumber}
+:man manual: WSJT-X Manual
+= jt65code(1)
+
+== NAME
+
+jt65code, jt9code - Weak signal communications encoding support utility.
+
+== SYNOPSIS
+
+*jt65code* MESSAGE
+
+*jt9code* MESSAGE
+
+== DESCRIPTION
+
+*jt65code* and *jt9code* are utility programs that let you explore the
+conversion of user-level messages into channel symbols or “tone
+numbers.” These programs can be useful to someone designing a beacon
+generator for JT9 or JT65, or for studying behavior of the
+error-control codes.
+
+Channel-symbol values for JT9 run from 0 to 8, with 0 representing the
+sync tone. The total number of symbols in a transmitted message is
+85. To run jt9code, enter the program name followed by a JT9 message
+enclosed in quotes. In Windows the command and program output might
+look like this:
+
+.....
+$ jt9code "G0XYZ K1ABC FN42"
+Message:   G0XYZ K1ABC FN42
+Channel symbols:
+ 0 0 7 3 0 3 2 5 4 0 1 7 7 7 8 0 4 8 8 2 2 1 0 1 1 3 5 4 5 6
+ 8 7 0 6 0 1 8 3 3 7 8 1 1 2 4 5 8 1 5 2 0 0 8 6 0 5 8 5 1 0
+ 5 8 7 7 2 0 4 6 6 6 7 6 0 1 8 8 5 7 2 5 1 5 0 4 0
+Decoded message: G0XYZ K1ABC FN42
+.....
+
+For the corresponding program jt65code only the information-carrying
+channel symbols are shown, and the symbol values range from 0 to
+63. Sync synbols lie two tone intervals below data tone 0, and the
+sequential locations of sync symbols are described in the JT65
+Protocol section of this Guide.
+
+A typical execution of jt65code is shown below. The program displays
+the packed message of 72 bits, shown here as 12 six-bit symbol values,
+followed by the channel symbols:
+
+.....
+$ jt65code "G0XYZ K1ABC FN42"
+Message:   G0XYZ K1ABC FN42
+Packed message, 6-bit symbols:  61 36 45 30  3 55  3  2 14  5 33 40
+Information-carrying channel symbols:
+   56 40  8 40 51 47 50 34 44 53 22 53 28 31 13 60 46  2 14 58 43
+   41 58 35  8 35  3 24  1 21 41 43  0 25 54  9 41 54  7 25 21  9
+   62 59  7 43 31 21 57 13 59 41 17 49 19 54 21 39 33 42 18  2 60
+Decoded message: G0XYZ K1ABC FN42
+.....
+
+For an illustration of the power of the strong error-control coding in
+JT9 and JT65, try looking at the channel symbols after changing a
+single character in the message. For example, change the grid locater
+from FN42 to FN43 in the JT65 message:
+
+.....
+$ jt65code "G0XYZ K1ABC FN43"
+Message:   G0XYZ K1ABC FN43
+Packed message, 6-bit symbols:  61 36 45 30  3 55  3  2 14  5 33 41
+Information-carrying channel symbols:
+   25 35 47  8 13  9 61 40 44  9 51  6  8 40 38 34  8  2 21 23 30
+   51 32 56 39 35  3 50 48 30  8  5 40 18 54  9 24 30 26 61 23 11
+    3 59  7  7 39  1 25 24  4 50 17 49 52 19 34  7  4 34 61  2 61
+Decoded message: G0XYZ K1ABC FN43
+.....
+
+You will discover that every possible JT65 message differs from every
+other possible JT65 message in at least 52 of the 63
+information-carrying channel symbols.
+
+WSJT-X home page:: http://www.physics.princeton.edu/pulsar/K1JT/wsjtx.html
+
+WSJT-X User's Guide:: http://www.physics.princeton.edu/pulsar/K1JT/wsjtx-doc/wsjtx-main.html
+
+== OPTIONS
+
+== FILES
+
+== AUTHOR
+
+Joe Taylor, K1JT.
+
+== COPYING
+
+*jt65code* and *jt9code* are Copyright (C) 2001 - 2014 by Joseph
+H. Taylor, Jr., K1JT, with contributions from additional authors.
+WSJT-X is Open Source software, licensed under the GNU General Public
+License (GPLv3).
+
+These programs are distributed in the hope that they 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.
diff --git a/manpages/man1/rigctl-wsjtx.1.txt b/manpages/man1/rigctl-wsjtx.1.txt
new file mode 100644
index 0000000..e96667f
--- /dev/null
+++ b/manpages/man1/rigctl-wsjtx.1.txt
@@ -0,0 +1,29 @@
+:doctype: manpage
+:man source: AsciiDoc
+:man version: {revnumber}
+:man manual: WSJT-X Manual
+= rigctl-wsjtx(1)
+
+== NAME
+
+rigctl-wsjtx - Hamlib 3 rigctld server.
+
+== SYNOPSIS
+
+*rigctl-wsjtx* [OPTIONS]
+
+== DESCRIPTION
+
+*wsjtx* uses a version of the *hamlib* CAT control library.  This
+ library is heavily modified over the current release version of
+ *hamlib*. If a *wsjtx* user wishes to use the *hamlib* network rig
+ server *rigctld* to remotely control their transceiver; then this
+ special version of the *rigctl* client should be used since that too
+ has the modified *hamlib* code embedded with it.
+
+WSJT-X home page:: http://www.physics.princeton.edu/pulsar/K1JT/wsjtx.html
+
+WSJT-X User's Guide:: http://www.physics.princeton.edu/pulsar/K1JT/wsjtx-doc/wsjtx-main-toc2.html
+
+== OPTIONS
+Refer to the *hamlib* documentation.
diff --git a/manpages/man1/rigctld-wsjtx.1.txt b/manpages/man1/rigctld-wsjtx.1.txt
new file mode 100644
index 0000000..6cf9ebf
--- /dev/null
+++ b/manpages/man1/rigctld-wsjtx.1.txt
@@ -0,0 +1,29 @@
+:doctype: manpage
+:man source: AsciiDoc
+:man version: {revnumber}
+:man manual: WSJT-X Manual
+= rigctld-wsjtx(1)
+
+== NAME
+
+rigctld-wsjtx - Hamlib 3 rigctld server.
+
+== SYNOPSIS
+
+*rigctld-wsjtx* [OPTIONS]
+
+== DESCRIPTION
+
+*wsjtx* uses a version of the *hamlib* CAT control library.  This
+ library is heavily modified over the current release version of
+ *hamlib*. If a *wsjtx* user wishes to use the *hamlib* network rig
+ server *rigctld* to remotely control their transceiver; then this
+ special version of *rigctld* should be used since that too has the
+ modified *hamlib* code embedded with it.
+
+WSJT-X home page:: http://www.physics.princeton.edu/pulsar/K1JT/wsjtx.html
+
+WSJT-X User's Guide:: http://www.physics.princeton.edu/pulsar/K1JT/wsjtx-doc/wsjtx-main-toc2.html
+
+== OPTIONS
+Refer to the *hamlib* documentation.
diff --git a/manpages/man1/wsjtx.1.txt b/manpages/man1/wsjtx.1.txt
new file mode 100644
index 0000000..c88c43b
--- /dev/null
+++ b/manpages/man1/wsjtx.1.txt
@@ -0,0 +1,120 @@
+:doctype: manpage
+:man source: AsciiDoc
+:man version: {revnumber}
+:man manual: WSJT-X Manual
+= wsjtx(1)
+
+== NAME
+
+wsjtx, jt9 - Weak signal communications program.
+
+== SYNOPSIS
+
+*wsjtx* [OPTIONS]
+
+== DESCRIPTION
+
+*wsjtx* is a weak signal communications program supporting two operating
+modes: JT65 and JT9 (*wsjtx* version 1 supported JT9 only).
+
+WSJT-X home page:: http://www.physics.princeton.edu/pulsar/K1JT/wsjtx.html
+
+WSJT-X User's Guide:: http://www.physics.princeton.edu/pulsar/K1JT/wsjtx-doc/wsjtx-main-toc2.html
+
+An alternative JT65 decoder executable *kvasd* for i386 Ubuntu is
+available at http://www.physics.princeton.edu/pulsar/K1JT/kvasd .
+This decoder is not open-source, is not included in the wsjtx package,
+and is not required for JT65 decoding.
+
+== OPTIONS
+*-r, --rig-name*[=RIGNAME]::
+
+Enable multiple instances of the wsjtx(1) application to run
+concurrently.  Each RIGNAME must be unique. One instance may use no
+RIGNAME. If this option is not supplied then only one instance of
+wsjtx(1) may be run at any time.
+
+*-v, --version*:: Display the application version.
+
+*-h,--help*:: Display usage information.
+
+*--test-mode*::
+
+When this option is provided all writable files will be placed in a
+special test location (~/.qttest).  This option is only for
+application testing and is not designed for normal operations.  **Use
+with caution**.
+
+== FILES
+
+Most of the following files are in a directory path containing the
+directory name *WSJT-X[ - RIGNAME]* which indicates the value of the
+command line option *--rig-name=RIGNAME* to indicate multiple instances of
+*wsjtx* running concurrently. All writable files listed below are
+therefore unique to each concurrent instance of *wsjtx*. If the
+*--rig-name* command line option is not supplied or the *RIGNAME* argument
+is not supplied then the directory paths below will have the directory
+*WSJT-X*.
+
+~/.config/WSJT-X[ - RIGNAME].ini::
+
+This file stores the application
+configuration settings.
+
+~/.local/share/WSJT-X[ - RIGNAME]/ALL.txt::
+
+*ALL.txt* contains a record of transmitted and received messages and
+other activity such as frequency or band changes.
+
+~/.local/share/WSJT-X[ - RIGNAME]/save/::
+
+Is the default location for saved .WAV files recorded by the
+application.  The .WAV file save location may be changed in the
+applications settings dialog.
+
+~/.local/share/WSJT-X[ - RIGNAME]/save/samples/::
+
+Sample .WAV files suppied with the application are found in this
+directory, they may be played back in the application and are referred
+to in the user guide tutorial sections.
+
+~/.local/share/WSJT-X[ -RIGNAME]/timer.out::
+
+This is a diagnostic file that records decode performance profiling
+information.
+
+~/.local/share/WSJT-X[ - RIGNAME]/cty.dat::
+
+This file is not required as a version of it is embedded in the
+application, but if you wish an updated version can be placed here.
+If present that version will be used in preference to the embedded
+version.
+
+~/.local/share/WSJT-X[ - RIGNAME]/wsjtx.log::
+
+This is a plain text CSV record of logged QSOs.
+
+~/.local/share/WSJT-X[ - RIGNAME]/wsjtx_log.adi::
+
+This is a record of QSOs logged in the ADIF format which is suitable
+for import into many Ham Radio logging programs.
+
+== AUTHOR
+
+Joe Taylor, K1JT.
+
+== COPYING
+
+*wsjtx* is Copyright (C) 2001 - 2014 by Joseph H. Taylor, Jr., K1JT,
+with contributions from additional authors.  WSJT-X is Open Source
+software, licensed under the GNU General Public License (GPLv3).
+
+*wsjtx* includes the ``**Hamlib - Ham Radio Control Libraries**''
+software which is licensed under the GNU Lesser General Public License
+(LGPL).  Home page https://sourceforge.net/apps/mediawiki/hamlib,
+sources from https://sourceforge.net/p/hamlib/code/ci/master/tree/.
+
+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.
diff --git a/message_aggregator.qrc.in b/message_aggregator.qrc.in
new file mode 100644
index 0000000..792aa44
--- /dev/null
+++ b/message_aggregator.qrc.in
@@ -0,0 +1,5 @@
+<!DOCTYPE RCC>
+<RCC version="1.0">
+  <qresource>@message_aggregator_RESOURCES@
+  </qresource>
+</RCC>
diff --git a/meterwidget.cpp b/meterwidget.cpp
index b48aa65..e36097e 100644
--- a/meterwidget.cpp
+++ b/meterwidget.cpp
@@ -3,6 +3,8 @@
 
 #include "meterwidget.h"
 
+#include "moc_meterwidget.cpp"
+
 MeterWidget::MeterWidget(QWidget *parent) :
     QWidget(parent),
     m_signal(0)
diff --git a/meterwidget.h b/meterwidget.h
index 7b51efb..fbc27b6 100644
--- a/meterwidget.h
+++ b/meterwidget.h
@@ -1,3 +1,4 @@
+// -*- Mode: C++ -*-
 #ifndef METERWIDGET_H
 #define METERWIDGET_H
 
diff --git a/mouse_commands.txt b/mouse_commands.txt
index 8e26589..c147e82 100644
--- a/mouse_commands.txt
+++ b/mouse_commands.txt
@@ -14,5 +14,4 @@ Decoded text:	 Double-click to copy second callsign to Dx Call,
 Erase button:	 Click to erase QSO window
       	 Double-click to erase QSO and Band Activity windows
 
-Tx5 Entry:	 Right-click to select a macro message
 
diff --git a/paInputDevice.c b/paInputDevice.c
deleted file mode 100644
index 641bd85..0000000
--- a/paInputDevice.c
+++ /dev/null
@@ -1,56 +0,0 @@
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-
-void paInputDevice(int id, char* hostAPI_DeviceName, int* minChan, 
-		   int* maxChan, int* minSpeed, int* maxSpeed)
-{
-  int i, j, k;
-  char pa_device_name[128];     
-  char pa_device_hostapi[128]; 
-  double pa_device_max_speed;
-  double pa_device_min_speed;
-  int pa_device_max_bytes;
-  int pa_device_min_bytes;
-  int pa_device_max_channels;
-  int pa_device_min_channels;
-  char p2[50];
-  char *p,*p1;
-  static int iret, numDevices, valid_dev_cnt;
-
-  iret=pa_get_device_info (id,
-                          &pa_device_name,
-                          &pa_device_hostapi,
-			  &pa_device_max_speed,
-			  &pa_device_min_speed,
-			  &pa_device_max_bytes,
-			  &pa_device_min_bytes,
-			  &pa_device_max_channels,
-			  &pa_device_min_channels);
-
-  if (iret >= 0 ) {
-    valid_dev_cnt++;
-
-    p1="";
-    p=strstr(pa_device_hostapi,"MME");
-    if(p!=NULL) p1="MME";
-    p=strstr(pa_device_hostapi,"Direct");
-    if(p!=NULL) p1="DirectX";
-    p=strstr(pa_device_hostapi,"WASAPI");
-    if(p!=NULL) p1="WASAPI";
-    p=strstr(pa_device_hostapi,"ASIO");
-    if(p!=NULL) p1="ASIO";
-    p=strstr(pa_device_hostapi,"WDM-KS");
-    if(p!=NULL) p1="WDM-KS";
-
-    sprintf(p2,"%-8s %-39s",p1,pa_device_name);
-    for(i=0; i<50; i++) {
-      hostAPI_DeviceName[i]=p2[i];
-      if(p2[i]==0) break;
-    }
-    *minChan=pa_device_min_channels;
-    *maxChan=pa_device_max_channels;
-    *minSpeed=(int)pa_device_min_speed;
-    *maxSpeed=(int)pa_device_max_speed;
-  }
-}
diff --git a/pa_get_device_info.c b/pa_get_device_info.c
deleted file mode 100644
index ac6bc9f..0000000
--- a/pa_get_device_info.c
+++ /dev/null
@@ -1,172 +0,0 @@
-#include <portaudio.h>
-#include <stdio.h>
-
-#define MAX_LATENCY 20
-
-PaStream *in_stream;
-//------------------------------------------------------- pa_get_device_info
-int pa_get_device_info (int  n,
-                        void *pa_device_name,
-                        void *pa_device_hostapi, 
-			double *pa_device_max_speed,
-			double *pa_device_min_speed,
-			int *pa_device_max_bytes,
-			int *pa_device_min_bytes,
-			int *pa_device_max_channels,
-			int *pa_device_min_channels )
-{
-
-  (void) n ;
-  (void) pa_device_name;
-  (void) pa_device_hostapi; 
-  (void) pa_device_max_speed;
-  (void) pa_device_min_speed;
-  (void) pa_device_max_bytes;
-  (void) pa_device_min_bytes;
-  (void) pa_device_max_channels;
-  (void) pa_device_min_channels;
-  const PaDeviceInfo *deviceInfo;
-  PaError pa_err;
-  PaStreamParameters inputParameters;
-  int i,j, speed_warning;
-  int minBytes, maxBytes;
-  double maxStandardSampleRate;
-  double minStandardSampleRate;
-  int minInputChannels;
-  int maxInputChannels;
-
-// negative terminated  list
-  static double standardSampleRates[] = {8000.0, 9600.0, 
-        11025.0, 12000.0, 16000.0, 22050.0, 24000.0, 32000.0,
-        44100.0, 48000.0, 88200.0, 96000.0, 192000.0, -1};
-// *******************************************************
-
-
-  *pa_device_max_speed=0;
-  *pa_device_min_speed=0;
-  *pa_device_max_bytes=0;
-  *pa_device_min_bytes=0;
-  *pa_device_max_channels=0;
-  *pa_device_min_channels=0;
-  minInputChannels=0;
-  if(n >= Pa_GetDeviceCount() ) return -1;
-  deviceInfo = Pa_GetDeviceInfo(n);
-  if (deviceInfo->maxInputChannels==0) return -1; 
-  sprintf((char*)(pa_device_name),"%s",deviceInfo->name);
-  sprintf((char*)(pa_device_hostapi),"%s",
-	  Pa_GetHostApiInfo( deviceInfo->hostApi )->name);
-  speed_warning=0;
-
-// bypass bug in Juli@ ASIO driver: 
-// this driver hangs after a Pa_IsFormatSupported call 
-  i = strncmp(deviceInfo->name, "ASIO 2.0 - ESI Juli@", 19);
-  if (i == 0) {
-    minStandardSampleRate=44100;
-    maxStandardSampleRate=192000;
-    minBytes=1;
-    maxBytes=4;
-    maxInputChannels= deviceInfo->maxInputChannels;
-    minInputChannels= 1;
-    goto end_pa_get_device_info;
-  }
-
-// Investigate device capabilities.
-// Check min and max samplerates  with 16 bit data.
-  maxStandardSampleRate=0;
-  minStandardSampleRate=0;
-  inputParameters.device = n;
-  inputParameters.channelCount = deviceInfo->maxInputChannels;
-  inputParameters.sampleFormat = paInt16;
-  inputParameters.suggestedLatency = 0;
-  inputParameters.hostApiSpecificStreamInfo = NULL;
-
-// ************************************************************************
-//filter for portaudio Windows hostapi's with non experts.
-//only allow ASIO or WASAPI or WDM-KS
-  i = strncmp(Pa_GetHostApiInfo(deviceInfo->hostApi)->name, "ASIO", 4);
-  if (i==0 ) goto end_filter_hostapi;
-  i = strncmp(Pa_GetHostApiInfo(deviceInfo->hostApi)->name, 
-	      "Windows WASAPI", 14);
-  if (i==0 ) goto end_filter_hostapi;
-  i = strncmp(Pa_GetHostApiInfo(deviceInfo->hostApi)->name, 
-	      "Windows WDM-KS", 14);
-  if (i==0 ) goto end_filter_hostapi;
-  speed_warning=1;
-end_filter_hostapi:;
-
-// ************************************************************************
-  i=0;
-  while(standardSampleRates[i] > 0 && minStandardSampleRate==0) {
-    pa_err=Pa_IsFormatSupported(&inputParameters, NULL, 
-				standardSampleRates[i] );
-    if(pa_err == paDeviceUnavailable) return -1;
-    if(pa_err == paInvalidDevice) return -1;
-    if(pa_err == paFormatIsSupported ) { 
-      minStandardSampleRate=standardSampleRates[i];
-    }
-    i++;
-  }
-  if(minStandardSampleRate == 0) return -1;
-  j=i;
-  while(standardSampleRates[i] > 0 ) i++;
-  i--;
-  while(i >= j && maxStandardSampleRate==0) {
-      pa_err=Pa_IsFormatSupported(&inputParameters, NULL, 
-				  standardSampleRates[i] );
-    if(pa_err == paDeviceUnavailable) return -1;
-    if(pa_err == paInvalidDevice) return -1;
-    if( pa_err == paFormatIsSupported ) { 
-      maxStandardSampleRate=standardSampleRates[i];
-    }
-    i--;
-  }
-
-// check if min SampleRate  = max SampleRate 
-  if(maxStandardSampleRate==0 && (minStandardSampleRate != 0)) {
-    maxStandardSampleRate= minStandardSampleRate;
-  }
-
-// check min and max bytes
-  minBytes=2;
-  maxBytes=2;
-  inputParameters.sampleFormat = paUInt8;
-  pa_err=Pa_IsFormatSupported(&inputParameters, NULL, 
-				maxStandardSampleRate );
-  if( pa_err == paFormatIsSupported ) { 
-    minBytes=1;
-  }
-    inputParameters.sampleFormat = paInt32;
-    pa_err=Pa_IsFormatSupported(&inputParameters, NULL, 
-				maxStandardSampleRate );
-  if( pa_err == paFormatIsSupported ) { 
-    maxBytes=4;
-  }
-
-// check min channel count
-  maxInputChannels= deviceInfo->maxInputChannels;
-  inputParameters.channelCount = 1;
-  inputParameters.sampleFormat = paInt16;
-  pa_err=paFormatIsSupported+32000;
-  while(pa_err != paFormatIsSupported &&
-	  ( inputParameters.channelCount < (maxInputChannels+1)) ) {
-    pa_err=Pa_IsFormatSupported(&inputParameters, NULL, 
-				maxStandardSampleRate );
-    inputParameters.channelCount++;
-  }
-  if( pa_err == paFormatIsSupported ) {
-    minInputChannels=inputParameters.channelCount-1;
-  } else {
-    return -1;
-  }
-
-end_pa_get_device_info:;
-
-  *pa_device_max_speed=maxStandardSampleRate;
-  *pa_device_min_speed=minStandardSampleRate;
-  *pa_device_max_bytes=maxBytes;
-  *pa_device_min_bytes=minBytes;
-  *pa_device_max_channels= maxInputChannels;
-  *pa_device_min_channels= minInputChannels;
-
-  return speed_warning;
-}
diff --git a/pimpl_h.hpp b/pimpl_h.hpp
new file mode 100644
index 0000000..b202761
--- /dev/null
+++ b/pimpl_h.hpp
@@ -0,0 +1,29 @@
+#ifndef PIMPL_H_HPP_
+#define PIMPL_H_HPP_
+
+#include <memory>
+
+//
+// opaque implementation type with perfect forwarding of constructor arguments
+//
+// see pimpl_impl.hpp for the out-of-line definitions of the members and lifetime management
+//
+// thanks to Herb Sutter (http://herbsutter.com/gotw/_101/) for the implementation
+//
+template<typename T>
+class pimpl
+{
+private:
+  std::unique_ptr<T> m_;
+
+public:
+  pimpl ();
+  template<typename ...Args> pimpl (Args&& ...);
+  ~pimpl ();
+  T * operator -> ();
+  T const * operator -> () const;
+  T& operator * ();
+  T const& operator * () const;
+};
+
+#endif
diff --git a/pimpl_impl.hpp b/pimpl_impl.hpp
new file mode 100644
index 0000000..3d01b7e
--- /dev/null
+++ b/pimpl_impl.hpp
@@ -0,0 +1,28 @@
+#ifndef PIMPL_IMPL_HPP_
+#define PIMPL_IMPL_HPP_
+
+#include <utility>
+
+template<typename T>
+pimpl<T>::pimpl () : m_ {new T {}} {}
+
+template<typename T>
+template<typename ...Args>
+pimpl<T>::pimpl (Args&& ...args) : m_ {new T {std::forward<Args> (args)...} } {}
+
+template<typename T>
+pimpl<T>::~pimpl () {}
+
+template<typename T>
+T * pimpl<T>::operator -> () {return m_.get ();}
+
+template<typename T>
+T const * pimpl<T>::operator -> () const {return m_.get ();}
+
+template<typename T>
+T& pimpl<T>::operator * () {return *m_.get ();}
+
+template<typename T>
+T const& pimpl<T>::operator * () const {return *m_.get ();}
+
+#endif
diff --git a/plotter.cpp b/plotter.cpp
index a43bdbf..d91929b 100644
--- a/plotter.cpp
+++ b/plotter.cpp
@@ -2,6 +2,8 @@
 #include <math.h>
 #include <QDebug>
 
+#include "moc_plotter.cpp"
+
 #define MAX_SCREENSIZE 2048
 
 
@@ -15,7 +17,7 @@ CPlotter::CPlotter(QWidget *parent) :                  //CPlotter Constructor
   setAttribute(Qt::WA_OpaquePaintEvent, false);
   setAttribute(Qt::WA_NoSystemBackground, true);
 
-  m_StartFreq = 0;
+  m_startFreq = 0;
   m_nSpan=2;                         //used for FFT bins/pixel
   m_fSpan=(float)m_nSpan;
   m_hdivs = HORZ_DIVS;
@@ -83,13 +85,12 @@ void CPlotter::paintEvent(QPaintEvent *)                    // paintEvent()
   m_paintEventBusy=false;
 }
 
-void CPlotter::draw(float swide[], int i0)             //draw()
+void CPlotter::draw(float swide[])             //draw()
 {
-  int j,y2;
+  int j,j0,y2;
   float y;
 
-  m_i0=i0;
-  double gain = pow(10.0,0.05*(m_plotGain+7));
+  double gain = pow(10.0,0.05*m_plotGain);
 
 //move current data down one line (must do this before attaching a QPainter object)
   m_WaterfallPixmap.scroll(0,1,0,0,m_w,m_h1);
@@ -97,35 +98,53 @@ void CPlotter::draw(float swide[], int i0)             //draw()
   m_2DPixmap = m_OverlayPixmap.copy(0,0,m_w,m_h2);
   QPainter painter2D(&m_2DPixmap);
 
-  painter2D.setPen(Qt::green);
+  if(m_bLinearAvg) {
+    painter2D.setPen(Qt::yellow);
+  } else {
+    painter2D.setPen(Qt::green);
+  }
 
   QPoint LineBuf[MAX_SCREENSIZE];
   j=0;
-
-//  int iz=XfromFreq(2000.0);
+  j0=int(m_startFreq/m_fftBinWidth + 0.5);
   int iz=XfromFreq(5000.0);
+  int jz=iz*m_binsPerPixel;
   m_fMax=FreqfromX(iz);
+
+  flat4_(swide,&iz,&m_Flatten);
+  flat4_(&jt9com_.savg[j0],&jz,&m_Flatten);
+
   for(int i=0; i<iz; i++) {
-    if(i>iz) swide[i]=0;
-    y=0.0;
-    if(swide[i]>0.0) y = 10.0*log10(swide[i]);
-    int y1 = 5.0*gain*y + 10*(m_plotZero-4);
+    y=swide[i];
+    int y1 = 10.0*gain*y + 10*m_plotZero +40;
     if (y1<0) y1=0;
     if (y1>254) y1=254;
     if (swide[i]>1.e29) y1=255;
     painter1.setPen(m_ColorTbl[y1]);
     painter1.drawPoint(i,0);
+
     y2=0;
-    if(m_bCurrent) y2 = 0.4*gain*y - 15;
+    if(m_bCurrent) y2 = gain*y - 15;
+
     if(m_bCumulative) {
       float sum=0.0;
-      int j=m_binsPerPixel*i;
+      int j=j0+m_binsPerPixel*i;
       for(int k=0; k<m_binsPerPixel; k++) {
         sum+=jt9com_.savg[j++];
       }
-      y2=gain*6.0*log10(sum/m_binsPerPixel) - 10.0;
+      y2=1.3*gain*sum/m_binsPerPixel + m_plotZero - 15;
+      if(m_Flatten==0) y2 += 40;
     }
-    y2 += m_plotZero;
+
+    if(m_bLinearAvg) {
+      float sum=0.0;
+      int j=j0+m_binsPerPixel*i;
+      for(int k=0; k<m_binsPerPixel; k++) {
+        sum+=jt9w_.syellow[j++];
+      }
+      y2=gain*sum/m_binsPerPixel * (m_h/50.0) - 20.0;
+    }
+
     if(i==iz-1) painter2D.drawPolyline(LineBuf,j);
     LineBuf[j].setX(i);
     LineBuf[j].setY(m_h-(y2+0.8*m_h));
@@ -167,36 +186,39 @@ void CPlotter::DrawOverlay()                                 //DrawOverlay()
 //  int nHzDiv[11]={0,50,100,200,200,200,500,500,500,500,500};
   float pixperdiv;
 
-  QRect rect;
-  QPainter painter(&m_OverlayPixmap);
-  painter.initFrom(this);
-  QLinearGradient gradient(0, 0, 0 ,m_h2);  //fill background with gradient
-  gradient.setColorAt(1, Qt::black);
-  gradient.setColorAt(0, Qt::darkBlue);
-  painter.setBrush(gradient);
-  painter.drawRect(0, 0, m_w, m_h2);
-  painter.setBrush(Qt::SolidPattern);
-
   double df = m_binsPerPixel*m_fftBinWidth;
-  pixperdiv = m_freqPerDiv/df;
-  y = m_h2 - m_h2/VERT_DIVS;
-  m_hdivs = w*df/m_freqPerDiv + 0.9999;
-  for( int i=1; i<m_hdivs; i++)                   //draw vertical grids
+  QRect rect;
   {
-    x = (int)( (float)i*pixperdiv );
-    if(x >= 0 and x<=m_w) {
-      painter.setPen(QPen(Qt::white, 1,Qt::DotLine));
-      painter.drawLine(x, 0, x , y);
-      painter.drawLine(x, m_h2-5, x , m_h2);
+    QPainter painter(&m_OverlayPixmap);
+    painter.initFrom(this);
+    QLinearGradient gradient(0, 0, 0 ,m_h2);  //fill background with gradient
+    gradient.setColorAt(1, Qt::black);
+    gradient.setColorAt(0, Qt::darkBlue);
+    painter.setBrush(gradient);
+    painter.drawRect(0, 0, m_w, m_h2);
+    painter.setBrush(Qt::SolidPattern);
+
+    pixperdiv = m_freqPerDiv/df;
+    y = m_h2 - m_h2/VERT_DIVS;
+    m_hdivs = w*df/m_freqPerDiv + 1.9999;
+    float xx0=float(m_startFreq)/float(m_freqPerDiv);
+    xx0=xx0-int(xx0);
+    int x0=xx0*pixperdiv+0.5;
+    for( int i=1; i<m_hdivs; i++) {                  //draw vertical grids
+      x = (int)((float)i*pixperdiv ) - x0;
+      if(x >= 0 and x<=m_w) {
+        painter.setPen(QPen(Qt::white, 1,Qt::DotLine));
+        painter.drawLine(x, 0, x , y);
+        painter.drawLine(x, m_h2-5, x , m_h2);
+      }
     }
-  }
 
-  pixperdiv = (float)m_h2 / (float)VERT_DIVS;
-  painter.setPen(QPen(Qt::white, 1,Qt::DotLine));
-  for( int i=1; i<VERT_DIVS; i++)                 //draw horizontal grids
-  {
-          y = (int)( (float)i*pixperdiv );
-          painter.drawLine(0, y, w, y);
+    pixperdiv = (float)m_h2 / (float)VERT_DIVS;
+    painter.setPen(QPen(Qt::white, 1,Qt::DotLine));
+    for( int i=1; i<VERT_DIVS; i++) {                //draw horizontal grids
+      y = (int)( (float)i*pixperdiv );
+      painter.drawLine(0, y, w, y);
+    }
   }
 
   QRect rect0;
@@ -222,11 +244,12 @@ void CPlotter::DrawOverlay()                                 //DrawOverlay()
   m_hdivs = w*df/m_freqPerDiv + 0.9999;
   m_ScalePixmap.fill(Qt::white);
   painter0.drawRect(0, 0, w, 30);
+  MakeFrequencyStrs();
 
 //draw tick marks on upper scale
   pixperdiv = m_freqPerDiv/df;
-  for( int i=1; i<m_hdivs; i++) {     //major ticks
-    x = (int)( (float)i*pixperdiv );
+  for( int i=0; i<m_hdivs; i++) {     //major ticks
+    x = (int)((m_xOffset+i)*pixperdiv );
     painter0.drawLine(x,18,x,30);
   }
   int minor=5;
@@ -237,28 +260,10 @@ void CPlotter::DrawOverlay()                                 //DrawOverlay()
   }
 
   //draw frequency values
-  MakeFrequencyStrs();
   for( int i=0; i<=m_hdivs; i++) {
-    if(0==i) {
-      //left justify the leftmost text
-      x = (int)( (float)i*pixperdiv);
-      rect0.setRect(x,0, (int)pixperdiv, 20);
-      painter0.drawText(rect0, Qt::AlignLeft|Qt::AlignVCenter,
-                       m_HDivText[i]);
-    }
-    else if(m_hdivs == i) {
-      //right justify the rightmost text
-      x = (int)( (float)i*pixperdiv - pixperdiv);
-      rect0.setRect(x,0, (int)pixperdiv, 20);
-      painter0.drawText(rect0, Qt::AlignRight|Qt::AlignVCenter,
-                       m_HDivText[i]);
-    } else {
-      //center justify the rest of the text
-      x = (int)( (float)i*pixperdiv - pixperdiv/2);
-      rect0.setRect(x,0, (int)pixperdiv, 20);
-      painter0.drawText(rect0, Qt::AlignHCenter|Qt::AlignVCenter,
-                       m_HDivText[i]);
-    }
+    x = (int)((m_xOffset+i)*pixperdiv - pixperdiv/2);
+    rect0.setRect(x,0, (int)pixperdiv, 20);
+    painter0.drawText(rect0, Qt::AlignHCenter|Qt::AlignVCenter,m_HDivText[i]);
   }
 
   float bw=9.0*12000.0/m_nsps;
@@ -304,18 +309,19 @@ void CPlotter::DrawOverlay()                                 //DrawOverlay()
 
 void CPlotter::MakeFrequencyStrs()                       //MakeFrequencyStrs
 {
-  float freq;
+  int f=(m_startFreq+m_freqPerDiv-1)/m_freqPerDiv;
+  f*=m_freqPerDiv;
+  m_xOffset=float(f-m_startFreq)/m_freqPerDiv;
   for(int i=0; i<=m_hdivs; i++) {
-    freq = m_StartFreq + i*m_freqPerDiv;
-    m_HDivText[i].setNum((int)freq);
-    //      StartFreq += m_freqPerDiv;
+    m_HDivText[i].setNum(f);
+    f+=m_freqPerDiv;
   }
 }
 
 int CPlotter::XfromFreq(float f)                               //XfromFreq()
 {
 //  float w = m_WaterfallPixmap.width();
-  int x = int(m_w * (f - m_StartFreq)/m_fSpan + 0.5);
+  int x = int(m_w * (f - m_startFreq)/m_fSpan + 0.5);
   if(x<0 ) return 0;
   if(x>m_w) return m_w;
   return x;
@@ -323,8 +329,7 @@ int CPlotter::XfromFreq(float f)                               //XfromFreq()
 
 float CPlotter::FreqfromX(int x)                               //FreqfromX()
 {
-//  return float(1000.0 + x*m_binsPerPixel*m_fftBinWidth);
-  return float(x*m_binsPerPixel*m_fftBinWidth);
+  return float(m_startFreq + x*m_binsPerPixel*m_fftBinWidth);
 }
 
 void CPlotter::SetRunningState(bool running)              //SetRunningState()
@@ -352,16 +357,16 @@ int CPlotter::getPlotGain()                               //getPlotGain()
   return m_plotGain;
 }
 
-void CPlotter::SetStartFreq(quint64 f)                    //SetStartFreq()
+void CPlotter::setStartFreq(int f)                    //SetStartFreq()
 {
-  m_StartFreq=f;
-//    resizeEvent(NULL);
-  DrawOverlay();
+  m_startFreq=f;
+  resizeEvent(NULL);
+  update();
 }
 
-qint64 CPlotter::startFreq()                              //startFreq()
+int CPlotter::startFreq()                              //startFreq()
 {
-  return m_StartFreq;
+  return m_startFreq;
 }
 
 int CPlotter::plotWidth(){return m_WaterfallPixmap.width();}
@@ -385,18 +390,9 @@ int CPlotter::binsPerPixel()                                // get nbpp
   return m_binsPerPixel;
 }
 
-void CPlotter::setRxFreq(int x, bool bf)                       //setRxFreq()
+void CPlotter::setRxFreq (int x)
 {
-  if(bf) {
-    m_rxFreq=x;         // x is freq in Hz
-    m_xClick=XfromFreq(m_rxFreq);
-  } else {
-    if(x<0) x=0;      // x is pixel number
-    if(x>m_Size.width()) x=m_Size.width();
-    m_rxFreq=int(FreqfromX(x)+0.5);
-    m_xClick=x;
-  }
-  emit setFreq1(m_rxFreq,m_txFreq);
+  m_rxFreq = x;         // x is freq in Hz
   DrawOverlay();
   update();
 }
@@ -406,18 +402,22 @@ int CPlotter::rxFreq() {return m_rxFreq;}                //get rxFreq
 void CPlotter::mousePressEvent(QMouseEvent *event)       //mousePressEvent
 {
   int x=event->x();
-  setRxFreq(x,false);                               // Wideband waterfall
+  if(x<0) x=0;
+  if(x>m_Size.width()) x=m_Size.width();
   bool ctrl = (event->modifiers() & Qt::ControlModifier);
+  int freq = int(FreqfromX(x)+0.5);
+  int tx_freq = m_txFreq;
+  if (ctrl or m_lockTxFreq) tx_freq = freq;
+
+  emit setFreq1 (freq, tx_freq);
+
   int n=1;
   if(ctrl) n+=100;
   emit freezeDecode1(n);
-  if(ctrl or m_lockTxFreq) setTxFreq(m_rxFreq);
 }
 
 void CPlotter::mouseDoubleClickEvent(QMouseEvent *event)  //mouse2click
 {
-//  int x=event->x();
-//  setRxFreq(x,false);
   bool ctrl = (event->modifiers() & Qt::ControlModifier);
   int n=2;
   if(ctrl) n+=100;
@@ -429,93 +429,6 @@ void CPlotter::setNSpan(int n)                                  //setNSpan()
   m_nSpan=n;
 }
 
-void CPlotter::setPalette(QString palette)                      //setPalette()
-{
-  if(palette=="Linrad") {
-    float twopi=6.2831853;
-    float r,g,b,phi,x;
-    for(int i=0; i<256; i++) {
-      r=0.0;
-      if(i>105 and i<=198) {
-        phi=(twopi/4.0) * (i-105.0)/(198.0-105.0);
-        r=sin(phi);
-      } else if(i>=198) {
-          r=1.0;
-      }
-
-      g=0.0;
-      if(i>35 and i<198) {
-        phi=(twopi/4.0) * (i-35.0)/(122.5-35.0);
-        g=0.625*sin(phi);
-      } else if(i>=198) {
-        x=(i-186.0);
-        g=-0.014 + 0.0144*x -0.00007*x*x +0.000002*x*x*x;
-        if(g>1.0) g=1.0;
-      }
-
-      b=0.0;
-      if(i<=117) {
-        phi=(twopi/2.0) * i/117.0;
-        b=0.4531*sin(phi);
-      } else if(i>186) {
-        x=(i-186.0);
-        b=-0.014 + 0.0144*x -0.00007*x*x +0.000002*x*x*x;
-        if(b>1.0) b=1.0;
-      }
-      m_ColorTbl[i].setRgb(int(255.0*r),int(255.0*g),int(255.0*b));
-    }
-    m_ColorTbl[255].setRgb(255,255,100);
-
-  }
-
-  if(palette=="CuteSDR") {
-      for( int i=0; i<256; i++) {
-      if( (i<43) )
-        m_ColorTbl[i].setRgb( 0,0, 255*(i)/43);
-      if( (i>=43) && (i<87) )
-        m_ColorTbl[i].setRgb( 0, 255*(i-43)/43, 255 );
-      if( (i>=87) && (i<120) )
-        m_ColorTbl[i].setRgb( 0,255, 255-(255*(i-87)/32));
-      if( (i>=120) && (i<154) )
-        m_ColorTbl[i].setRgb( (255*(i-120)/33), 255, 0);
-      if( (i>=154) && (i<217) )
-        m_ColorTbl[i].setRgb( 255, 255 - (255*(i-154)/62), 0);
-      if( (i>=217)  )
-        m_ColorTbl[i].setRgb( 255, 0, 128*(i-217)/38);
-    }
-    m_ColorTbl[255].setRgb(255,255,100);
-  }
-
-  if(palette=="Blue") {
-    FILE* fp=fopen("blue.dat","r");
-    int n,r,g,b;
-    float xr,xg,xb;
-    for(int i=0; i<256; i++) {
-      int nn=fscanf(fp,"%d%f%f%f",&n,&xr,&xg,&xb);
-      r=255.0*xr + 0.5;
-      g=255.0*xg + 0.5;
-      b=255.0*xb + 0.5;
-      m_ColorTbl[i].setRgb(r,g,b);
-      if(nn==-999999) i++;                  //Silence compiler warning
-    }
-  }
-
-  if(palette=="AFMHot") {
-    FILE* fp=fopen("afmhot.dat","r");
-    int n,r,g,b;
-    float xr,xg,xb;
-    for(int i=0; i<256; i++) {
-      int nn=fscanf(fp,"%d%f%f%f",&n,&xr,&xg,&xb);
-      r=255.0*xr + 0.5;
-      g=255.0*xg + 0.5;
-      b=255.0*xb + 0.5;
-      m_ColorTbl[i].setRgb(r,g,b);
-      if(nn==-999999) i++;                  //Silence compiler warning
-    }
-  }
-
-}
-
 double CPlotter::fGreen()
 {
   return m_fGreen;
@@ -537,7 +450,6 @@ void CPlotter::setNsps(int ntrperiod, int nsps)
 void CPlotter::setTxFreq(int n)                                 //setTol()
 {
   m_txFreq=n;
-  emit setFreq1(m_rxFreq,m_txFreq);
   DrawOverlay();
   update();
 }
@@ -563,3 +475,9 @@ void CPlotter::setDialFreq(double d)
   DrawOverlay();
   update();
 }
+
+void CPlotter::setFlatten(bool b)
+{
+  m_Flatten=0;
+  if(b) m_Flatten=1;
+}
diff --git a/plotter.h b/plotter.h
index b491cf9..cda3cc5 100644
--- a/plotter.h
+++ b/plotter.h
@@ -1,3 +1,4 @@
+// -*- Mode: C++ -*-
 ///////////////////////////////////////////////////////////////////////////
 // Some code in this file and accompanying files is based on work by
 // Moe Wheatley, AE4Y, released under the "Simplified BSD License".
@@ -14,6 +15,7 @@
 #endif
 #include <QFrame>
 #include <QImage>
+#include <QVector>
 #include <cstring>
 #include "commons.h"
 
@@ -22,46 +24,33 @@
 
 class CPlotter : public QFrame
 {
-  Q_OBJECT
+  Q_OBJECT;
+
 public:
   explicit CPlotter(QWidget *parent = 0);
   ~CPlotter();
 
   QSize minimumSizeHint() const;
   QSize sizeHint() const;
-  QColor  m_ColorTbl[256];
-
-  bool    m_bCurrent;
-  bool    m_bCumulative;
-  bool    m_lockTxFreq;
-
-  float   m_fSpan;
-
-  qint32  m_plotZero;
-  qint32  m_plotGain;
-  qint32  m_nSpan;
-  qint32  m_binsPerPixel;
-  qint32  m_w;
-
-  void draw(float sw[], int i0);		//Update the waterfall
+  void draw(float sw[]);		//Update the waterfall
   void SetRunningState(bool running);
   void setPlotZero(int plotZero);
   int  getPlotZero();
   void setPlotGain(int plotGain);
   int  getPlotGain();
-  void SetStartFreq(quint64 f);
-  qint64 startFreq();
+  void setStartFreq(int f);
+  int startFreq();
   int  plotWidth();
   void setNSpan(int n);
+  int nSpan() const {return m_nSpan;}
   void UpdateOverlay();
   void setDataFromDisk(bool b);
   void setRxRange(int fMin);
   void setBinsPerPixel(int n);
   int  binsPerPixel();
-  void setRxFreq(int n, bool bf);
+  void setRxFreq(int n);
   void DrawOverlay();
   int  rxFreq();
-  void setPalette(QString palette);
   void setFsample(int n);
   void setNsps(int ntrperiod, int nsps);
   void setTxFreq(int n);
@@ -71,6 +60,18 @@ public:
   void SetPercent2DScreen(int percent){m_Percent2DScreen=percent;}
   int getFmax();
   void setDialFreq(double d);
+  void setCurrent(bool b) {m_bCurrent = b;}
+  bool current() const {return m_bCurrent;}
+  void setCumulative(bool b) {m_bCumulative = b;}
+  bool cumulative() const {return m_bCumulative;}
+  void setLinearAvg(bool b) {m_bLinearAvg = b;}
+  bool linearAvg() const {return m_bLinearAvg;}
+  void setBreadth(qint32 w) {m_w = w;}
+  qint32 breadth() const {return m_w;}
+  float fSpan() const {return m_fSpan;}
+  void setLockTxFreq(bool b) {m_lockTxFreq = b;}
+  void setColours(QVector<QColor> const& cl) {m_ColorTbl = cl;}
+  void setFlatten(bool b);
 
 signals:
   void freezeDecode1(int n);
@@ -87,7 +88,22 @@ private:
   void UTCstr();
   int XfromFreq(float f);
   float FreqfromX(int x);
-  qint64 RoundFreq(qint64 freq, int resolution);
+
+  QVector<QColor> m_ColorTbl;
+
+  bool    m_bCurrent;
+  bool    m_bCumulative;
+  bool    m_bLinearAvg;
+  bool    m_lockTxFreq;
+
+  float   m_fSpan;
+
+  qint32  m_plotZero;
+  qint32  m_plotGain;
+  qint32  m_nSpan;
+  qint32  m_binsPerPixel;
+  qint32  m_w;
+  qint32  m_Flatten;
 
   QPixmap m_WaterfallPixmap;
   QPixmap m_2DPixmap;
@@ -107,15 +123,13 @@ private:
   double  m_fGreen;
   double  m_fftBinWidth;
   double  m_dialFreq;
-
-  qint64  m_StartFreq;
+  double  m_xOffset;
 
   qint32  m_dBStepSize;
   qint32  m_FreqUnits;
   qint32  m_hdivs;
   qint32  m_line;
   qint32  m_fSample;
-  qint32  m_i0;
   qint32  m_xClick;
   qint32  m_freqPerDiv;
   qint32  m_nsps;
@@ -128,6 +142,7 @@ private:
   qint32  m_txFreq;
   qint32  m_fMin;
   qint32  m_fMax;
+  qint32  m_startFreq;
 
   char    m_sutc[6];
 
@@ -136,4 +151,8 @@ private slots:
   void mouseDoubleClickEvent(QMouseEvent *event);
 };
 
+extern "C" {
+  void flat4_(float swide[], int* iz, int* nflatten);
+}
+
 #endif // PLOTTER_H
diff --git a/prefixes.txt b/prefixes.txt
new file mode 100644
index 0000000..2ab4bc7
--- /dev/null
+++ b/prefixes.txt
@@ -0,0 +1,27 @@
+Short-list of Add-On DXCC Prefixes:
+
+ 1A    1S    3A    3B6   3B8   3B9   3C    3C0   3D2   3D2C  3D2R  3DA   3V    3W    3X   
+ 3Y    3YB   3YP   4J    4L    4S    4U1I  4U1U  4W    4X    5A    5B    5H    5N    5R   
+ 5T    5U    5V    5W    5X    5Z    6W    6Y    7O    7P    7Q    7X    8P    8Q    8R   
+ 9A    9G    9H    9J    9K    9L    9M2   9M6   9N    9Q    9U    9V    9X    9Y    A2   
+ A3    A4    A5    A6    A7    A9    AP    BS7   BV    BV9   BY    C2    C3    C5    C6   
+ C9    CE    CE0X  CE0Y  CE0Z  CE9   CM    CN    CP    CT    CT3   CU    CX    CY0   CY9  
+ D2    D4    D6    DL    DU    E3    E4    EA    EA6   EA8   EA9   EI    EK    EL    EP   
+ ER    ES    ET    EU    EX    EY    EZ    F     FG    FH    FJ    FK    FKC   FM    FO   
+ FOA   FOC   FOM   FP    FR    FRG   FRJ   FRT   FT5W  FT5X  FT5Z  FW    FY    M     MD   
+ MI    MJ    MM    MU    MW    H4    H40   HA    HB    HB0   HC    HC8   HH    HI    HK   
+ HK0A  HK0M  HL    HM    HP    HR    HS    HV    HZ    I     IS    IS0   J2    J3    J5   
+ J6    J7    J8    JA    JDM   JDO   JT    JW    JX    JY    K     KG4   KH0   KH1   KH2  
+ KH3   KH4   KH5   KH5K  KH6   KH7   KH8   KH9   KL    KP1   KP2   KP4   KP5   LA    LU   
+ LX    LY    LZ    OA    OD    OE    OH    OH0   OJ0   OK    OM    ON    OX    OY    OZ   
+ P2    P4    PA    PJ2   PJ7   PY    PY0F  PT0S  PY0T  PZ    R1F   R1M   S0    S2    S5   
+ S7    S9    SM    SP    ST    SU    SV    SVA   SV5   SV9   T2    T30   T31   T32   T33  
+ T5    T7    T8    T9    TA    TF    TG    TI    TI9   TJ    TK    TL    TN    TR    TT   
+ TU    TY    TZ    UA    UA2   UA9   UK    UN    UR    V2    V3    V4    V5    V6    V7   
+ V8    VE    VK    VK0H  VK0M  VK9C  VK9L  VK9M  VK9N  VK9W  VK9X  VP2E  VP2M  VP2V  VP5  
+ VP6   VP6D  VP8   VP8G  VP8H  VP8O  VP8S  VP9   VQ9   VR    VU    VU4   VU7   XE    XF4  
+ XT    XU    XW    XX9   XZ    YA    YB    YI    YJ    YK    YL    YN    YO    YS    YU   
+ YV    YV0   Z2    Z3    ZA    ZB    ZC4   ZD7   ZD8   ZD9   ZF    ZK1N  ZK1S  ZK2   ZK3  
+ ZL    ZL7   ZL8   ZL9   ZP    ZS    ZS8   KC4   E5   
+
+Short-list of Add-on Suffixes:    /0 /1 /2 /3 /4 /5 /6 /7 /8 /9 /A /P
diff --git a/psk_reporter.cpp b/psk_reporter.cpp
index 6856d17..dd2b424 100644
--- a/psk_reporter.cpp
+++ b/psk_reporter.cpp
@@ -5,17 +5,27 @@
 
 #include "psk_reporter.h"
 
-PSK_Reporter::PSK_Reporter(QObject *parent) :
-    QObject(parent),
-    m_sequenceNumber(0)
+#include <QHostInfo>
+#include <QTimer>
+
+#include "MessageClient.hpp"
+
+#include "moc_psk_reporter.cpp"
+
+PSK_Reporter::PSK_Reporter(MessageClient * message_client, QObject *parent) :
+    QObject {parent},
+    m_messageClient {message_client},
+    reportTimer {new QTimer {this}},
+    m_sequenceNumber {0}
 {
     m_header_h = "000Allllttttttttssssssssiiiiiiii";
 
     // We use 50E2 and 50E3 for link Id
-    m_rxInfoDescriptor_h = "0003002450E200030000"
-                           "8002FFFF0000768F" // 2. Rx Call
-                           "8004FFFF0000768F" // 4. Rx Grid
-                           "8008FFFF0000768F" // 8. Rx Soft
+    m_rxInfoDescriptor_h = "0003002C50E200040000"
+                           "8002FFFF0000768F"     // 2. Rx Call
+                           "8004FFFF0000768F"     // 4. Rx Grid
+                           "8008FFFF0000768F"     // 8. Rx Soft
+                           "8009FFFF0000768F"     // 9. Rx Antenna
                            "0000";
 
     m_txInfoDescriptor_h = "0002003C50E30007"
@@ -31,18 +41,18 @@ PSK_Reporter::PSK_Reporter(QObject *parent) :
     qsrand(QDateTime::currentDateTime().toTime_t());
     m_randomId_h = QString("%1").arg(qrand(),8,16,QChar('0'));
 
-    m_udpSocket = new QUdpSocket(this);
+    QHostInfo::lookupHost("report.pskreporter.info", this, SLOT(dnsLookupResult(QHostInfo)));
 
-    reportTimer = new QTimer(this);
     connect(reportTimer, SIGNAL(timeout()), this, SLOT(sendReport()));
+    reportTimer->start(5*60*1000); // 5 minutes;
 }
 
-void PSK_Reporter::setLocalStation(QString call, QString gridSquare, QString programInfo)
+void PSK_Reporter::setLocalStation(QString call, QString gridSquare, QString antenna, QString programInfo)
 {
   m_rxCall = call;
   m_rxGrid = gridSquare;
+  m_rxAnt = antenna;
   m_progId = programInfo;
-  reportTimer->start(5*60*1000); // 5 minutes;
 }
 
 void PSK_Reporter::addRemoteStation(QString call, QString grid, QString freq, QString mode, QString snr, QString time )
@@ -59,8 +69,11 @@ void PSK_Reporter::addRemoteStation(QString call, QString grid, QString freq, QS
 
 void PSK_Reporter::sendReport()
 {
-    if (m_spotQueue.isEmpty())
+    if (m_spotQueue.isEmpty()) {
         return;
+    }
+
+    QString report_h;
 
     // Header
     QString header_h = m_header_h;
@@ -73,10 +86,11 @@ void PSK_Reporter::sendReport()
     rxInfoData_h += QString("%1").arg(m_rxCall.length(),2,16,QChar('0')) + m_rxCall.toUtf8().toHex();
     rxInfoData_h += QString("%1").arg(m_rxGrid.length(),2,16,QChar('0')) + m_rxGrid.toUtf8().toHex();
     rxInfoData_h += QString("%1").arg(m_progId.length(),2,16,QChar('0')) + m_progId.toUtf8().toHex();
+    rxInfoData_h += QString("%1").arg(m_rxAnt.length(),2,16,QChar('0')) + m_rxAnt.toUtf8().toHex();
     rxInfoData_h += "0000";
     rxInfoData_h.replace("50E2llll", "50E2" + QString("%1").arg(rxInfoData_h.length()/2,4,16,QChar('0')));
 
-    // Sender information        
+    // Sender information
     QString txInfoData_h = "50E3llll";
     while (!m_spotQueue.isEmpty()) {
         QHash<QString,QString> spot = m_spotQueue.dequeue();
@@ -90,15 +104,24 @@ void PSK_Reporter::sendReport()
     }
     txInfoData_h += "0000";
     txInfoData_h.replace("50E3llll", "50E3" + QString("%1").arg(txInfoData_h.length()/2,4,16,QChar('0')));
+    report_h = header_h + m_rxInfoDescriptor_h + m_txInfoDescriptor_h + rxInfoData_h + txInfoData_h;
+    //qDebug() << "Sending Report TX: ";
 
-    // Build report
-    QString report_h = header_h + m_rxInfoDescriptor_h + m_txInfoDescriptor_h + rxInfoData_h + txInfoData_h;
     report_h.replace("000Allll", "000A" + QString("%1").arg(report_h.length()/2,4,16,QChar('0')));
     QByteArray report = QByteArray::fromHex(report_h.toUtf8());
 
-    // Get IP address for pskreporter.info and send report via UDP
-    QHostInfo info = QHostInfo::fromName("report.pskreporter.info");
-    m_udpSocket->writeDatagram(report,info.addresses().at(0),4739);
+    // Send data to PSK Reporter site
+    if (!m_pskReporterAddress.isNull()) {
+        m_messageClient->send_raw_datagram (report, m_pskReporterAddress, 4739);
+    }
+}
+
+void PSK_Reporter::dnsLookupResult(QHostInfo info)
+{
+    if (!info.addresses().isEmpty()) {
+        m_pskReporterAddress = info.addresses().at(0);
+//        qDebug() << "PSK Reporter IP: " << m_pskReporterAddress;
+    }
 }
 
 
diff --git a/psk_reporter.h b/psk_reporter.h
index abadda1..16afcf4 100644
--- a/psk_reporter.h
+++ b/psk_reporter.h
@@ -1,16 +1,23 @@
+// -*- Mode: C++ -*-
 #ifndef PSK_REPORTER_H
 #define PSK_REPORTER_H
 
-#include <QtCore>
-#include <QUdpSocket>
-#include <QHostInfo>
+#include <QObject>
+#include <QString>
+#include <QHostAddress>
+#include <QQueue>
+#include <QHash>
+
+class MessageClient;
+class QTimer;
+class QHostInfo;
 
 class PSK_Reporter : public QObject
 {
     Q_OBJECT
 public:
-    explicit PSK_Reporter(QObject *parent = 0);
-    void setLocalStation(QString call, QString grid, QString programInfo);
+  explicit PSK_Reporter(MessageClient *, QObject *parent = nullptr);
+    void setLocalStation(QString call, QString grid, QString antenna, QString programInfo);
     void addRemoteStation(QString call, QString grid, QString freq, QString mode, QString snr, QString time);
     
 signals:
@@ -18,6 +25,9 @@ signals:
 public slots:
     void sendReport();
 
+private slots:
+    void dnsLookupResult(QHostInfo info);
+
 private:
     QString m_header_h;
     QString m_rxInfoDescriptor_h;
@@ -27,11 +37,14 @@ private:
 
     QString m_rxCall;
     QString m_rxGrid;
+    QString m_rxAnt;
     QString m_progId;
 
+    QHostAddress m_pskReporterAddress;
+
     QQueue< QHash<QString,QString> > m_spotQueue;
 
-    QUdpSocket *m_udpSocket;
+    MessageClient * m_messageClient;
 
     QTimer *reportTimer;
 
diff --git a/qmake_only/svnversion.h b/qmake_only/svnversion.h
new file mode 100644
index 0000000..3f14daf
--- /dev/null
+++ b/qmake_only/svnversion.h
@@ -0,0 +1,4 @@
+/* This is a dummy file required to make the qmake build compatible
+   with the CMake build. */
+
+#define WSJTX_STRINGIZE(X)
diff --git a/qss/default.qss b/qss/default.qss
new file mode 100644
index 0000000..f5571d5
--- /dev/null
+++ b/qss/default.qss
@@ -0,0 +1,5 @@
+/* default stylesheet for the message aggregator application */
+
+[transmitting="true"] {
+       background-color: yellow
+}
diff --git a/qt_helpers.cpp b/qt_helpers.cpp
new file mode 100644
index 0000000..62def12
--- /dev/null
+++ b/qt_helpers.cpp
@@ -0,0 +1,37 @@
+#include "qt_helpers.hpp"
+
+#include <QString>
+#include <QFont>
+#include <QWidget>
+#include <QStyle>
+#include <QVariant>
+
+QString font_as_stylesheet (QFont const& font)
+{
+  QString font_weight;
+  switch (font.weight ())
+    {
+    case QFont::Light: font_weight = "light"; break;
+    case QFont::Normal: font_weight = "normal"; break;
+    case QFont::DemiBold: font_weight = "demibold"; break;
+    case QFont::Bold: font_weight = "bold"; break;
+    case QFont::Black: font_weight = "black"; break;
+    }
+  return QString {
+      " font-family: %1;\n"
+      " font-size: %2pt;\n"
+      " font-style: %3;\n"
+      " font-weight: %4;\n"}
+  .arg (font.family ())
+     .arg (font.pointSize ())
+     .arg (font.styleName ())
+     .arg (font_weight);
+}
+
+void update_dynamic_property (QWidget * widget, char const * property, QVariant const& value)
+{
+  widget->setProperty (property, value);
+  widget->style ()->unpolish (widget);
+  widget->style ()->polish (widget);
+  widget->update ();
+}
diff --git a/qt_helpers.hpp b/qt_helpers.hpp
new file mode 100644
index 0000000..ec417dc
--- /dev/null
+++ b/qt_helpers.hpp
@@ -0,0 +1,82 @@
+#ifndef QT_HELPERS_HPP_
+#define QT_HELPERS_HPP_
+
+#include <stdexcept>
+#include <functional>
+
+#include <QDataStream>
+#include <QMetaObject>
+#include <QMetaType>
+#include <QMetaEnum>
+#include <QString>
+#include <QDebug>
+#include <QHostAddress>
+
+class QVariant;
+
+#define ENUM_QDATASTREAM_OPS_DECL(CLASS, ENUM)				\
+  QDataStream& operator << (QDataStream&, CLASS::ENUM);			\
+  QDataStream& operator >> (QDataStream&, CLASS::ENUM&);
+
+#define ENUM_QDATASTREAM_OPS_IMPL(CLASS, ENUM)				\
+  QDataStream& operator << (QDataStream& os, CLASS::ENUM v)		\
+  {									\
+    auto const& mo = CLASS::staticMetaObject;				\
+    return os << mo.enumerator (mo.indexOfEnumerator (#ENUM)).valueToKey (v); \
+  }									\
+									\
+  QDataStream& operator >> (QDataStream& is, CLASS::ENUM& v)		\
+  {									\
+    char * buffer;							\
+    is >> buffer;							\
+    bool ok {false};							\
+    auto const& mo = CLASS::staticMetaObject;				\
+    auto const& me = mo.enumerator (mo.indexOfEnumerator (#ENUM));	\
+    if (buffer)								\
+      {									\
+	v = static_cast<CLASS::ENUM> (me.keyToValue (buffer, &ok));	\
+	delete [] buffer;						\
+      }									\
+    if (!ok)								\
+      {									\
+	v = static_cast<CLASS::ENUM> (me.value (0));			\
+      }									\
+    return is;								\
+  }
+
+#define ENUM_QDEBUG_OPS_DECL(CLASS, ENUM)				\
+  QDebug operator << (QDebug, CLASS::ENUM);
+
+#define ENUM_QDEBUG_OPS_IMPL(CLASS, ENUM)				\
+  QDebug operator << (QDebug d, CLASS::ENUM m)				\
+  {									\
+    auto const& mo = CLASS::staticMetaObject;				\
+    return d << mo.enumerator (mo.indexOfEnumerator (#ENUM)).valueToKey (m); \
+  }
+
+#define ENUM_CONVERSION_OPS_DECL(CLASS, ENUM)	\
+  QString enum_to_qstring (CLASS::ENUM);
+
+#define ENUM_CONVERSION_OPS_IMPL(CLASS, ENUM)				\
+  QString enum_to_qstring (CLASS::ENUM m)				\
+  {									\
+    auto const& mo = CLASS::staticMetaObject;				\
+    return QString {mo.enumerator (mo.indexOfEnumerator (#ENUM)).valueToKey (m)}; \
+  }
+
+inline
+void throw_qstring (QString const& qs)
+{
+  throw std::runtime_error {qs.toLocal8Bit ().constData ()};
+}
+
+QString font_as_stylesheet (QFont const&);
+
+// do what is necessary to change a dynamic property and trigger any
+// conditional style sheet updates
+void update_dynamic_property (QWidget *, char const * property, QVariant const& value);
+
+// Register some useful Qt types with QMetaType
+Q_DECLARE_METATYPE (QHostAddress);
+
+#endif
diff --git a/revision_utils.cpp b/revision_utils.cpp
new file mode 100644
index 0000000..fe31beb
--- /dev/null
+++ b/revision_utils.cpp
@@ -0,0 +1,83 @@
+#include "revision_utils.hpp"
+
+#include <cstring>
+
+#include <QCoreApplication>
+#include <QRegularExpression>
+
+#include "svnversion.h"
+
+namespace
+{
+  QString revision_extract_number (QString const& s)
+  {
+    QString revision;
+
+    // try and match a number
+    QRegularExpression re {R"(^[$:]\w+: (\d+[^$]*)\$$)"};
+    auto match = re.match (s);
+    if (match.hasMatch ())
+      {
+        revision = 'r' + match.captured (1);
+      }
+    return revision;
+  }
+}
+
+QString revision (QString const& svn_rev_string)
+{
+  QString result;
+  auto revision_from_svn = revision_extract_number (svn_rev_string);
+
+#if defined (CMAKE_BUILD)
+  QString svn_info {":Rev: " WSJTX_STRINGIZE (SVNVERSION) " $"};
+
+  auto revision_from_svn_info = revision_extract_number (svn_info);
+  if (!revision_from_svn_info.isEmpty ())
+    {
+      // we managed to get the revision number from svn info etc.
+      result = revision_from_svn_info;
+    }
+  else if (!revision_from_svn.isEmpty ())
+    {
+      // fall back to revision passed in if any
+      result = revision_from_svn;
+    }
+  else
+    {
+      // match anything
+      QRegularExpression re {R"(^[$:]\w+: ([^$]*)\$$)"};
+      auto match = re.match (svn_info);
+      if (match.hasMatch ())
+        {
+          result = match.captured (1);
+        }
+    }
+#else
+  if (!revision_from_svn.isEmpty ())
+    {
+      // not CMake build so all we have is revision passed
+      result = revision_from_svn;
+    }
+#endif
+  return result.trimmed ();
+}
+
+QString version ()
+{
+#if defined (CMAKE_BUILD)
+  QString v {WSJTX_STRINGIZE (WSJTX_VERSION_MAJOR) "." WSJTX_STRINGIZE (WSJTX_VERSION_MINOR) "." WSJTX_STRINGIZE (WSJTX_VERSION_PATCH)};
+# if defined (WSJTX_RC)
+  v += "-rc" WSJTX_STRINGIZE (WSJTX_RC);
+# endif
+#else
+  QString v {"Not for Release"};
+#endif
+  return v;
+}
+
+QString program_title (QString const& revision)
+{
+  QString id {QCoreApplication::applicationName () + "   v" + QCoreApplication::applicationVersion ()};
+  return id + " " + revision + "  by K1JT";
+}
diff --git a/revision_utils.hpp b/revision_utils.hpp
new file mode 100644
index 0000000..838c36e
--- /dev/null
+++ b/revision_utils.hpp
@@ -0,0 +1,10 @@
+#ifndef REVISION_UTILS_HPP__
+#define REVISION_UTILS_HPP__
+
+#include <QString>
+
+QString revision (QString const& svn_rev_string = QString {});
+QString version ();
+QString program_title (QString const& revision = QString {});
+
+#endif
diff --git a/rigclass.cpp b/rigclass.cpp
deleted file mode 100644
index 3f61e03..0000000
--- a/rigclass.cpp
+++ /dev/null
@@ -1,324 +0,0 @@
-/**
- * \file src/rigclass.cc
- * \brief Ham Radio Control Libraries C++ interface
- * \author Stephane Fillod
- * \date 2001-2003
- *
- * Hamlib C++ interface is a frontend implementing wrapper functions.
- */
-
-/**
- *
- *  Hamlib C++ bindings - main file
- *  Copyright (c) 2001-2003 by Stephane Fillod
- *
- *
- *   This library is free software; you can redistribute it and/or
- *   modify it under the terms of the GNU Lesser General Public
- *   License as published by the Free Software Foundation; either
- *   version 2.1 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
- *   Lesser General Public License for more details.
- *
- *   You should have received a copy of the GNU Lesser General Public
- *   License along with this library; if not, write to the Free Software
- *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <hamlib/rig.h>
-#include "rigclass.h"
-#include <QDebug>
-#include <QHostAddress>
-
-static int hamlibpp_freq_event(RIG *rig, vfo_t vfo, freq_t freq, rig_ptr_t arg);
-
-static int hamlibpp_freq_event(RIG *rig, vfo_t vfo, freq_t freq, rig_ptr_t arg)
-{
-  if (!rig || !rig->state.obj)
-    return -RIG_EINVAL;
-
-/* assert rig == ((Rig*)rig->state.obj).theRig */
-  return ((Rig*)rig->state.obj)->FreqEvent(vfo, freq, arg);
-}
-
-Rig::Rig()
-{
-  rig_set_debug_level( RIG_DEBUG_WARN);
-}
-
-Rig::~Rig() {
-  theRig->state.obj = NULL;
-  rig_cleanup(theRig);
-  caps = NULL;
-}
-
-int Rig::init(rig_model_t rig_model)
-{
-    int initOk;
-
-    theRig = rig_init(rig_model);
-    if (!theRig)
-        initOk = false;
-    else
-        initOk = true;
-
-    caps = theRig->caps;
-    theRig->callbacks.freq_event = &hamlibpp_freq_event;
-    theRig->state.obj = (rig_ptr_t)this;
-
-    return initOk;
-}
-
-int Rig::open(int n) {
-  m_hrd=false;
-  m_cmndr=false;
-  if(n<9900) {
-    if(n==-99999) return -1;                      //Silence compiler warning
-    return rig_open(theRig);
-  }
-
-#ifdef WIN32	              // Ham radio Deluxe or Commander (Windows only)
-  if(n==9999) {
-    m_hrd=true;
-    bool bConnect=false;
-    bConnect = HRDInterfaceConnect(L"localhost",7809);
-    if(bConnect) {
-      const wchar_t* context=HRDInterfaceSendMessage(L"Get Context");
-      m_context="[" + QString::fromWCharArray (context,-1) + "] ";
-      HRDInterfaceFreeString(context);
-      return 0;
-    } else {
-      m_hrd=false;
-      return -1;
-    }
-  }
-  if(n==9998) {
-    if(socket->state()==QAbstractSocket::ConnectedState) {
-      socket->abort();
-    }
-
-    if(socket->state()==QAbstractSocket::UnconnectedState) {
-      socket->connectToHost(QHostAddress::LocalHost, 52002);
-      if(!socket->waitForConnected(1000)) {
-        return -1;
-      }
-    }
-    QString t;
-    t="<command:10>CmdGetFreq<parameters:0>";
-    QByteArray ba = t.toLocal8Bit();
-    const char* buf=ba.data();
-    socket->write(buf);
-    socket->waitForReadyRead(1000);
-    QByteArray reply=socket->read(128);
-    if(reply.indexOf("<CmdFreq:")==0) {
-      m_cmndr=true;
-      return 0;
-    }
-  }
-#endif
-  return -1;
-}
-
-int Rig::close(void) {
-#ifdef WIN32	// Ham Radio Deluxe only on Windows
-  if(m_hrd) {
-    HRDInterfaceDisconnect();
-    return 0;
-  } else if(m_cmndr) {
-    socket->close();
-    return 0;
-  } else
-#endif
-    {
-    return rig_close(theRig);
-  }
-}
-
-int Rig::setConf(const char *name, const char *val)
-{
-  return rig_set_conf(theRig, tokenLookup(name), val);
-}
-
-int Rig::setFreq(freq_t freq, vfo_t vfo) {
-#ifdef WIN32	// Ham Radio Deluxe (only on Windows)
-  if(m_hrd) {
-    QString t;
-    int nhz=(int)freq;
-    t=m_context + "Set Frequency-Hz " + QString::number(nhz);
-    const wchar_t* cmnd = (const wchar_t*) t.utf16();
-    const wchar_t* result=HRDInterfaceSendMessage(cmnd);
-    QString t2=QString::fromWCharArray (result,-1);
-    HRDInterfaceFreeString(result);
-    if(t2=="OK") {
-      return 0;
-    } else {
-      return -1;
-    }
-  } else if(m_cmndr) {
-    QString t;
-    double f=0.001*freq;
-    t.sprintf("<command:10>CmdSetFreq<parameters:23><xcvrfreq:10>%10.3f",f);
-    QByteArray ba = t.toLocal8Bit();
-    const char* buf=ba.data();
-    socket->write(buf);
-    socket->waitForBytesWritten(1000);
-    return 0;
-  } else
-#endif
-  {
-    return rig_set_freq(theRig, vfo, freq);
-  }
-}
-
-int Rig::setXit(shortfreq_t xit, vfo_t vfo)
-{
-  return rig_set_xit(theRig, vfo, xit);
-}
-
-int Rig::setVFO(vfo_t vfo)
-{
-  return rig_set_vfo(theRig, vfo);
-}
-
-vfo_t Rig::getVFO()
-{
-  vfo_t vfo;
-  rig_get_vfo(theRig, &vfo);
-  return vfo;
-}
-
-int Rig::setSplitFreq(freq_t tx_freq, vfo_t vfo) {
-#ifdef WIN32	// Ham Radio Deluxe only on Windows
-  if(m_hrd) {
-    QString t;
-    int nhz=(int)tx_freq;
-    t=m_context + "Set Frequency-Hz " + QString::number(nhz);
-    const wchar_t* cmnd = (const wchar_t*) t.utf16();
-    const wchar_t* result=HRDInterfaceSendMessage(cmnd);
-    QString t2=QString::fromWCharArray (result,-1);
-    HRDInterfaceFreeString(result);
-    if(t2=="OK") {
-      return 0;
-    } else {
-      return -1;
-    }
-  } else if(m_cmndr) {
-    QString t;
-    double f=0.001*tx_freq;
-    t.sprintf("<command:12>CmdSetTxFreq<parameters:23><xcvrfreq:10>%10.3f",f);
-    QByteArray ba = t.toLocal8Bit();
-    const char* buf=ba.data();
-    socket->write(buf);
-    socket->waitForBytesWritten(1000);
-    return 0;
-  } else
-#endif
-  {
-    return rig_set_split_freq(theRig, vfo, tx_freq);
-  }
-}
-
-freq_t Rig::getFreq(vfo_t vfo)
-{
-  freq_t freq;
-#ifdef WIN32	// Ham Radio Deluxe (only on Windows)
-  if(m_hrd) {
-    const wchar_t* cmnd = (const wchar_t*) (m_context+"Get Frequency").utf16();
-    const wchar_t* freqString=HRDInterfaceSendMessage(cmnd);
-    QString t2=QString::fromWCharArray (freqString,-1);
-    HRDInterfaceFreeString(freqString);
-    freq=t2.toDouble();
-    return freq;
-  } else if(m_cmndr) {
-    QString t;
-    t="<command:10>CmdGetFreq<parameters:0>";
-    QByteArray ba = t.toLocal8Bit();
-    const char* buf=ba.data();
-    socket->write(buf);
-    socket->waitForReadyRead(1000);
-    QByteArray reply=socket->read(128);
-    QString t2(reply);
-    if(t2.indexOf("<CmdFreq:")==0) {
-      int i1=t2.indexOf(">");
-      t2=t2.mid(i1+1).replace(",","");
-      freq=1000.0*t2.toDouble();
-      return freq;
-    } else {
-      return -1.0;
-    }
-  } else
-#endif
-  {
-    int iret=rig_get_freq(theRig, vfo, &freq);
-// iret should be 0.  Negative values mean rig_get_freq() failed.
-    if(iret<0) freq=-1.0;
-    return freq;
-  }
-}
-
-int Rig::setMode(rmode_t mode, pbwidth_t width, vfo_t vfo) {
-  return rig_set_mode(theRig, vfo, mode, width);
-}
-
-rmode_t Rig::getMode(pbwidth_t& width, vfo_t vfo) {
-  rmode_t mode;
-  rig_get_mode(theRig, vfo, &mode, &width);
-  return mode;
-}
-
-int Rig::setPTT(ptt_t ptt, vfo_t vfo)
-{
-#ifdef WIN32	// Ham Radio Deluxe only on Windows
-  if(m_hrd) {
-    wchar_t* cmnd;
-
-    if(ptt==0) {
-      cmnd = (wchar_t*) (m_context +
-                             "Set Button-Select TX 0").utf16();
-    } else {
-      cmnd = (wchar_t*) (m_context +
-                             "Set Button-Select TX 1").utf16();
-    }
-    const wchar_t* result=HRDInterfaceSendMessage(cmnd);
-    QString t2=QString::fromWCharArray (result,-1);
-    HRDInterfaceFreeString(result);
-    if(t2=="OK") {
-      return 0;
-    } else {
-      return -1;
-    }
-  } else if(m_cmndr) {
-    QString t;
-    if(ptt==0) t="<command:5>CmdRX<parameters:0>";
-    if(ptt>0) t="<command:5>CmdTX<parameters:0>";
-    QByteArray ba = t.toLocal8Bit();
-    const char* buf=ba.data();
-    socket->write(buf);
-    socket->waitForBytesWritten(1000);
-    return 0;
-  } else
-#endif
-    {
-    return rig_set_ptt(theRig, vfo, ptt);
-  }
-}
-
-ptt_t Rig::getPTT(vfo_t vfo)
-{
-  ptt_t ptt;
-  rig_get_ptt(theRig, vfo, &ptt);
-  return ptt;
-}
-
-token_t Rig::tokenLookup(const char *name)
-{
-  return rig_token_lookup(theRig, name);
-}
diff --git a/rigclass.h b/rigclass.h
deleted file mode 100644
index 9c933e7..0000000
--- a/rigclass.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- *  Hamlib C++ bindings - API header
- *  Copyright (c) 2001-2002 by Stephane Fillod
- *
- *
- *   This library is free software; you can redistribute it and/or
- *   modify it under the terms of the GNU Lesser General Public
- *   License as published by the Free Software Foundation; either
- *   version 2.1 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
- *   Lesser General Public License for more details.
- *
- *   You should have received a copy of the GNU Lesser General Public
- *   License along with this library; if not, write to the Free Software
- *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- *
- */
-
-#ifndef _RIGCLASS_H
-#define _RIGCLASS_H 1
-
-#include <hamlib/rig.h>
-#include <iostream>
-#include <QString>
-#include <QTcpSocket>
-
-extern QTcpSocket* socket;
-
-class BACKEND_IMPEXP Rig {
-private:
-  RIG* theRig;  // Global ref. to the rig
-  bool m_hrd;
-  bool m_cmndr;
-  QString m_context;
-
-
-protected:
-public:
-  Rig();
-  virtual ~Rig();
-
-  const struct rig_caps *caps;
-
-  // Initialize rig
-  int init(rig_model_t rig_model);
-
-  // This method open the communication port to the rig
-  int open(int n);
-
-  // This method close the communication port to the rig
-  int close(void);
-
-  int setConf(const char *name, const char *val);
-  token_t tokenLookup(const char *name);
-
-  int setFreq(freq_t freq, vfo_t vfo = RIG_VFO_CURR);
-  freq_t getFreq(vfo_t vfo = RIG_VFO_CURR);
-  int setMode(rmode_t, pbwidth_t width = RIG_PASSBAND_NORMAL, vfo_t vfo = RIG_VFO_CURR);
-  rmode_t getMode(pbwidth_t&, vfo_t vfo = RIG_VFO_CURR);
-  int setVFO(vfo_t);
-  vfo_t getVFO();
-  int setXit(shortfreq_t xit, vfo_t vfo);
-  int setSplitFreq(freq_t tx_freq, vfo_t vfo = RIG_VFO_CURR);
-  int setPTT (ptt_t ptt, vfo_t vfo = RIG_VFO_CURR);
-  ptt_t getPTT (vfo_t vfo = RIG_VFO_CURR);
-
-  // callbacks available in your derived object
-  virtual int FreqEvent(vfo_t, freq_t, rig_ptr_t) const {
-		  return RIG_OK;
-  }
-  virtual int ModeEvent(vfo_t, rmode_t, pbwidth_t, rig_ptr_t) const {
-		  return RIG_OK;
-  }
-  virtual int VFOEvent(vfo_t, rig_ptr_t) const {
-		  return RIG_OK;
-  }
-  virtual int PTTEvent(vfo_t, ptt_t, rig_ptr_t) const {
-		  return RIG_OK;
-  }
-  virtual int DCDEvent(vfo_t, dcd_t, rig_ptr_t) const {
-		  return RIG_OK;
-  }
-};
-
-#ifdef WIN32
-extern "C" {
-  bool HRDInterfaceConnect(const wchar_t *host, const ushort);
-  void HRDInterfaceDisconnect();
-  bool HRDInterfaceIsConnected();
-  wchar_t* HRDInterfaceSendMessage(const wchar_t *msg);
-  void HRDInterfaceFreeString(const wchar_t *lstring);
-}
-#endif
-
-#endif	// _RIGCLASS_H
diff --git a/samples/130418_1742.wav b/samples/130418_1742.wav
new file mode 100644
index 0000000..056cd2e
Binary files /dev/null and b/samples/130418_1742.wav differ
diff --git a/samples/130610_2343.wav b/samples/130610_2343.wav
new file mode 100644
index 0000000..1fbfaf2
Binary files /dev/null and b/samples/130610_2343.wav differ
diff --git a/shortcuts.txt b/shortcuts.txt
index 821ec70..8ea5474 100644
--- a/shortcuts.txt
+++ b/shortcuts.txt
@@ -1,26 +1,28 @@
-F1	Online User's Guide
-Ctrl+F1	About WSJT-X
-F2	Open configuration window
-F3	Display keyboard shortcuts
-F4	Clear Dx Call and Dx Grid entries
-Alt+F4	Exit program
-F5	Display special mouse commands
-F6	Open next in directory
-F11	Move Rx frequency down 1 Hz
-Ctrl+F11     	Move Rx and Tx frequencies down 1 Hz
-F12	Move Rx frequency up 1 Hz
-Ctrl+F12     	Move Rx and Tx frequencies up 1 Hz
-Shift+F6     	Decode remaining files in directory
-Alt+D	Decode again at QSO frequency
-Shift+D	Full-bandwidth decode (both windows)
-Alt+E	Erase()
-Ctrl+F	Edit the free text message box
-Alt+G	Generate standard messages
-Alt+H	Halt Tx()
-Ctrl+L	Lookup callsign in database, generate standard messages
-Alt M	Monitor()
-Alt+N	Enable Tx()
-Alt+Q	Log QSO()
-Alt+S	Stop()
-Alt+T	Tune
-Alt+V	Save the most recently completed *.wav file
+F1	Online User's Guide
+Ctrl+F1	About WSJT-X
+F2	Open configuration window
+F3	Display keyboard shortcuts
+F4	Clear DX Call, DX Grid, Tx messages 1-5
+Alt+F4	Exit program
+F5	Display special mouse commands
+F6	Open next file in directory
+Shift+F6        Decode all remaining files in directrory
+F11	Move Rx frequency down 1 Hz
+Ctrl+F11     	Move Rx and Tx frequencies down 1 Hz
+F12	Move Rx frequency up 1 Hz
+Ctrl+F12     	Move Rx and Tx frequencies up 1 Hz
+Alt+1-6	Set now transmission to this number on Tab 1
+Ctl+1-6	Set next transmission to this number on Tab 1
+Alt+D	Decode again at QSO frequency
+Shift+D	Full decode (both windows)
+Alt+E	Erase
+Ctrl+F	Edit the free text message box
+Alt+G	Generate standard messages
+Alt+H	Halt Tx
+Ctrl+L	Lookup callsign in database, generate standard messages
+Alt+M	Monitor
+Alt+N	Enable Tx
+Alt+Q	Log QSO
+Alt+S	Stop monitoring
+Alt+T	Tune
+Alt+V	Save the most recently completed *.wav file
diff --git a/signalmeter.cpp b/signalmeter.cpp
index 537b900..e21cb5a 100644
--- a/signalmeter.cpp
+++ b/signalmeter.cpp
@@ -5,6 +5,8 @@
 
 #include "signalmeter.h"
 
+#include "moc_signalmeter.cpp"
+
 SignalMeter::SignalMeter(QWidget *parent) :
     QWidget(parent)
 {
diff --git a/signalmeter.h b/signalmeter.h
index ea1aa62..30badc5 100644
--- a/signalmeter.h
+++ b/signalmeter.h
@@ -1,3 +1,4 @@
+// -*- Mode: C++ -*-
 #ifndef SIGNALMETER_H
 #define SIGNALMETER_H
 
@@ -21,9 +22,6 @@ private:
 
     QLabel *m_label;
 
-    int m_signal;
-    int m_sigPeak;
-
 protected:
     void paintEvent( QPaintEvent * );
     void resizeEvent(QResizeEvent *s);
diff --git a/sleep.h b/sleep.h
index c11188c..c170c9c 100644
--- a/sleep.h
+++ b/sleep.h
@@ -1,3 +1,4 @@
+// -*- Mode: C++ -*-
 #ifndef SLEEP_H
 #define SLEEP_H
 #include <qthread.h>
diff --git a/soundin.cpp b/soundin.cpp
index 332e5d3..a93fb49 100644
--- a/soundin.cpp
+++ b/soundin.cpp
@@ -1,208 +1,162 @@
 #include "soundin.h"
-#include <stdexcept>
-
-#define FRAMES_PER_BUFFER 1024
-//#define NSMAX 1365
-#define NSMAX 6827
-#define NTMAX 120
-
-extern "C" {
-#include <portaudio.h>
-extern struct {
-  float ss[184*NSMAX];              //This is "common/jt9com/..." in fortran
-  float savg[NSMAX];
-//  float c0[2*NTMAX*1500];
-  short int d2[NTMAX*12000];
-  int nutc;                         //UTC as integer, HHMM
-  int ndiskdat;                     //1 ==> data read from *.wav file
-  int ntrperiod;                    //TR period (seconds)
-  int mousefqso;                    //User-selected QSO freq (kHz)
-  int newdat;                       //1 ==> new data, must do long FFT
-  int npts8;                        //npts in c0() array
-  int nfa;                          //Low decode limit (Hz)
-  int nfb;                          //High decode limit (Hz)
-  int ntol;                         //+/- decoding range around fQSO (Hz)
-  int kin;
-  int nzhsym;
-  int nsave;
-  int nagain;
-  int ndepth;
-  int ntxmode;
-  int nmode;
-  char datetime[20];
-} jt9com_;
-}
 
-typedef struct
-{
-  int kin;          //Parameters sent to/from the portaudio callback function
-  int ncall;
-  bool bzero;
-  bool monitoring;
-} paUserData;
-
-//--------------------------------------------------------------- a2dCallback
-extern "C" int a2dCallback( const void *inputBuffer, void *outputBuffer,
-                         unsigned long framesToProcess,
-                         const PaStreamCallbackTimeInfo* timeInfo,
-                         PaStreamCallbackFlags statusFlags,
-                         void *userData )
-
-// This routine called by the PortAudio engine when samples are available.
-// It may be called at interrupt level, so don't do anything
-// that could mess up the system like calling malloc() or free().
+#include <QAudioDeviceInfo>
+#include <QAudioFormat>
+#include <QAudioInput>
+#include <QDebug>
 
+#include "moc_soundin.cpp"
+
+bool SoundInput::audioError () const
 {
-  paUserData *udata=(paUserData*)userData;
-  (void) outputBuffer;          //Prevent unused variable warnings.
-  (void) timeInfo;
-  (void) userData;
-  int nbytes,k;
-
-  udata->ncall++;
-  if( (statusFlags&paInputOverflow) != 0) {
-    qDebug() << "Input Overflow in a2dCallback";
-  }
-  if(udata->bzero) {           //Start of a new Rx sequence
-    udata->kin=0;              //Reset buffer pointer
-    udata->bzero=false;
-  }
-
-  nbytes=2*framesToProcess;        //Bytes per frame
-  k=udata->kin;
-  if(udata->monitoring) {
-    memcpy(&jt9com_.d2[k],inputBuffer,nbytes);      //Copy all samples to d2
-  }
-  udata->kin += framesToProcess;
-  jt9com_.kin=udata->kin;
-
-  return paContinue;
+  bool result (true);
+
+  Q_ASSERT_X (m_stream, "SoundInput", "programming error");
+  if (m_stream)
+    {
+      switch (m_stream->error ())
+        {
+        case QAudio::OpenError:
+          Q_EMIT error (tr ("An error opening the audio input device has occurred."));
+          break;
+
+        case QAudio::IOError:
+          Q_EMIT error (tr ("An error occurred during read from the audio input device."));
+          break;
+
+        case QAudio::UnderrunError:
+          Q_EMIT error (tr ("Audio data not being fed to the audio input device fast enough."));
+          break;
+
+        case QAudio::FatalError:
+          Q_EMIT error (tr ("Non-recoverable error, audio input device not usable at this time."));
+          break;
+
+        case QAudio::NoError:
+          result = false;
+          break;
+        }
+    }
+  return result;
 }
 
-void SoundInThread::run()                           //SoundInThread::run()
+void SoundInput::start(QAudioDeviceInfo const& device, int framesPerBuffer, AudioDevice * sink, unsigned downSampleFactor, AudioDevice::Channel channel)
 {
-  quitExecution = false;
-
-//---------------------------------------------------- Soundcard Setup
-  PaError paerr;
-  PaStreamParameters inParam;
-  PaStream *inStream;
-  paUserData udata;
-
-  udata.kin=0;                              //Buffer pointer
-  udata.ncall=0;                            //Number of callbacks
-  udata.bzero=false;                        //Flag to request reset of kin
-  udata.monitoring=m_monitoring;
-
-  inParam.device=m_nDevIn;                  //### Input Device Number ###
-  inParam.channelCount=1;                   //Number of analog channels
-  inParam.sampleFormat=paInt16;             //Get i*2 from Portaudio
-  inParam.suggestedLatency=0.05;
-  inParam.hostApiSpecificStreamInfo=NULL;
-
-  paerr=Pa_IsFormatSupported(&inParam,NULL,12000.0);
-  if(paerr<0) {
-    emit error("PortAudio says requested soundcard format not supported.");
-//    return;
-  }
-  qDebug() << "";
-  paerr=Pa_OpenStream(&inStream,            //Input stream
-        &inParam,                           //Input parameters
-        NULL,                               //No output parameters
-        12000.0,                            //Sample rate
-        FRAMES_PER_BUFFER,                  //Frames per buffer
-//        paClipOff+paDitherOff,            //No clipping or dithering
-        paClipOff,                          //No clipping
-        a2dCallback,                        //Input callback routine
-        &udata);                            //userdata
-
-  paerr=Pa_StartStream(inStream);
-  if(paerr<0) {
-    emit error("Failed to start audio input stream.");
-    return;
-  }
-
-  bool qe = quitExecution;
-  static int ntr0=99;
-  int k=0;
-  int nsec;
-  int ntr;
-  int nBusy=0;
-  int nstep0=0;
-  int nsps0=0;
-  qint64 ms0 = QDateTime::currentMSecsSinceEpoch();
-
-//---------------------------------------------- Soundcard input loop
-  while (!qe) {
-    qe = quitExecution;
-    if (qe) break;
-    udata.monitoring=m_monitoring;
-    qint64 ms = QDateTime::currentMSecsSinceEpoch();
-    m_SamFacIn=1.0;
-    if(udata.ncall>100) {
-      m_SamFacIn=udata.ncall*FRAMES_PER_BUFFER*1000.0/(12000.0*(ms-ms0-50));
+  Q_ASSERT (sink);
+
+  stop ();
+
+  m_sink = sink;
+
+  QAudioFormat format (device.preferredFormat());
+  format.setChannelCount (AudioDevice::Mono == channel ? 1 : 2);
+  format.setCodec ("audio/pcm");
+  format.setSampleRate (12000 * downSampleFactor);
+  format.setSampleType (QAudioFormat::SignedInt);
+  format.setSampleSize (16);
+
+  if (!format.isValid ())
+    {
+      Q_EMIT error (tr ("Requested input audio format is not valid."));
+      return;
     }
-    ms=ms % 86400000;
-    nsec = ms/1000;             // Time according to this computer
-    ntr = nsec % m_TRperiod;
-
-// Reset buffer pointer and symbol number at start of minute
-    if(ntr < ntr0 or !m_monitoring or m_nsps!=nsps0) {
-      nstep0=0;
-      nsps0=m_nsps;
-      udata.bzero=true;
+
+  // this function lies!
+  // if (!device.isFormatSupported (format))
+  //   {
+  //     Q_EMIT error (tr ("Requested input audio format is not supported on device."));
+  //     return;
+  //   }
+
+  m_stream.reset (new QAudioInput {device, format});
+  if (audioError ())
+    {
+      return;
     }
-    k=udata.kin;
-    if(m_monitoring) {
-      int kstep=m_nsps/2;
-//      m_step=k/kstep;
-      m_step=(k-1)/kstep;
-      if(m_step != nstep0) {
-        if(m_dataSinkBusy) {
-          nBusy++;
-        } else {
-//          m_dataSinkBusy=true;
-//          emit readyForFFT(k);         //Signal to compute new FFTs
-          emit readyForFFT(k-1);         //Signal to compute new FFTs
-        }
-        nstep0=m_step;
-      }
+
+  connect (m_stream.data(), &QAudioInput::stateChanged, this, &SoundInput::handleStateChanged);
+
+  m_stream->setBufferSize (m_stream->format ().bytesForFrames (framesPerBuffer));
+  if (sink->initialize (QIODevice::WriteOnly, channel))
+    {
+      m_stream->start (sink);
+      audioError ();
+    }
+  else
+    {
+      Q_EMIT error (tr ("Failed to initialize audio sink device"));
     }
-    msleep(100);
-    ntr0=ntr;
-  }
-  Pa_StopStream(inStream);
-  Pa_CloseStream(inStream);
 }
 
-void SoundInThread::setInputDevice(int n)                  //setInputDevice()
+void SoundInput::suspend ()
 {
-  if (isRunning()) return;
-  this->m_nDevIn=n;
+  if (m_stream)
+    {
+      m_stream->suspend ();
+      audioError ();
+    }
 }
 
-void SoundInThread::quit()                                       //quit()
+void SoundInput::resume ()
 {
-  quitExecution = true;
-}
+  if (m_sink)
+    {
+      m_sink->reset ();
+    }
 
-void SoundInThread::setMonitoring(bool b)                    //setMonitoring()
-{
-  m_monitoring = b;
+  if (m_stream)
+    {
+      m_stream->resume ();
+      audioError ();
+    }
 }
 
-void SoundInThread::setPeriod(int ntrperiod, int nsps)
+void SoundInput::handleStateChanged (QAudio::State newState) const
 {
-  m_TRperiod=ntrperiod;
-  m_nsps=nsps;
+  // qDebug () << "SoundInput::handleStateChanged: newState:" << newState;
+
+  switch (newState)
+    {
+    case QAudio::IdleState:
+      Q_EMIT status (tr ("Idle"));
+      break;
+
+    case QAudio::ActiveState:
+      Q_EMIT status (tr ("Receiving"));
+      break;
+
+    case QAudio::SuspendedState:
+      Q_EMIT status (tr ("Suspended"));
+      break;
+
+    case QAudio::StoppedState:
+      if (audioError ())
+        {
+          Q_EMIT status (tr ("Error"));
+        }
+      else
+        {
+          Q_EMIT status (tr ("Stopped"));
+        }
+      break;
+    }
 }
 
-int SoundInThread::mstep()
+void SoundInput::stop()
 {
-  return m_step;
+  if (m_stream)
+    {
+      m_stream->stop ();
+    }
+  m_stream.reset ();
+
+  if (m_sink)
+    {
+      m_sink->close ();
+    }
 }
 
-double SoundInThread::samFacIn()
+SoundInput::~SoundInput ()
 {
-  return m_SamFacIn;
+  stop ();
 }
diff --git a/soundin.h b/soundin.h
index 955f08d..c575c35 100644
--- a/soundin.h
+++ b/soundin.h
@@ -1,50 +1,50 @@
-#ifndef SOUNDIN_H
-#define SOUNDIN_H
+// -*- Mode: C++ -*-
+#ifndef SOUNDIN_H__
+#define SOUNDIN_H__
 
-#include <QtCore>
-#include <QDebug>
+#include <QObject>
+#include <QString>
+#include <QScopedPointer>
+#include <QAudioInput>
 
+#include "AudioDevice.hpp"
 
-// Thread gets audio data from soundcard and signals when a buffer of
-// specified size is available.
-class SoundInThread : public QThread
-{
-  Q_OBJECT
-  bool quitExecution;           // if true, thread exits gracefully
+class QAudioDeviceInfo;
+class QAudioInput;
 
-protected:
-  virtual void run();
+// Gets audio data from sound sample source and passes it to a sink device
+class SoundInput
+  : public QObject
+{
+  Q_OBJECT;
 
 public:
-  bool m_dataSinkBusy;
-
-  SoundInThread():
-    quitExecution(false),
-    m_dataSinkBusy(false)
+  SoundInput (QObject * parent = nullptr)
+    : QObject {parent}
+    , m_sink {nullptr}
   {
   }
 
-  void setInputDevice(qint32 n);
-  void setMonitoring(bool b);
-  void setPeriod(int ntrperiod, int nsps);
-  int  mstep();
-  double samFacIn();
+  ~SoundInput ();
 
-signals:
-  void readyForFFT(int k);
-  void error(const QString& message);
-  void status(const QString& message);
+  // sink must exist from the start call until the next start call or
+  // stop call
+  Q_SLOT void start(QAudioDeviceInfo const&, int framesPerBuffer, AudioDevice * sink, unsigned downSampleFactor, AudioDevice::Channel = AudioDevice::Mono);
+  Q_SLOT void suspend ();
+  Q_SLOT void resume ();
+  Q_SLOT void stop ();
 
-public slots:
-  void quit();
+  Q_SIGNAL void error (QString message) const;
+  Q_SIGNAL void status (QString message) const;
 
 private:
-  double m_SamFacIn;                    //(Input sample rate)/12000.0
-  qint32 m_step;
-  qint32 m_nDevIn;
-  qint32 m_TRperiod;
-  qint32 m_TRperiod0;
-  qint32 m_nsps;
-  bool   m_monitoring;
+  // used internally
+  Q_SLOT void handleStateChanged (QAudio::State) const;
+
+  bool audioError () const;
+
+  QScopedPointer<QAudioInput> m_stream;
+  AudioDevice * m_sink;
 };
-#endif // SOUNDIN_H
+
+#endif
diff --git a/soundout.cpp b/soundout.cpp
index 8693237..9e5843e 100644
--- a/soundout.cpp
+++ b/soundout.cpp
@@ -1,270 +1,195 @@
 #include "soundout.h"
 
-//#define FRAMES_PER_BUFFER 1024
-
-extern "C" {
-#include <portaudio.h>
-}
-
-extern float gran();                  //Noise generator (for tests only)
-extern int itone[126];                //Audio tones for all Tx symbols
-extern int icw[250];                  //Dits for CW ID
-extern int outBufSize;
-extern bool btxok;
-extern bool btxMute;
-extern double outputLatency;
-
-typedef struct   //Parameters sent to or received from callback function
-{
-  double txsnrdb;
-  double dnsps;
-  int    ntrperiod;
-  int    ntxfreq;
-  int    xit;
-  int    ncall;
-  int    nsym;
-  bool   txMute;
-  bool   bRestart;
-  bool   btune;
-} paUserData;
+#include <QDateTime>
+#include <QAudioDeviceInfo>
+#include <QAudioOutput>
+#include <qmath.h>
+#include <QDebug>
+
+#include "moc_soundout.cpp"
+
+#if defined (WIN32)
+# define MS_BUFFERED 1000u
+#else
+# define MS_BUFFERED 2000u
+#endif
 
-//--------------------------------------------------------------- d2aCallback
-extern "C" int d2aCallback(const void *inputBuffer, void *outputBuffer,
-                           unsigned long framesToProcess,
-                           const PaStreamCallbackTimeInfo* timeInfo,
-                           PaStreamCallbackFlags statusFlags,
-                           void *userData )
+bool SoundOutput::audioError () const
 {
-  paUserData *udata=(paUserData*)userData;
-  short *wptr = (short*)outputBuffer;
-
-  static double twopi=2.0*3.141592653589793238462;
-  static double baud;
-  static double phi=0.0;
-  static double dphi;
-  static double freq;
-  static double snr;
-  static double fac;
-  static double amp;
-  static int ic=0,j=0;
-  static int isym0=-999;
-  static short int i2;
-  int isym,nspd;
-
-  udata->ncall++;
-  if(udata->bRestart) {
- // Time according to this computer
-    qint64 ms = QDateTime::currentMSecsSinceEpoch() % 86400000;
-    int mstr = ms % (1000*udata->ntrperiod );
-    if(mstr<1000) return paContinue;
-    ic=(mstr-1000)*48;
-    udata->bRestart=false;
-    srand(mstr);                                //Initialize random seed
-  }
-  isym=ic/(4.0*udata->dnsps);                   //Actual fsample=48000
-  if(udata->btune) isym=0;                      //If tuning, send pure tone
-  if(udata->txsnrdb < 0.0) {
-    snr=pow(10.0,0.05*(udata->txsnrdb-6.0));
-    fac=3000.0;
-    if(snr>1.0) fac=3000.0/snr;
-  }
-
-  if(isym>=udata->nsym and icw[0]>0) {              //Output the CW ID
-    freq=udata->ntxfreq - udata->xit;
-    dphi=twopi*freq/48000.0;
-
-//    float wpm=20.0;
-//    int nspd=1.2*48000.0/wpm;
-//    nspd=3072;                           //18.75 WPM
-    nspd=2048 + 512;                       //22.5 WPM
-    int ic0=udata->nsym*4*udata->dnsps;
-    for(uint i=0 ; i<framesToProcess; i++ )  {
-      phi += dphi;
-      if(phi>twopi) phi -= twopi;
-      i2=32767.0*sin(phi);
-      j=(ic-ic0)/nspd + 1;
-      if(icw[j]==0) i2=0;
-      if(udata->txsnrdb < 0.0) {
-        int i4=fac*(gran() + i2*snr/32768.0);
-        if(i4>32767) i4=32767;
-        if(i4<-32767) i4=-32767;
-        i2=i4;
+  bool result (true);
+
+  Q_ASSERT_X (m_stream, "SoundOutput", "programming error");
+  if (m_stream) {
+    switch (m_stream->error ())
+      {
+      case QAudio::OpenError:
+        Q_EMIT error (tr ("An error opening the audio output device has occurred."));
+        break;
+
+      case QAudio::IOError:
+        Q_EMIT error (tr ("An error occurred during write to the audio output device."));
+        break;
+
+      case QAudio::UnderrunError:
+        Q_EMIT error (tr ("Audio data not being fed to the audio output device fast enough."));
+        break;
+
+      case QAudio::FatalError:
+        Q_EMIT error (tr ("Non-recoverable error, audio output device not usable at this time."));
+        break;
+
+      case QAudio::NoError:
+        result = false;
+        break;
       }
-      if(!btxok or btxMute)  i2=0;
-      *wptr++ = i2;                   //left
-#ifdef UNIX
-      *wptr++ = i2;                   //right
-#endif
-      ic++;
-    }
-    if(j>icw[0]) return paComplete;
-    if(statusFlags==999999 and timeInfo==NULL and
-       inputBuffer==NULL) return paContinue;   //Silence compiler warning:
-    return paContinue;
-  }
-
-  baud=12000.0/udata->dnsps;
-  amp=32767.0;
-  int i0=(udata->nsym-0.017)*4.0*udata->dnsps;
-  int i1=udata->nsym*4.0*udata->dnsps;
-  if(udata->btune) {                           //If tuning, no ramp down
-    i0=999*udata->dnsps;
-    i1=i0;
-  }
-  for(uint i=0 ; i<framesToProcess; i++ )  {
-    isym=ic/(4.0*udata->dnsps);                   //Actual fsample=48000
-    if(udata->btune) isym=0;                      //If tuning, send pure tone
-    if(isym!=isym0) {
-      freq=udata->ntxfreq + itone[isym]*baud - udata->xit;
-      dphi=twopi*freq/48000.0;
-      isym0=isym;
-    }
-    phi += dphi;
-    if(phi>twopi) phi -= twopi;
-    if(ic>i0) amp=0.98*amp;
-    if(ic>i1) amp=0.0;
-    i2=amp*sin(phi);
-    if(udata->txsnrdb < 0.0) {
-      int i4=fac*(gran() + i2*snr/32768.0);
-      if(i4>32767) i4=32767;
-      if(i4<-32767) i4=-32767;
-      i2=i4;
-    }
-    if(!btxok or btxMute)  i2=0;
-    *wptr++ = i2;                   //left
-#ifdef UNIX
-    *wptr++ = i2;                   //right
-#endif
-    ic++;
   }
-  if(amp==0.0) {
-    if(icw[0]==0) return paComplete;
-    phi=0.0;
-  }
-  return paContinue;
+  return result;
 }
 
-void SoundOutThread::run()
+void SoundOutput::setFormat (QAudioDeviceInfo const& device, unsigned channels, unsigned msBuffered)
 {
-  PaError paerr;
-  PaStreamParameters outParam;
-  PaStream *outStream;
-  paUserData udata;
-  quitExecution = false;
+  Q_ASSERT (0 < channels && channels < 3);
 
-  outParam.device=m_nDevOut;                 //Output device number
-  outParam.channelCount=1;                   //Number of analog channels
-#ifdef UNIX
-  outParam.channelCount=2;                   //Number of analog channels
-#endif
-  outParam.sampleFormat=paInt16;             //Send short ints to PortAudio
-  outParam.suggestedLatency=0.05;
-  outParam.hostApiSpecificStreamInfo=NULL;
+  m_msBuffered = msBuffered;
 
-  paerr=Pa_IsFormatSupported(NULL,&outParam,48000.0);
-  if(paerr<0) {
-    qDebug() << "PortAudio says requested output format not supported.";
-    qDebug() << paerr << m_nDevOut;
-    return;
-  }
+  QAudioFormat format (device.preferredFormat ());
 
-  udata.txsnrdb=99.0;
-  udata.dnsps=m_nsps;
-  udata.nsym=85;
-  if(m_modeTx=="JT65") {
-    udata.dnsps=4096.0*12000.0/11025.0;
-    udata.nsym=126;
-  }
-  udata.ntrperiod=m_TRperiod;
-  udata.ntxfreq=m_txFreq;
-  udata.xit=m_xit;
-  udata.ncall=0;
-  udata.txMute=m_txMute;
-  udata.bRestart=true;
-  udata.btune=m_tune;
+  format.setChannelCount (channels);
+  format.setCodec ("audio/pcm");
+  format.setSampleRate (48000);
+  format.setSampleType (QAudioFormat::SignedInt);
+  format.setSampleSize (16);
+  if (!format.isValid ())
+    {
+      Q_EMIT error (tr ("Requested output audio format is not valid."));
+    }
+  if (!device.isFormatSupported (format))
+    {
+      Q_EMIT error (tr ("Requested output audio format is not supported on device."));
+    }
 
-  paerr=Pa_OpenStream(&outStream,           //Output stream
-        NULL,                               //No input parameters
-        &outParam,                          //Output parameters
-        48000.0,                            //Sample rate
-        outBufSize,                         //Frames per buffer
-        paClipOff,                          //No clipping
-        d2aCallback,                        //output callbeck routine
-        &udata);                            //userdata
+  m_stream.reset (new QAudioOutput (device, format));
+  audioError ();
+  m_stream->setVolume (m_volume);
+  m_stream->setNotifyInterval(100);
 
-  paerr=Pa_StartStream(outStream);
-  if(paerr<0) {
-    qDebug() << "Failed to start audio output stream.";
-    return;
-  }
-  const PaStreamInfo* p=Pa_GetStreamInfo(outStream);
-  outputLatency = p->outputLatency;
-  bool qe = quitExecution;
-  qint64 ms0 = QDateTime::currentMSecsSinceEpoch();
+  connect (m_stream.data(), &QAudioOutput::stateChanged, this, &SoundOutput::handleStateChanged);
 
-//---------------------------------------------- Soundcard output loop
-  while (!qe) {
-    qe = quitExecution;
-    if (qe) break;
+  //      qDebug() << "A" << m_volume << m_stream->notifyInterval();
+}
 
-    udata.txsnrdb=m_txsnrdb;
-    udata.dnsps=m_nsps;
-    udata.nsym=85;
-    if(m_modeTx=="JT65") {
-      udata.dnsps=4096.0*12000.0/11025.0;
-      udata.nsym=126;
-    }
-    udata.ntrperiod=m_TRperiod;
-    udata.ntxfreq=m_txFreq;
-    udata.xit=m_xit;
-    udata.txMute=m_txMute;
-    udata.btune=m_tune;
+void SoundOutput::restart (QIODevice * source)
+{
+  Q_ASSERT (m_stream);
+
+  //
+  // This buffer size is critical since for proper sound streaming. If
+  // it is too short; high activity levels on the machine can starve
+  // the audio buffer. On the other hand the Windows implementation
+  // seems to take the length of the buffer in time to stop the audio
+  // stream even if reset() is used.
+  //
+  // 2 seconds seems a reasonable compromise except for Windows
+  // where things are probably broken.
+  //
+  // we have to set this before every start on the stream because the
+  // Windows implementation seems to forget the buffer size after a
+  // stop.
+  m_stream->setBufferSize (m_stream->format().bytesForDuration((m_msBuffered ? m_msBuffered : MS_BUFFERED) * 1000));
+  //  qDebug() << "B" << m_stream->bufferSize() <<
+  //  m_stream->periodSize() << m_stream->notifyInterval();
+
+  m_stream->start (source);
+}
 
-    m_SamFacOut=1.0;
-    if(udata.ncall>400) {
-      qint64 ms = QDateTime::currentMSecsSinceEpoch();
-      m_SamFacOut=udata.ncall*outBufSize*1000.0/(48000.0*(ms-ms0-50));
+void SoundOutput::suspend ()
+{
+  if (m_stream && QAudio::ActiveState == m_stream->state ())
+    {
+      m_stream->suspend ();
+      audioError ();
     }
-    msleep(100);
-  }
-  Pa_StopStream(outStream);
-  Pa_CloseStream(outStream);
 }
 
-void SoundOutThread::setOutputDevice(int n)      //setOutputDevice()
+void SoundOutput::resume ()
 {
-  if (isRunning()) return;
-  this->m_nDevOut=n;
+  if (m_stream && QAudio::SuspendedState == m_stream->state ())
+    {
+      m_stream->resume ();
+      audioError ();
+    }
 }
 
-void SoundOutThread::setPeriod(int ntrperiod, int nsps)
+void SoundOutput::reset ()
 {
-  m_TRperiod=ntrperiod;
-  m_nsps=nsps;
+  if (m_stream)
+    {
+      m_stream->reset ();
+      audioError ();
+    }
 }
 
-void SoundOutThread::setTxFreq(int n)
+void SoundOutput::stop ()
 {
-  m_txFreq=n;
+  if (m_stream)
+    {
+      m_stream->stop ();
+      audioError ();
+    }
 }
 
-void SoundOutThread::setXIT(int n)
+qreal SoundOutput::attenuation () const
 {
-  m_xit=n;
-
+  return -(10. * qLn (m_volume) / qLn (10.));
 }
 
-void SoundOutThread::setTxSNR(double snr)
+void SoundOutput::setAttenuation (qreal a)
 {
-  m_txsnrdb=snr;
+  Q_ASSERT (0. <= a && a <= 999.);
+  m_volume = qPow (10., -a / 10.);
+  //  qDebug () << "SoundOut: attn = " << a << ", vol = " << m_volume;
+  if (m_stream)
+    {
+      m_stream->setVolume (m_volume);
+    }
 }
 
-void SoundOutThread::setTune(bool b)
+void SoundOutput::resetAttenuation ()
 {
-  m_tune=b;
+  m_volume = 1.;
+  if (m_stream)
+    {
+      m_stream->setVolume (m_volume);
+    }
 }
 
-double SoundOutThread::samFacOut()
+void SoundOutput::handleStateChanged (QAudio::State newState)
 {
-  return m_SamFacOut;
+  // qDebug () << "SoundOutput::handleStateChanged: newState:" << newState;
+
+  switch (newState)
+    {
+    case QAudio::IdleState:
+      Q_EMIT status (tr ("Idle"));
+      break;
+
+    case QAudio::ActiveState:
+      Q_EMIT status (tr ("Sending"));
+      break;
+
+    case QAudio::SuspendedState:
+      Q_EMIT status (tr ("Suspended"));
+      break;
+
+    case QAudio::StoppedState:
+      if (audioError ())
+        {
+          Q_EMIT status (tr ("Error"));
+        }
+      else
+        {
+          Q_EMIT status (tr ("Stopped"));
+        }
+      break;
+    }
 }
diff --git a/soundout.h b/soundout.h
index a289afc..1e4b3a9 100644
--- a/soundout.h
+++ b/soundout.h
@@ -1,53 +1,54 @@
-#ifndef SOUNDOUT_H
-#define SOUNDOUT_H
-#include <QtCore>
-#include <QDebug>
+// -*- Mode: C++ -*-
+#ifndef SOUNDOUT_H__
+#define SOUNDOUT_H__
 
-// An instance of this thread sends audio data to a specified soundcard.
-// Output can be muted while underway, preserving waveform timing when
-// transmission is resumed.
+#include <QObject>
+#include <QString>
+#include <QAudioOutput>
+#include <QAudioDeviceInfo>
 
-class SoundOutThread : public QThread
-{
-  Q_OBJECT
+class QAudioDeviceInfo;
 
-protected:
-  virtual void run();
+// An instance of this sends audio data to a specified soundcard.
 
+class SoundOutput
+  : public QObject
+{
+  Q_OBJECT;
+  
 public:
-// Constructs (but does not start) a SoundOutThread
-  SoundOutThread()
-    :   quitExecution(false)           // Initialize some private members
-    ,   m_txOK(false)
-    ,   m_txMute(false)
+  SoundOutput ()
+    : m_msBuffered {0u}
+    , m_volume {1.0}
   {
   }
 
-public:
-  void setOutputDevice(qint32 n);
-  void setPeriod(int ntrperiod, int nsps);
-  void setTxFreq(int n);
-  void setXIT(int n);
-  void setTxSNR(double snr);
-  void setTune(bool b);
-  double samFacOut();
-  bool quitExecution;           //If true, thread exits gracefully
-  QString m_modeTx;
-
-// Private members
+  qreal attenuation () const;
+
+public Q_SLOTS:
+  void setFormat (QAudioDeviceInfo const& device, unsigned channels, unsigned msBuffered = 0u);
+  void restart (QIODevice *);
+  void suspend ();
+  void resume ();
+  void reset ();
+  void stop ();
+  void setAttenuation (qreal);	/* unsigned */
+  void resetAttenuation ();	/* to zero */
+  
+Q_SIGNALS:
+  void error (QString message) const;
+  void status (QString message) const;
+
+private:
+  bool audioError () const;
+
+private Q_SLOTS:
+  void handleStateChanged (QAudio::State);
+
 private:
-  double  m_txsnrdb;            //if < 0, add noise to Tx audio
-  double  m_SamFacOut;          //(Output sample rate)/48000.0
-
-  qint32  m_nDevOut;            //Output device number
-  qint32  m_TRperiod;           //T/R period (s)
-  qint32  m_nsps;               //Samples per symbol (at 12000 Hz)
-  qint32  m_txFreq;
-  qint32  m_xit;
-
-  bool    m_txOK;               //Enable Tx audio
-  bool    m_txMute;             //Mute temporarily
-  bool    m_tune;
+  QScopedPointer<QAudioOutput> m_stream;
+  unsigned m_msBuffered;
+  qreal m_volume;
 };
 
 #endif
diff --git a/ss.bat b/ss.bat
index 37f669a..d8483ff 100644
--- a/ss.bat
+++ b/ss.bat
@@ -1 +1 @@
-svn status | grep -v '?'
+svn status | grep -v "?"
diff --git a/wf_palette_design_dialog.ui b/wf_palette_design_dialog.ui
new file mode 100644
index 0000000..14e60e1
--- /dev/null
+++ b/wf_palette_design_dialog.ui
@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>wf_palette_design_dialog</class>
+ <widget class="QDialog" name="wf_palette_design_dialog">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>181</width>
+    <height>209</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Dialog</string>
+  </property>
+  <layout class="QHBoxLayout" name="horizontalLayout">
+   <item>
+    <widget class="QTableWidget" name="colour_table_widget">
+     <property name="contextMenuPolicy">
+      <enum>Qt::CustomContextMenu</enum>
+     </property>
+     <property name="toolTip">
+      <string><html><head/><body><p>Double click a color to edit it.</p><p>Right click to insert or delete colors.</p><p>Colors at the top represent weak signals</p><p>and colors at the bottom represent strong</p><p>signals. You can have up to 256 colors.</p></body></html></string>
+     </property>
+     <property name="selectionMode">
+      <enum>QAbstractItemView::NoSelection</enum>
+     </property>
+     <property name="columnCount">
+      <number>1</number>
+     </property>
+     <attribute name="horizontalHeaderVisible">
+      <bool>false</bool>
+     </attribute>
+     <attribute name="horizontalHeaderStretchLastSection">
+      <bool>true</bool>
+     </attribute>
+     <column/>
+    </widget>
+   </item>
+   <item>
+    <widget class="QDialogButtonBox" name="button_box">
+     <property name="orientation">
+      <enum>Qt::Vertical</enum>
+     </property>
+     <property name="standardButtons">
+      <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections>
+  <connection>
+   <sender>button_box</sender>
+   <signal>accepted()</signal>
+   <receiver>wf_palette_design_dialog</receiver>
+   <slot>accept()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>248</x>
+     <y>254</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>157</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>button_box</sender>
+   <signal>rejected()</signal>
+   <receiver>wf_palette_design_dialog</receiver>
+   <slot>reject()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>316</x>
+     <y>260</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>286</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+</ui>
diff --git a/widegraph.cpp b/widegraph.cpp
index 3efa1f2..7271eee 100644
--- a/widegraph.cpp
+++ b/widegraph.cpp
@@ -1,19 +1,37 @@
 #include "widegraph.h"
+
+#include <QApplication>
+#include <QSettings>
+
 #include "ui_widegraph.h"
 #include "commons.h"
+#include "Configuration.hpp"
+
+#include "moc_widegraph.cpp"
+
+#define MAX_SCREENSIZE 2048
+
+namespace
+{
+  auto user_defined = QObject::tr ("User Defined");
+}
 
-WideGraph::WideGraph(QWidget *parent) :
+WideGraph::WideGraph(QSettings * settings, QWidget *parent) :
   QDialog(parent),
-  ui(new Ui::WideGraph)
+  ui(new Ui::WideGraph),
+  m_settings (settings),
+  m_palettes_path {":/Palettes"}
 {
   ui->setupUi(this);
-  this->setWindowFlags(Qt::Dialog);
-  this->installEventFilter(parent); //Installing the filter
+
+  setWindowTitle (QApplication::applicationName () + " - " + tr ("Wide Graph"));
+  setWindowFlags (Qt::WindowCloseButtonHint | Qt::WindowMinimizeButtonHint);
+  setMaximumWidth (MAX_SCREENSIZE);
+  setMaximumHeight (880);
+
   ui->widePlot->setCursor(Qt::CrossCursor);
-  this->setMaximumWidth(2048);
-  this->setMaximumHeight(880);
   ui->widePlot->setMaximumHeight(800);
-  ui->widePlot->m_bCurrent=false;
+  ui->widePlot->setCurrent(false);
 
   connect(ui->widePlot, SIGNAL(freezeDecode1(int)),this,
           SLOT(wideFreezeDecode(int)));
@@ -21,68 +39,99 @@ WideGraph::WideGraph(QWidget *parent) :
   connect(ui->widePlot, SIGNAL(setFreq1(int,int)),this,
           SLOT(setFreq2(int,int)));
 
-  m_fMin=3000;
-  ui->fMinSpinBox->setValue(m_fMin);
-
   //Restore user's settings
-  QString inifile(QApplication::applicationDirPath());
-  inifile += "/wsjtx.ini";
-  QSettings settings(inifile, QSettings::IniFormat);
-
-  settings.beginGroup("WideGraph");
-  ui->widePlot->setPlotZero(settings.value("PlotZero", 0).toInt());
-  ui->widePlot->setPlotGain(settings.value("PlotGain", 0).toInt());
+  m_settings->beginGroup("WideGraph");
+  restoreGeometry (m_settings->value ("geometry", saveGeometry ()).toByteArray ());
+  ui->widePlot->setPlotZero(m_settings->value("PlotZero", 0).toInt());
+  ui->widePlot->setPlotGain(m_settings->value("PlotGain", 0).toInt());
   ui->zeroSpinBox->setValue(ui->widePlot->getPlotZero());
   ui->gainSpinBox->setValue(ui->widePlot->getPlotGain());
-  int n = settings.value("FreqSpan",2).toInt();
-  int w = settings.value("PlotWidth",1000).toInt();
-  ui->widePlot->m_w=w;
+  int n = m_settings->value("FreqSpan",2).toInt();
+  m_bFlatten=m_settings->value("Flatten",true).toBool();
+  ui->cbFlatten->setChecked(m_bFlatten);
+  ui->widePlot->setFlatten(m_bFlatten);
+  ui->widePlot->setBreadth(m_settings->value("PlotWidth",1000).toInt());
   ui->freqSpanSpinBox->setValue(n);
   ui->widePlot->setNSpan(n);
-  m_waterfallAvg = settings.value("WaterfallAvg",5).toInt();
+  m_waterfallAvg = m_settings->value("WaterfallAvg",5).toInt();
   ui->waterfallAvgSpinBox->setValue(m_waterfallAvg);
-  ui->widePlot->m_bCurrent=settings.value("Current",false).toBool();
-  ui->widePlot->m_bCumulative=settings.value("Cumulative",true).toBool();
-  if(ui->widePlot->m_bCurrent) ui->spec2dComboBox->setCurrentIndex(0);
-  if(ui->widePlot->m_bCumulative) ui->spec2dComboBox->setCurrentIndex(1);
-  int nbpp=settings.value("BinsPerPixel",2).toInt();
+  ui->widePlot->setCurrent(m_settings->value("Current",false).toBool());
+  ui->widePlot->setCumulative(m_settings->value("Cumulative",true).toBool());
+  ui->widePlot->setLinearAvg(m_settings->value("LinearAvg",false).toBool());
+  if(ui->widePlot->current()) ui->spec2dComboBox->setCurrentIndex(0);
+  if(ui->widePlot->cumulative()) ui->spec2dComboBox->setCurrentIndex(1);
+  if(ui->widePlot->linearAvg()) ui->spec2dComboBox->setCurrentIndex(2);
+  int nbpp=m_settings->value("BinsPerPixel",2).toInt();
   ui->widePlot->setBinsPerPixel(nbpp);
-  m_slope=settings.value("Slope",0.0).toDouble();
-  ui->slopeSpinBox->setValue(m_slope);
-  settings.endGroup();
+  ui->widePlot->setStartFreq(m_settings->value("StartFreq",0).toInt());
+  ui->fStartSpinBox->setValue(ui->widePlot->startFreq());
+  m_waterfallPalette=m_settings->value("WaterfallPalette","Default").toString();
+  m_userPalette = WFPalette {m_settings->value("UserPalette").value<WFPalette::Colours> ()};
+  int m_fMin = m_settings->value ("fMin", 2500).toInt ();
+  ui->fMinSpinBox->setValue (m_fMin);
+  setRxRange (m_fMin);
+  m_settings->endGroup();
+
+  saveSettings ();		// update config with defaults
+
+  QStringList allFiles = m_palettes_path.entryList(QDir::NoDotAndDotDot |
+        QDir::System | QDir::Hidden | QDir::AllDirs | QDir::Files,
+        QDir::DirsFirst);
+  int index=0;
+  foreach(QString file, allFiles) {
+    QString t=file.mid(0,file.length()-4);
+    ui->paletteComboBox->addItem(t);
+    if(t==m_waterfallPalette) {
+      ui->paletteComboBox->setCurrentIndex(index);
+    }
+    index++;
+  }
+  ui->paletteComboBox->addItem (user_defined);
+  if (user_defined == m_waterfallPalette)
+    {
+      ui->paletteComboBox->setCurrentIndex(index);
+    }
+  readPalette ();
+
+  //  ui->paletteComboBox->lineEdit()->setAlignment(Qt::AlignHCenter);
 }
 
-WideGraph::~WideGraph()
+WideGraph::~WideGraph ()
 {
-  saveSettings();
-  delete ui;
 }
 
-void WideGraph::saveSettings()
+void WideGraph::closeEvent (QCloseEvent * e)
 {
-  //Save user's settings
-  QString inifile(QApplication::applicationDirPath());
-  inifile += "/wsjtx.ini";
-  QSettings settings(inifile, QSettings::IniFormat);
+  saveSettings ();
+  QDialog::closeEvent (e);
+}
 
-  settings.beginGroup("WideGraph");
-  settings.setValue("PlotZero",ui->widePlot->m_plotZero);
-  settings.setValue("PlotGain",ui->widePlot->m_plotGain);
-  settings.setValue("PlotWidth",ui->widePlot->plotWidth());
-  settings.setValue("FreqSpan",ui->freqSpanSpinBox->value());
-  settings.setValue("WaterfallAvg",ui->waterfallAvgSpinBox->value());
-  settings.setValue("Current",ui->widePlot->m_bCurrent);
-  settings.setValue("Cumulative",ui->widePlot->m_bCumulative);
-  settings.setValue("BinsPerPixel",ui->widePlot->binsPerPixel());
-  settings.setValue("Slope",m_slope);
-  settings.endGroup();
+void WideGraph::saveSettings()
+{
+  m_settings->beginGroup ("WideGraph");
+  m_settings->setValue ("geometry", saveGeometry ());
+  m_settings->setValue ("PlotZero", ui->widePlot->getPlotZero());
+  m_settings->setValue ("PlotGain", ui->widePlot->getPlotGain());
+  m_settings->setValue ("PlotWidth", ui->widePlot->plotWidth ());
+  m_settings->setValue ("FreqSpan", ui->freqSpanSpinBox->value ());
+  m_settings->setValue ("WaterfallAvg", ui->waterfallAvgSpinBox->value ());
+  m_settings->setValue ("Current", ui->widePlot->current());
+  m_settings->setValue ("Cumulative", ui->widePlot->cumulative());
+  m_settings->setValue ("LinearAvg", ui->widePlot->linearAvg());
+  m_settings->setValue ("BinsPerPixel", ui->widePlot->binsPerPixel ());
+  m_settings->setValue ("StartFreq", ui->widePlot->startFreq ());
+  m_settings->setValue ("WaterfallPalette", m_waterfallPalette);
+  m_settings->setValue ("UserPalette", QVariant::fromValue (m_userPalette.colours ()));
+  m_settings->setValue ("Fmin", m_fMin);
+  m_settings->setValue("Flatten",m_bFlatten);
+  m_settings->endGroup ();
 }
 
 void WideGraph::dataSink2(float s[], float df3, int ihsym,
                           int ndiskdata)
 {
   static float splot[NSMAX];
-  static float swide[2048];
+	static float swide[MAX_SCREENSIZE];
   int nbpp = ui->widePlot->binsPerPixel();
   static int n=0;
 
@@ -100,16 +149,13 @@ void WideGraph::dataSink2(float s[], float df3, int ihsym,
     for (int i=0; i<NSMAX; i++)
         splot[i] /= n;                       //Normalize the average
     n=0;
-
-//    int w=ui->widePlot->plotWidth();
-    int i0=-1;                            //###
-    int i=i0;
+    int i=int(ui->widePlot->startFreq()/df3 + 0.5);
     int jz=5000.0/(nbpp*df3);
+		if(jz>MAX_SCREENSIZE) jz=MAX_SCREENSIZE;
     for (int j=0; j<jz; j++) {
       float sum=0;
       for (int k=0; k<nbpp; k++) {
-        i++;
-        sum += splot[i];
+        sum += splot[i++];
       }
       swide[j]=sum;
     }
@@ -123,7 +169,7 @@ void WideGraph::dataSink2(float s[], float df3, int ihsym,
       }
     }
     m_ntr0=ntr;
-    ui->widePlot->draw(swide,i0);
+    ui->widePlot->draw(swide);
   }
 }
 
@@ -163,15 +209,14 @@ void WideGraph::keyPressEvent(QKeyEvent *e)
     emit f11f12(n);
     break;
   default:
-    e->ignore();
+    QDialog::keyPressEvent (e);
   }
 }
 
 void WideGraph::setRxFreq(int n)
 {
-  m_rxFreq=n;
-  ui->widePlot->setRxFreq(m_rxFreq,true);
-  if(m_lockTxFreq) setTxFreq(m_rxFreq);
+  ui->widePlot->setRxFreq(n);
+  if(m_lockTxFreq) setTxFreq(n);
 }
 
 int WideGraph::rxFreq()
@@ -181,12 +226,12 @@ int WideGraph::rxFreq()
 
 int WideGraph::nSpan()
 {
-  return ui->widePlot->m_nSpan;
+  return ui->widePlot->nSpan();
 }
 
 float WideGraph::fSpan()
 {
-  return ui->widePlot->m_fSpan;
+  return ui->widePlot->fSpan();
 }
 
 int WideGraph::nStartFreq()
@@ -218,18 +263,6 @@ int WideGraph::getFmax()
   return n;
 }
 
-void WideGraph::setFmin(int n)
-{
-  m_fMin = n;
-  ui->fMinSpinBox->setValue(n);
-  setRxRange(m_fMin);
-}
-
-void WideGraph::setPalette(QString palette)
-{
-  ui->widePlot->setPalette(palette);
-}
-
 double WideGraph::fGreen()
 {
   return ui->widePlot->fGreen();
@@ -267,10 +300,12 @@ void WideGraph::setModeTx(QString modeTx)
 
 void WideGraph::on_spec2dComboBox_currentIndexChanged(const QString &arg1)
 {
-  ui->widePlot->m_bCurrent=false;
-  ui->widePlot->m_bCumulative=false;
-  if(arg1=="Current") ui->widePlot->m_bCurrent=true;
-  if(arg1=="Cumulative") ui->widePlot->m_bCumulative=true;
+  ui->widePlot->setCurrent(false);
+  ui->widePlot->setCumulative(false);
+  ui->widePlot->setLinearAvg(false);
+  if(arg1=="Current") ui->widePlot->setCurrent(true);
+  if(arg1=="Cumulative") ui->widePlot->setCumulative(true);
+  if(arg1=="Linear Avg") ui->widePlot->setLinearAvg(true);
 }
 
 void WideGraph::on_fMinSpinBox_valueChanged(int n)
@@ -279,36 +314,80 @@ void WideGraph::on_fMinSpinBox_valueChanged(int n)
   setRxRange(m_fMin);
 }
 
-void WideGraph::on_slopeSpinBox_valueChanged(double d)
+void WideGraph::setLockTxFreq(bool b)
 {
-  m_slope=d;
+  m_lockTxFreq=b;
+  ui->widePlot->setLockTxFreq(b);
 }
 
-void WideGraph::setSlope(double d)
+void WideGraph::setFreq2(int rxFreq, int txFreq)
 {
-  m_slope=d;
-  ui->slopeSpinBox->setValue(d);
+  emit setFreq3(rxFreq,txFreq);
 }
 
-void WideGraph::setLockTxFreq(bool b)
+void WideGraph::setDialFreq(double d)
 {
-  m_lockTxFreq=b;
-  ui->widePlot->m_lockTxFreq=b;
+  ui->widePlot->setDialFreq(d);
 }
-double WideGraph::getSlope()
+
+void WideGraph::on_fStartSpinBox_valueChanged(int n)
 {
-  return m_slope;
+  ui->widePlot->setStartFreq(n);
 }
 
-void WideGraph::setFreq2(int rxFreq, int txFreq)
+void WideGraph::readPalette ()
 {
-  m_rxFreq=rxFreq;
-  m_txFreq=txFreq;
-  emit setFreq3(rxFreq,txFreq);
+  try
+    {
+      if (user_defined == m_waterfallPalette)
+        {
+          ui->widePlot->setColours (WFPalette {m_userPalette}.interpolate ());
+        }
+      else
+        {
+          ui->widePlot->setColours (WFPalette {m_palettes_path.absoluteFilePath (m_waterfallPalette + ".pal")}.interpolate());
+        }
+    }
+  catch (std::exception const& e)
+    {
+      QMessageBox msgBox0;
+      msgBox0.setText(e.what());
+      msgBox0.exec();
+    }
 }
 
-void WideGraph::setDialFreq(double d)
+void WideGraph::on_paletteComboBox_activated (QString const& palette)
 {
-  m_dialFreq=d;
-  ui->widePlot->setDialFreq(d);
+  m_waterfallPalette = palette;
+  readPalette();
+}
+
+void WideGraph::on_cbFlatten_toggled(bool b)
+{
+  m_bFlatten=b;
+  ui->widePlot->setFlatten(m_bFlatten);
+}
+
+void WideGraph::on_adjust_palette_push_button_clicked (bool)
+{
+  try
+    {
+      if (m_userPalette.design ())
+        {
+          m_waterfallPalette = user_defined;
+          ui->paletteComboBox->setCurrentText (m_waterfallPalette);
+          readPalette ();
+        }
+    }
+  catch (std::exception const& e)
+    {
+      QMessageBox msgBox0;
+      msgBox0.setText(e.what());
+      msgBox0.exec();
+    }
+}
+
+bool WideGraph::flatten()
+{
+  return m_bFlatten;
 }
diff --git a/widegraph.h b/widegraph.h
index 194998d..edd106d 100644
--- a/widegraph.h
+++ b/widegraph.h
@@ -1,89 +1,96 @@
-#ifndef WIDEGRAPH_H
-#define WIDEGRAPH_H
-#include <QDialog>
-
-namespace Ui {
-  class WideGraph;
-}
-
-class WideGraph : public QDialog
-{
-  Q_OBJECT
-
-public:
-  explicit WideGraph(QWidget *parent = 0);
-  ~WideGraph();
-
-  void   dataSink2(float s[], float df3, int ihsym, int ndiskdata);
-  void   setRxFreq(int n);
-  int    rxFreq();
-  int    nSpan();
-  int    nStartFreq();
-  int    getFmin();
-  int    getFmax();
-  float  fSpan();
-  void   saveSettings();
-  void   setRxRange(int fMin);
-  void   setFmin(int n);
-  void   setPalette(QString palette);
-  void   setFsample(int n);
-  void   setPeriod(int ntrperiod, int nsps);
-  void   setTxFreq(int n);
-  void   setMode(QString mode);
-  void   setModeTx(QString modeTx);
-  void   setSlope(double d);
-  void   setLockTxFreq(bool b);
-  double getSlope();
-  double fGreen();
-
-  qint32 m_rxFreq;
-  qint32 m_txFreq;
-
-signals:
-  void freezeDecode2(int n);
-  void f11f12(int n);
-  void setXIT2(int n);
-  void setFreq3(int rxFreq, int txFreq);
-
-public slots:
-  void wideFreezeDecode(int n);
-  void setFreq2(int rxFreq, int txFreq);
-  void setDialFreq(double d);
-
-protected:
-  virtual void keyPressEvent( QKeyEvent *e );
-
-private slots:
-  void on_waterfallAvgSpinBox_valueChanged(int arg1);
-  void on_freqSpanSpinBox_valueChanged(int arg1);
-  void on_zeroSpinBox_valueChanged(int arg1);
-  void on_gainSpinBox_valueChanged(int arg1);
-  void on_spec2dComboBox_currentIndexChanged(const QString &arg1);
-  void on_fMinSpinBox_valueChanged(int n);
-  void on_slopeSpinBox_valueChanged(double d);
-
-private:
-  double m_slope;
-  double m_dialFreq;
-
-  qint32 m_waterfallAvg;
-  qint32 m_fSample;
-  qint32 m_TRperiod;
-  qint32 m_nsps;
-  qint32 m_ntr0;
-  qint32 m_fMin;
-  qint32 m_fMax;
-
-  bool   m_lockTxFreq;
-
-  QString m_mode;
-  QString m_modeTx;
-
-  Ui::WideGraph *ui;
-};
-
-#ifdef WIN32
-extern int set570(double freq_MHz);
-#endif
-
-#endif // WIDEGRAPH_H
+// -*- Mode: C++ -*-
+#ifndef WIDEGRAPH_H
+#define WIDEGRAPH_H
+
+#include <QDialog>
+#include <QScopedPointer>
+#include <QDir>
+
+#include "WFPalette.hpp"
+
+namespace Ui {
+  class WideGraph;
+}
+
+class QSettings;
+class Configuration;
+
+class WideGraph : public QDialog
+{
+  Q_OBJECT
+
+public:
+  explicit WideGraph(QSettings *, QWidget *parent = 0);
+  ~WideGraph ();
+
+  void   dataSink2(float s[], float df3, int ihsym, int ndiskdata);
+  void   setRxFreq(int n);
+  int    rxFreq();
+  int    nSpan();
+  int    nStartFreq();
+  int    getFmin();
+  int    getFmax();
+  float  fSpan();
+  void   saveSettings();
+  void   setRxRange(int fMin);
+  void   setFsample(int n);
+  void   setPeriod(int ntrperiod, int nsps);
+  void   setTxFreq(int n);
+  void   setMode(QString mode);
+  void   setModeTx(QString modeTx);
+  void   setLockTxFreq(bool b);
+  double fGreen();
+  bool   flatten();
+
+signals:
+  void freezeDecode2(int n);
+  void f11f12(int n);
+  void setXIT2(int n);
+  void setFreq3(int rxFreq, int txFreq);
+
+public slots:
+  void wideFreezeDecode(int n);
+  void setFreq2(int rxFreq, int txFreq);
+  void setDialFreq(double d);
+
+protected:
+  virtual void keyPressEvent( QKeyEvent *e );
+  void closeEvent (QCloseEvent *);
+
+private slots:
+  void on_waterfallAvgSpinBox_valueChanged(int arg1);
+  void on_freqSpanSpinBox_valueChanged(int arg1);
+  void on_zeroSpinBox_valueChanged(int arg1);
+  void on_gainSpinBox_valueChanged(int arg1);
+  void on_spec2dComboBox_currentIndexChanged(const QString &arg1);
+  void on_fMinSpinBox_valueChanged(int n);
+  void on_fStartSpinBox_valueChanged(int n);
+  void on_paletteComboBox_activated(const QString &palette);
+  void on_cbFlatten_toggled(bool b);
+  void on_adjust_palette_push_button_clicked (bool);
+
+private:
+  void   readPalette();
+
+  QScopedPointer<Ui::WideGraph> ui;
+  QSettings * m_settings;
+  QDir m_palettes_path;
+  WFPalette m_userPalette;
+
+  qint32 m_waterfallAvg;
+  qint32 m_fSample;
+  qint32 m_TRperiod;
+  qint32 m_nsps;
+  qint32 m_ntr0;
+  qint32 m_fMin;
+  qint32 m_fMax;
+
+  bool   m_lockTxFreq;
+  bool   m_bFlatten;
+
+  QString m_mode;
+  QString m_modeTx;
+  QString m_waterfallPalette;
+};
+
+#endif // WIDEGRAPH_H
diff --git a/widegraph.ui b/widegraph.ui
index 42faba8..dc57be9 100644
--- a/widegraph.ui
+++ b/widegraph.ui
@@ -1,398 +1,402 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>WideGraph</class>
- <widget class="QDialog" name="WideGraph">
-  <property name="geometry">
-   <rect>
-    <x>0</x>
-    <y>0</y>
-    <width>799</width>
-    <height>326</height>
-   </rect>
-  </property>
-  <property name="sizePolicy">
-   <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
-    <horstretch>0</horstretch>
-    <verstretch>0</verstretch>
-   </sizepolicy>
-  </property>
-  <property name="windowTitle">
-   <string>Dialog</string>
-  </property>
-  <layout class="QVBoxLayout" name="verticalLayout_2">
-   <item>
-    <layout class="QVBoxLayout" name="verticalLayout">
-     <item>
-      <widget class="CPlotter" name="widePlot">
-       <property name="enabled">
-        <bool>true</bool>
-       </property>
-       <property name="sizePolicy">
-        <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
-         <horstretch>0</horstretch>
-         <verstretch>0</verstretch>
-        </sizepolicy>
-       </property>
-       <property name="minimumSize">
-        <size>
-         <width>400</width>
-         <height>100</height>
-        </size>
-       </property>
-       <property name="frameShape">
-        <enum>QFrame::StyledPanel</enum>
-       </property>
-       <property name="frameShadow">
-        <enum>QFrame::Sunken</enum>
-       </property>
-       <property name="lineWidth">
-        <number>1</number>
-       </property>
-      </widget>
-     </item>
-     <item>
-      <layout class="QHBoxLayout" name="horizontalLayout_3">
-       <property name="spacing">
-        <number>0</number>
-       </property>
-       <item>
-        <spacer name="horizontalSpacer_4">
-         <property name="orientation">
-          <enum>Qt::Horizontal</enum>
-         </property>
-         <property name="sizeHint" stdset="0">
-          <size>
-           <width>20</width>
-           <height>20</height>
-          </size>
-         </property>
-        </spacer>
-       </item>
-       <item>
-        <widget class="QSpinBox" name="freqSpanSpinBox">
-         <property name="sizePolicy">
-          <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-           <horstretch>0</horstretch>
-           <verstretch>0</verstretch>
-          </sizepolicy>
-         </property>
-         <property name="minimumSize">
-          <size>
-           <width>110</width>
-           <height>0</height>
-          </size>
-         </property>
-         <property name="maximumSize">
-          <size>
-           <width>38</width>
-           <height>16777215</height>
-          </size>
-         </property>
-         <property name="toolTip">
-          <string>Compression factor for frequency scale</string>
-         </property>
-         <property name="suffix">
-          <string/>
-         </property>
-         <property name="prefix">
-          <string>Bins/Pixel </string>
-         </property>
-         <property name="minimum">
-          <number>1</number>
-         </property>
-         <property name="maximum">
-          <number>1000</number>
-         </property>
-         <property name="singleStep">
-          <number>1</number>
-         </property>
-         <property name="value">
-          <number>2</number>
-         </property>
-        </widget>
-       </item>
-       <item>
-        <spacer name="horizontalSpacer_6">
-         <property name="orientation">
-          <enum>Qt::Horizontal</enum>
-         </property>
-         <property name="sizeType">
-          <enum>QSizePolicy::Minimum</enum>
-         </property>
-         <property name="sizeHint" stdset="0">
-          <size>
-           <width>8</width>
-           <height>20</height>
-          </size>
-         </property>
-        </spacer>
-       </item>
-       <item>
-        <widget class="QSpinBox" name="waterfallAvgSpinBox">
-         <property name="sizePolicy">
-          <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-           <horstretch>0</horstretch>
-           <verstretch>0</verstretch>
-          </sizepolicy>
-         </property>
-         <property name="minimumSize">
-          <size>
-           <width>80</width>
-           <height>0</height>
-          </size>
-         </property>
-         <property name="maximumSize">
-          <size>
-           <width>38</width>
-           <height>16777215</height>
-          </size>
-         </property>
-         <property name="toolTip">
-          <string>Number of FFTs averaged (controls waterfall scrolling rate)</string>
-         </property>
-         <property name="prefix">
-          <string>N Avg </string>
-         </property>
-         <property name="minimum">
-          <number>1</number>
-         </property>
-         <property name="maximum">
-          <number>20</number>
-         </property>
-        </widget>
-       </item>
-       <item>
-        <spacer name="horizontalSpacer_2">
-         <property name="orientation">
-          <enum>Qt::Horizontal</enum>
-         </property>
-         <property name="sizeType">
-          <enum>QSizePolicy::Minimum</enum>
-         </property>
-         <property name="sizeHint" stdset="0">
-          <size>
-           <width>8</width>
-           <height>20</height>
-          </size>
-         </property>
-        </spacer>
-       </item>
-       <item>
-        <widget class="QSpinBox" name="gainSpinBox">
-         <property name="minimumSize">
-          <size>
-           <width>80</width>
-           <height>0</height>
-          </size>
-         </property>
-         <property name="maximumSize">
-          <size>
-           <width>38</width>
-           <height>16777215</height>
-          </size>
-         </property>
-         <property name="toolTip">
-          <string>Scaling (dB) applied to spectra before plotting</string>
-         </property>
-         <property name="prefix">
-          <string>Gain </string>
-         </property>
-         <property name="minimum">
-          <number>-20</number>
-         </property>
-         <property name="maximum">
-          <number>20</number>
-         </property>
-        </widget>
-       </item>
-       <item>
-        <spacer name="horizontalSpacer_7">
-         <property name="orientation">
-          <enum>Qt::Horizontal</enum>
-         </property>
-         <property name="sizeType">
-          <enum>QSizePolicy::Minimum</enum>
-         </property>
-         <property name="sizeHint" stdset="0">
-          <size>
-           <width>8</width>
-           <height>20</height>
-          </size>
-         </property>
-        </spacer>
-       </item>
-       <item>
-        <widget class="QSpinBox" name="zeroSpinBox">
-         <property name="minimumSize">
-          <size>
-           <width>80</width>
-           <height>0</height>
-          </size>
-         </property>
-         <property name="maximumSize">
-          <size>
-           <width>38</width>
-           <height>16777215</height>
-          </size>
-         </property>
-         <property name="toolTip">
-          <string>Constant offset applied to waterfall data</string>
-         </property>
-         <property name="suffix">
-          <string/>
-         </property>
-         <property name="prefix">
-          <string>Zero </string>
-         </property>
-         <property name="minimum">
-          <number>-100</number>
-         </property>
-         <property name="maximum">
-          <number>100</number>
-         </property>
-        </widget>
-       </item>
-       <item>
-        <widget class="QDoubleSpinBox" name="slopeSpinBox">
-         <property name="minimumSize">
-          <size>
-           <width>60</width>
-           <height>0</height>
-          </size>
-         </property>
-         <property name="prefix">
-          <string>Slope </string>
-         </property>
-         <property name="decimals">
-          <number>1</number>
-         </property>
-         <property name="minimum">
-          <double>-2.000000000000000</double>
-         </property>
-         <property name="maximum">
-          <double>2.000000000000000</double>
-         </property>
-         <property name="singleStep">
-          <double>0.100000000000000</double>
-         </property>
-        </widget>
-       </item>
-       <item>
-        <spacer name="horizontalSpacer">
-         <property name="orientation">
-          <enum>Qt::Horizontal</enum>
-         </property>
-         <property name="sizeType">
-          <enum>QSizePolicy::Minimum</enum>
-         </property>
-         <property name="sizeHint" stdset="0">
-          <size>
-           <width>8</width>
-           <height>20</height>
-          </size>
-         </property>
-        </spacer>
-       </item>
-       <item>
-        <widget class="QSpinBox" name="fMinSpinBox">
-         <property name="sizePolicy">
-          <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-           <horstretch>0</horstretch>
-           <verstretch>0</verstretch>
-          </sizepolicy>
-         </property>
-         <property name="minimumSize">
-          <size>
-           <width>110</width>
-           <height>0</height>
-          </size>
-         </property>
-         <property name="toolTip">
-          <string>Decode JT65 below this frequency, JT9 above</string>
-         </property>
-         <property name="suffix">
-          <string>  JT9</string>
-         </property>
-         <property name="prefix">
-          <string>JT65  </string>
-         </property>
-         <property name="minimum">
-          <number>0</number>
-         </property>
-         <property name="maximum">
-          <number>5000</number>
-         </property>
-         <property name="singleStep">
-          <number>100</number>
-         </property>
-         <property name="value">
-          <number>3000</number>
-         </property>
-        </widget>
-       </item>
-       <item>
-        <spacer name="horizontalSpacer_8">
-         <property name="orientation">
-          <enum>Qt::Horizontal</enum>
-         </property>
-         <property name="sizeType">
-          <enum>QSizePolicy::Minimum</enum>
-         </property>
-         <property name="sizeHint" stdset="0">
-          <size>
-           <width>8</width>
-           <height>20</height>
-          </size>
-         </property>
-        </spacer>
-       </item>
-       <item>
-        <widget class="QComboBox" name="spec2dComboBox">
-         <property name="toolTip">
-          <string>Select data for display curve</string>
-         </property>
-         <property name="currentIndex">
-          <number>1</number>
-         </property>
-         <item>
-          <property name="text">
-           <string>Current</string>
-          </property>
-         </item>
-         <item>
-          <property name="text">
-           <string>Cumulative</string>
-          </property>
-         </item>
-        </widget>
-       </item>
-       <item>
-        <spacer name="horizontalSpacer_3">
-         <property name="orientation">
-          <enum>Qt::Horizontal</enum>
-         </property>
-         <property name="sizeHint" stdset="0">
-          <size>
-           <width>20</width>
-           <height>20</height>
-          </size>
-         </property>
-        </spacer>
-       </item>
-      </layout>
-     </item>
-    </layout>
-   </item>
-  </layout>
- </widget>
- <customwidgets>
-  <customwidget>
-   <class>CPlotter</class>
-   <extends>QFrame</extends>
-   <header>plotter.h</header>
-   <container>1</container>
-  </customwidget>
- </customwidgets>
- <resources/>
- <connections/>
-</ui>
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>WideGraph</class>
+ <widget class="QDialog" name="WideGraph">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>799</width>
+    <height>395</height>
+   </rect>
+  </property>
+  <property name="sizePolicy">
+   <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+    <horstretch>0</horstretch>
+    <verstretch>0</verstretch>
+   </sizepolicy>
+  </property>
+  <property name="windowTitle">
+   <string>Dialog</string>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout_2">
+   <property name="spacing">
+    <number>0</number>
+   </property>
+   <property name="leftMargin">
+    <number>0</number>
+   </property>
+   <property name="topMargin">
+    <number>0</number>
+   </property>
+   <property name="rightMargin">
+    <number>0</number>
+   </property>
+   <property name="bottomMargin">
+    <number>0</number>
+   </property>
+   <item>
+    <layout class="QVBoxLayout" name="verticalLayout">
+     <item>
+      <widget class="CPlotter" name="widePlot">
+       <property name="enabled">
+        <bool>true</bool>
+       </property>
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="minimumSize">
+        <size>
+         <width>400</width>
+         <height>100</height>
+        </size>
+       </property>
+       <property name="frameShape">
+        <enum>QFrame::StyledPanel</enum>
+       </property>
+       <property name="frameShadow">
+        <enum>QFrame::Sunken</enum>
+       </property>
+       <property name="lineWidth">
+        <number>1</number>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <layout class="QGridLayout" name="gridLayout">
+       <item row="1" column="7">
+        <widget class="QComboBox" name="spec2dComboBox">
+         <property name="toolTip">
+          <string><html><head/><body><p>Select data for spectral display</p></body></html></string>
+         </property>
+         <property name="currentIndex">
+          <number>1</number>
+         </property>
+         <item>
+          <property name="text">
+           <string>Current</string>
+          </property>
+         </item>
+         <item>
+          <property name="text">
+           <string>Cumulative</string>
+          </property>
+         </item>
+         <item>
+          <property name="text">
+           <string>Linear Avg</string>
+          </property>
+         </item>
+        </widget>
+       </item>
+       <item row="1" column="2">
+        <widget class="QSpinBox" name="waterfallAvgSpinBox">
+         <property name="sizePolicy">
+          <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+           <horstretch>0</horstretch>
+           <verstretch>0</verstretch>
+          </sizepolicy>
+         </property>
+         <property name="minimumSize">
+          <size>
+           <width>91</width>
+           <height>0</height>
+          </size>
+         </property>
+         <property name="maximumSize">
+          <size>
+           <width>16777215</width>
+           <height>16777215</height>
+          </size>
+         </property>
+         <property name="toolTip">
+          <string>Number of FFTs averaged (controls waterfall scrolling rate)</string>
+         </property>
+         <property name="prefix">
+          <string>N Avg </string>
+         </property>
+         <property name="minimum">
+          <number>1</number>
+         </property>
+         <property name="maximum">
+          <number>20</number>
+         </property>
+        </widget>
+       </item>
+       <item row="1" column="5">
+        <widget class="QComboBox" name="paletteComboBox">
+         <property name="sizePolicy">
+          <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+           <horstretch>0</horstretch>
+           <verstretch>0</verstretch>
+          </sizepolicy>
+         </property>
+         <property name="minimumSize">
+          <size>
+           <width>80</width>
+           <height>0</height>
+          </size>
+         </property>
+         <property name="toolTip">
+          <string>Select waterfall palette</string>
+         </property>
+        </widget>
+       </item>
+       <item row="1" column="1">
+        <widget class="QSpinBox" name="fMinSpinBox">
+         <property name="sizePolicy">
+          <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+           <horstretch>0</horstretch>
+           <verstretch>0</verstretch>
+          </sizepolicy>
+         </property>
+         <property name="minimumSize">
+          <size>
+           <width>110</width>
+           <height>0</height>
+          </size>
+         </property>
+         <property name="toolTip">
+          <string>Decode JT65 below this frequency, JT9 above</string>
+         </property>
+         <property name="suffix">
+          <string>  JT9</string>
+         </property>
+         <property name="prefix">
+          <string>JT65  </string>
+         </property>
+         <property name="minimum">
+          <number>0</number>
+         </property>
+         <property name="maximum">
+          <number>5000</number>
+         </property>
+         <property name="singleStep">
+          <number>100</number>
+         </property>
+         <property name="value">
+          <number>3000</number>
+         </property>
+        </widget>
+       </item>
+       <item row="0" column="1">
+        <widget class="QSpinBox" name="freqSpanSpinBox">
+         <property name="sizePolicy">
+          <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+           <horstretch>0</horstretch>
+           <verstretch>0</verstretch>
+          </sizepolicy>
+         </property>
+         <property name="minimumSize">
+          <size>
+           <width>110</width>
+           <height>0</height>
+          </size>
+         </property>
+         <property name="maximumSize">
+          <size>
+           <width>38</width>
+           <height>16777215</height>
+          </size>
+         </property>
+         <property name="toolTip">
+          <string>Compression factor for frequency scale</string>
+         </property>
+         <property name="suffix">
+          <string/>
+         </property>
+         <property name="prefix">
+          <string>Bins/Pixel  </string>
+         </property>
+         <property name="minimum">
+          <number>1</number>
+         </property>
+         <property name="maximum">
+          <number>1000</number>
+         </property>
+         <property name="singleStep">
+          <number>1</number>
+         </property>
+         <property name="value">
+          <number>2</number>
+         </property>
+        </widget>
+       </item>
+       <item row="0" column="2">
+        <widget class="QSpinBox" name="fStartSpinBox">
+         <property name="sizePolicy">
+          <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+           <horstretch>0</horstretch>
+           <verstretch>0</verstretch>
+          </sizepolicy>
+         </property>
+         <property name="minimumSize">
+          <size>
+           <width>91</width>
+           <height>0</height>
+          </size>
+         </property>
+         <property name="toolTip">
+          <string>Frequency (Hz) at left edge of waterfall</string>
+         </property>
+         <property name="suffix">
+          <string> Hz</string>
+         </property>
+         <property name="prefix">
+          <string>Start </string>
+         </property>
+         <property name="maximum">
+          <number>5000</number>
+         </property>
+         <property name="singleStep">
+          <number>100</number>
+         </property>
+        </widget>
+       </item>
+       <item row="0" column="8">
+        <spacer name="horizontalSpacer_2">
+         <property name="orientation">
+          <enum>Qt::Horizontal</enum>
+         </property>
+         <property name="sizeHint" stdset="0">
+          <size>
+           <width>40</width>
+           <height>20</height>
+          </size>
+         </property>
+        </spacer>
+       </item>
+       <item row="0" column="0">
+        <spacer name="horizontalSpacer">
+         <property name="orientation">
+          <enum>Qt::Horizontal</enum>
+         </property>
+         <property name="sizeHint" stdset="0">
+          <size>
+           <width>40</width>
+           <height>20</height>
+          </size>
+         </property>
+        </spacer>
+       </item>
+       <item row="1" column="3">
+        <widget class="QSpinBox" name="gainSpinBox">
+         <property name="minimumSize">
+          <size>
+           <width>80</width>
+           <height>0</height>
+          </size>
+         </property>
+         <property name="maximumSize">
+          <size>
+           <width>38</width>
+           <height>16777215</height>
+          </size>
+         </property>
+         <property name="toolTip">
+          <string><html><head/><body><p>Gain (dB) applied to spectra before display</p></body></html></string>
+         </property>
+         <property name="prefix">
+          <string>Gain  </string>
+         </property>
+         <property name="minimum">
+          <number>-20</number>
+         </property>
+         <property name="maximum">
+          <number>20</number>
+         </property>
+        </widget>
+       </item>
+       <item row="0" column="7">
+        <widget class="QCheckBox" name="cbFlatten">
+         <property name="text">
+          <string>Flatten</string>
+         </property>
+        </widget>
+       </item>
+       <item row="0" column="3">
+        <widget class="QSpinBox" name="zeroSpinBox">
+         <property name="minimumSize">
+          <size>
+           <width>80</width>
+           <height>0</height>
+          </size>
+         </property>
+         <property name="maximumSize">
+          <size>
+           <width>38</width>
+           <height>16777215</height>
+          </size>
+         </property>
+         <property name="toolTip">
+          <string><html><head/><body><p>Constant offset applied to spectra</p></body></html></string>
+         </property>
+         <property name="suffix">
+          <string/>
+         </property>
+         <property name="prefix">
+          <string>Zero  </string>
+         </property>
+         <property name="minimum">
+          <number>-100</number>
+         </property>
+         <property name="maximum">
+          <number>100</number>
+         </property>
+        </widget>
+       </item>
+       <item row="0" column="5">
+        <layout class="QHBoxLayout" name="horizontalLayout">
+         <item>
+          <widget class="QLabel" name="labPalette">
+           <property name="text">
+            <string>  Palette</string>
+           </property>
+           <property name="alignment">
+            <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QPushButton" name="adjust_palette_push_button">
+           <property name="text">
+            <string>Adjust...</string>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </item>
+       <item row="0" column="4" rowspan="2">
+        <widget class="Line" name="line">
+         <property name="orientation">
+          <enum>Qt::Vertical</enum>
+         </property>
+        </widget>
+       </item>
+       <item row="0" column="6" rowspan="2">
+        <widget class="Line" name="line_2">
+         <property name="orientation">
+          <enum>Qt::Vertical</enum>
+         </property>
+        </widget>
+       </item>
+      </layout>
+     </item>
+    </layout>
+   </item>
+  </layout>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>CPlotter</class>
+   <extends>QFrame</extends>
+   <header>plotter.h</header>
+   <container>1</container>
+  </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/wsjt.ico b/wsjt.ico
deleted file mode 100644
index 8a55550..0000000
Binary files a/wsjt.ico and /dev/null differ
diff --git a/wsjtx.desktop b/wsjtx.desktop
new file mode 100644
index 0000000..147fc7c
--- /dev/null
+++ b/wsjtx.desktop
@@ -0,0 +1,11 @@
+[Desktop Entry]
+Version=1.0
+Name=wsjtx
+Comment=Amateur Radio Weak Signal Operating
+Exec=wsjtx
+Icon=wsjtx_icon
+Terminal=false
+X-MultipleArgs=false
+Type=Application
+Categories=AudioVideo;Audio;HamRadio;
+StartupNotify=true
diff --git a/wsjtx.iss b/wsjtx.iss
index 8d550fa..16a7dd9 100644
--- a/wsjtx.iss
+++ b/wsjtx.iss
@@ -1,23 +1,30 @@
 [Setup]
 AppName=wsjtx
-AppVerName=wsjtx Version 1.1.0 r3488
-AppCopyright=Copyright (C) 2001-2013 by Joe Taylor, K1JT
-DefaultDirName=c:\wsjtx2
-DefaultGroupName=wsjtx2
+AppVerName=wsjtx Version 1.3 r3673
+AppCopyright=Copyright (C) 2001-2014 by Joe Taylor, K1JT
+DefaultDirName=c:\wsjtx_w
+DefaultGroupName=wsjtx_w
 
 [Files]
-Source: "c:\Users\joe\wsjt\wsjtx_install\*.exe";                         DestDir: "{app}"
+Source: "c:\Users\joe\wsjt\wsjtx_install\wsjtx.exe";                     DestDir: "{app}"
+Source: "c:\Users\joe\wsjt\wsjtx_install\jt9.exe";                       DestDir: "{app}"
+Source: "c:\Users\joe\wsjt\wsjtx_install\jt9code.exe";                   DestDir: "{app}"
+Source: "c:\Users\joe\wsjt\wsjtx_install\kvasd.exe";                     DestDir: "{app}"
 Source: "c:\Users\joe\wsjt\wsjtx_install\*.dll";                         DestDir: "{app}";
-Source: "c:\Users\joe\wsjt\wsjtx_install\*.dat";                         DestDir: "{app}";
-Source: "c:\Users\joe\wsjt\wsjtx_install\wsjt.ico";                      DestDir: "{app}";
-Source: "c:\Users\joe\wsjt\wsjtx_install\CALL3.TXT";                     DestDir: "{app}";  Flags: onlyifdoesntexist
+Source: "c:\Users\joe\wsjt\wsjtx\cty.dat";                       DestDir: "{app}";
+Source: "c:\Users\joe\wsjt\wsjtx\kvasd.dat";                     DestDir: "{app}";
+Source: "c:\Users\joe\wsjt\wsjtx\wsjt.ico";                      DestDir: "{app}";
+Source: "c:\Users\joe\wsjt\wsjtx\qt.conf";                       DestDir: "{app}";
+Source: "c:\Users\joe\wsjt\wsjtx\CALL3.TXT";                             DestDir: "{app}";  Flags: onlyifdoesntexist
 Source: "c:\Users\joe\wsjt\wsjtx\shortcuts.txt";                         DestDir: "{app}"
 Source: "c:\Users\joe\wsjt\wsjtx\mouse_commands.txt";                    DestDir: "{app}"
-Source: "c:\Users\joe\wsjt\wsjtx\WSJT-X_Users_Guide_v1.1.pdf";           DestDir: "{app}"
+Source: "c:\Users\joe\wsjt\wsjtx\prefixes.txt";                          DestDir: "{app}"
 Source: "c:\Users\joe\wsjt\wsjtx_install\save\Samples\130418_1742.wav";  DestDir: "{app}\save\Samples";
 Source: "c:\Users\joe\wsjt\wsjtx_install\save\Samples\130610_2343.wav";  DestDir: "{app}\save\Samples";
+Source: "c:\Users\joe\wsjt\wsjtx_install\platforms\qwindows.dll";        DestDir: "{app}\platforms";
+Source: "c:\Users\joe\wsjt\wsjtx_install\Palettes\*.pal";                DestDir: "{app}\Palettes";
 
 [Icons]
-Name: "{group}\wsjtx2";        Filename: "{app}\wsjtx.exe";   WorkingDir: {app}; IconFilename: {app}\wsjt.ico
-Name: "{userdesktop}\wsjtx2";  Filename: "{app}\wsjtx.exe";   WorkingDir: {app}; IconFilename: {app}\wsjt.ico
+Name: "{group}\wsjtx_w";        Filename: "{app}\wsjtx.exe";   WorkingDir: {app}; IconFilename: {app}\wsjt.ico
+Name: "{userdesktop}\wsjtx_w";  Filename: "{app}\wsjtx.exe";   WorkingDir: {app}; IconFilename: {app}\wsjt.ico
 
diff --git a/wsjtx.pro b/wsjtx.pro
index 92270a5..2ae5cb1 100644
--- a/wsjtx.pro
+++ b/wsjtx.pro
@@ -4,78 +4,135 @@
 #
 #-------------------------------------------------
 
-QT       += core gui network
+QT       += network multimedia
 greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
 CONFIG   += thread
 #CONFIG   += console
 
 TARGET = wsjtx
-DESTDIR = ../wsjtx_install
-VERSION = 1.1
+VERSION = "Not for Release"
 TEMPLATE = app
-DEFINES = QT4
+DEFINES = QT5
+QMAKE_CXXFLAGS += -std=c++11
+DEFINES += PROJECT_MANUAL="'\"http://www.physics.princeton.edu/pulsar/K1JT/wsjtx-doc/wsjtx-main.html\"'"
 
-win32 {
-DEFINES += WIN32
-F90 = g95
-g95.output = ${QMAKE_FILE_BASE}.o
-g95.commands = $$F90 -c -O2 -o ${QMAKE_FILE_OUT} ${QMAKE_FILE_NAME}
-g95.input = F90_SOURCES
-QMAKE_EXTRA_COMPILERS += g95
+isEmpty (DESTDIR) {
+DESTDIR = ../wsjtx_install
+}
+
+isEmpty (HAMLIB_DIR) {
+HAMLIB_DIR = ../../hamlib3/mingw32
+}
+
+isEmpty (FFTW3_DIR) {
+FFTW3_DIR = .
 }
 
-unix {
-DEFINES += UNIX
 F90 = gfortran
 gfortran.output = ${QMAKE_FILE_BASE}.o
 gfortran.commands = $$F90 -c -O2 -o ${QMAKE_FILE_OUT} ${QMAKE_FILE_NAME}
 gfortran.input = F90_SOURCES
 QMAKE_EXTRA_COMPILERS += gfortran
-}
-
-SOURCES += main.cpp mainwindow.cpp plotter.cpp about.cpp \
-    soundin.cpp soundout.cpp devsetup.cpp widegraph.cpp \
-    getfile.cpp displaytext.cpp getdev.cpp logqso.cpp \
-    psk_reporter.cpp rigclass.cpp \
-    signalmeter.cpp \
-    meterwidget.cpp
 
 win32 {
-SOURCES += killbyname.cpp
+DEFINES += WIN32
+QT += axcontainer
+TYPELIBS = $$system(dumpcpp -getfile {4FE359C5-A58F-459D-BE95-CA559FB4F270})
+}
+
+unix {
+DEFINES += UNIX
 }
 
-HEADERS  += mainwindow.h plotter.h soundin.h soundout.h \
-            about.h devsetup.h widegraph.h getfile.h \
+#
+# Order matters here as the link is in this order so referrers need to be after referred
+#
+SOURCES += \
+	logbook/adif.cpp \
+	logbook/countrydat.cpp \
+	logbook/countriesworked.cpp \
+	logbook/logbook.cpp \
+        astro.cpp \
+        Radio.cpp \
+        NetworkServerLookup.cpp \
+        revision_utils.cpp \
+        Transceiver.cpp \
+        TransceiverBase.cpp \
+        TransceiverFactory.cpp \
+        PollingTransceiver.cpp \
+        EmulateSplitTransceiver.cpp \
+        HRDTransceiver.cpp \
+        DXLabSuiteCommanderTransceiver.cpp \
+        HamlibTransceiver.cpp \
+        FrequencyLineEdit.cpp \
+        Bands.cpp \
+        FrequencyList.cpp \
+        StationList.cpp \
+        ForeignKeyDelegate.cpp \
+        FrequencyItemDelegate.cpp \
+        LiveFrequencyValidator.cpp \
+        Configuration.cpp \
+	psk_reporter.cpp \
+        AudioDevice.cpp \
+	Modulator.cpp \
+	Detector.cpp \
+	logqso.cpp \
+	displaytext.cpp \
+	getfile.cpp \
+	soundout.cpp \
+	soundin.cpp \
+	meterwidget.cpp \
+	signalmeter.cpp \
+        WFPalette.cpp \
+	plotter.cpp \
+	widegraph.cpp \
+	about.cpp \
+	mainwindow.cpp \
+	main.cpp \
+        decodedtext.cpp
+
+HEADERS  += qt_helpers.hpp \
+	    pimpl_h.hpp pimpl_impl.hpp \
+            Radio.hpp NetworkServerLookup.hpp revision_utils.hpp \
+	    mainwindow.h plotter.h soundin.h soundout.h astro.h \
+            about.h WFPalette.hpp widegraph.h getfile.h \
             commons.h sleep.h displaytext.h logqso.h \
-            psk_reporter.h rigclass.h \
+            Bands.hpp FrequencyList.hpp StationList.hpp ForeignKeyDelegate.hpp FrequencyItemDelegate.hpp LiveFrequencyValidator.hpp \
+            FrequencyLineEdit.hpp AudioDevice.hpp Detector.hpp Modulator.hpp psk_reporter.h \
+            Transceiver.hpp TransceiverBase.hpp TransceiverFactory.hpp PollingTransceiver.hpp \
+            EmulateSplitTransceiver.hpp DXLabSuiteCommanderTransceiver.hpp HamlibTransceiver.hpp \
+            Configuration.hpp \
     signalmeter.h \
-    meterwidget.h
+    meterwidget.h \
+    logbook/logbook.h \
+    logbook/countrydat.h \
+    logbook/countriesworked.h \
+    logbook/adif.h
+
+INCLUDEPATH += qmake_only
 
-# (Is the following really needed???)
-#DEFINES += __cplusplus
+win32 {
+SOURCES += killbyname.cpp OmniRigTransceiver.cpp
+HEADERS += OmniRigTransceiver.hpp
+}
 
-FORMS    += mainwindow.ui about.ui devsetup.ui widegraph.ui \
-    logqso.ui
+FORMS    += mainwindow.ui about.ui Configuration.ui widegraph.ui astro.ui \
+    logqso.ui wf_palette_design_dialog.ui
 
 RC_FILE = wsjtx.rc
+RESOURCES = wsjtx.qrc
 
 unix {
-LIBS += ../wsjtx/lib/libjt9.a
+LIBS += -L lib -ljt9
 LIBS += -lhamlib
-LIBS += -lportaudio -lgfortran -lfftw3f
+LIBS += -lfftw3f $$system($$F90 -print-file-name=libgfortran.so)
 }
 
 win32 {
-INCLUDEPATH += ../../hamlib-1.2.15.3/include
-LIBS += ../../hamlib-1.2.15.3/src/.libs/libhamlib.dll.a
-#LIBS += ../../hamlib-1.2.15.3/lib/gcc/libhamlib.dll.a
-LIBS += ../wsjtx/lib/libjt9.a
-LIBS += ../wsjtx/libfftw3f_win.a
-LIBS += ../wsjtx/libpskreporter.a
-LIBS += ../wsjtx/libHRDInterface001.a
-#LIBS += ../QtSupport/palir-02.dll
-LIBS += /users/joe/wsjt/QtSupport/palir-02.dll
-LIBS += libwsock32
-LIBS += C:/MinGW/lib/libf95.a
-
+INCLUDEPATH += $${HAMLIB_DIR}/include
+LIBS += -L$${HAMLIB_DIR}/lib -lhamlib
+LIBS += -L./lib -lastro -ljt9
+LIBS += -L$${FFTW3_DIR} -lfftw3f-3
+LIBS += -lws2_32
+LIBS += $$system($$F90 -print-file-name=libgfortran.a)
 }
diff --git a/wsjtx.qrc.in b/wsjtx.qrc.in
new file mode 100644
index 0000000..ffa9bf8
--- /dev/null
+++ b/wsjtx.qrc.in
@@ -0,0 +1,5 @@
+<!DOCTYPE RCC>
+<RCC version="1.0">
+  <qresource>@wsjtx_RESOURCES@
+  </qresource>
+</RCC>
diff --git a/wsjtx.rc b/wsjtx.rc
index 9a0de81..d54bf4f 100644
--- a/wsjtx.rc
+++ b/wsjtx.rc
@@ -1 +1 @@
-IDI_ICON1       ICON    DISCARDABLE     "wsjt.ico"
+IDI_ICON1       ICON    DISCARDABLE     "icons/windows-icons/wsjtx.ico"
diff --git a/wsjtx_config.h.in b/wsjtx_config.h.in
new file mode 100644
index 0000000..4a564e2
--- /dev/null
+++ b/wsjtx_config.h.in
@@ -0,0 +1,33 @@
+#ifndef WSJTX_CONFIG_H__
+#define WSJTX_CONFIG_H__
+
+#define WSJTX_VERSION_MAJOR @WSJTX_VERSION_MAJOR@
+#define WSJTX_VERSION_MINOR @WSJTX_VERSION_MINOR@
+#define WSJTX_VERSION_PATCH @WSJTX_VERSION_PATCH@
+
+#define CONFIG_TEST_VERSION_MAJOR @CONFIG_TEST_VERSION_MAJOR@
+#define CONFIG_TEST_VERSION_MINOR @CONFIG_TEST_VERSION_MINOR@
+#define CONFIG_TEST_VERSION_PATCH @CONFIG_TEST_VERSION_PATCH@
+
+#cmakedefine WSJT_BIN_DESTINATION "@WSJT_BIN_DESTINATION@"
+#cmakedefine WSJT_SHARE_DESTINATION "@WSJT_SHARE_DESTINATION@"
+#cmakedefine WSJT_LIB_DESTINATION "@WSJT_LIB_DESTINATION@"
+#cmakedefine WSJT_DOC_DESTINATION "@WSJT_DOC_DESTINATION@"
+#cmakedefine PROJECT_MANUAL "@PROJECT_MANUAL@"
+#cmakedefine PROJECT_MANUAL_DIRECTORY_URL "@PROJECT_MANUAL_DIRECTORY_URL@"
+
+#cmakedefine01 WSJT_SHARED_RUNTIME
+#cmakedefine01 WSJT_QDEBUG_TO_FILE
+#cmakedefine01 WSJT_QDEBUG_IN_RELEASE
+#cmakedefine01 WSJT_TRACE_CAT
+#cmakedefine01 WSJT_TRACE_CAT_POLLS
+#cmakedefine01 WSJT_HAMLIB_TRACE
+#cmakedefine01 WSJT_HAMLIB_VERBOSE_TRACE
+#cmakedefine01 WSJT_SOFT_KEYING
+#cmakedefine01 WSJT_ENABLE_EXPERIMENTAL_FEATURES
+#cmakedefine01 WSJT_INCLUDE_KVASD
+
+#define WSJTX_STRINGIZE1(x) #x
+#define WSJTX_STRINGIZE(x) WSJTX_STRINGIZE1(x)
+
+#endif
diff --git a/wsjtx_update.iss b/wsjtx_update.iss
new file mode 100644
index 0000000..da3bec2
--- /dev/null
+++ b/wsjtx_update.iss
@@ -0,0 +1,18 @@
+[Setup]
+AppName=wsjtx
+AppVerName=wsjtx Version 1.2 r3537
+AppCopyright=Copyright (C) 2001-2013 by Joe Taylor, K1JT
+DefaultDirName=c:\wsjtx1.2
+DefaultGroupName=wsjtx1.2
+
+[Files]
+Source: "c:\Users\joe\wsjt\wsjtx_install\wsjtx.exe";                     DestDir: "{app}"
+Source: "c:\Users\joe\wsjt\wsjtx_install\jt9.exe";                       DestDir: "{app}"
+Source: "c:\Users\joe\wsjt\wsjtx\shortcuts.txt";                         DestDir: "{app}"
+Source: "c:\Users\joe\wsjt\wsjtx\mouse_commands.txt";                    DestDir: "{app}"
+Source: "c:\Users\joe\wsjt\wsjtx\WSJT-X_Users_Guide_v1.2.pdf";           DestDir: "{app}"
+
+[Icons]
+Name: "{group}\wsjtx1.2";        Filename: "{app}\wsjtx.exe";   WorkingDir: {app}; IconFilename: {app}\wsjt.ico
+Name: "{userdesktop}\wsjtx1.2";  Filename: "{app}\wsjtx.exe";   WorkingDir: {app}; IconFilename: {app}\wsjt.ico
+

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-hamradio/wsjtx.git



More information about the pkg-hamradio-commits mailing list