diff --git a/ChangeLog b/ChangeLog index dd9d8f63..95c8449c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,9 +1,240 @@ +=Version 3.23.12= + +2016-06-21 David Freese + + fa831b2: xmlrpc add_tx + 177a8f1: mfsk xmt filter + 2b57556: FSQ msg append + de187d9: FSQ IFKP heard lists + 76cf0e6: waterfall group + 5f762f0: thor image + 8cd6f83: RxID button + + +=Version 3.23.11= + + 198f645: RxID color changes + b657227: flmsg-arq autostart + c6ac0f1: Resize bug + 3c7392e: Hell Raster Display + 4841f10: Exit processing + +2016-05-29 Roman Bagiñski + + 274d500: Polish translation update + +2016-05-28 David Freese + + 9c959af: xmlrpc add tx text + 01245fe: Native Select Save-As dialogs + +2016-05-26 Robert Stiles + + 5209286: FLDIGI User Manual Update + 4b2005e: KISS IO Bug fixes/Additions and C++11 Test + + +=Version 3.23.10= + + +2016-05-23 David Freese + + e14bbb6: logger + 19e7bad: Restore focus + 0a99bef: RsID button + aa6592c: flmsg interface + 5b367fb: 4bars + b4b8df4: ASCII ctl chars + 759e6cf: Suppress dockable macros + 065ead7: Packet Prep + +2016-04-13 Edouard Lafargue W6ELA + + 505c8b3: Portaudio Mono + +2016-04-13 David Freese + + 68d9b32: FSQ message files + +2016-04-12 Robert Stiles + + 4ab48d4: KISS, 8PSK, FLARQ icon Modifications + +2016-04-12 David Freese + + 76ab77c: FLARQ + 9c04f07: focus behavior + 2a3f4d4: PTT delays + + +=Version 3.23.09= + + fc97b4a: FSQ variable Rx + 58b3940: Export ADIF_NAME + 91ddd6c: WF only + 92c3c36: DnD Image + 0ebcc2a: Frequencies2 use string + 20ac527: Documentation + 8eb05e6: View noise + 7cd0d8d: About + 9ed6cc3: NAVTEX update + +2016-03-07 Kamal Mostafa + + 6da8d51: Sanitize tile_x, tile_y startup values + +2016-03-05 David Freese + + b1d12b8: RxID enhancement + f7662df: TX timer + 4e055b4: rigcat mod + 4c9f140: PSK IMD + + +=Version 3.23.08= + + +2016-02-21 Rik van Riel + + f80745e: NAVTEX update + +2016-02-16 David Freese + + 5b2edad: Save Logbook + 1c8e0e9: Analysis mode + 0f650e9: flrig PTT + 106e3e2: flrig waiting + 71fa224: COM port close + dd1165a: fsq repeat last + fb0fd4c: Mac Logger + +2016-02-04 Jonathan Wakely + + 813b58a: GCC 6 build + +2016-02-01 David Freese + + d808977: CALL capture + bea9cfe: Scope View + 8bcc9e8: RigCAT modifications + + +=Version 3.23.07= + + 10266d2: Exit delays + e821e49: Contest fields + ebc00ed: OS-X start_process + f5e3186: LOG RECORD exports + c0281ee: HAMLIB CW RTTY + ddb084c: PSKR metric + 68c5a6a: PSKR/8 + 397f570: Audio adjust + 4280903: WEB query + 8af53b6: Mode Set + e756d93: Tab key docs + 2fb5648: hamlib PTT_ON_DATA + 22514a5: Macro Tool Bar + 94f8362: XmlRpc client update + 2652387: Log Notes + e9e8b36: Misc Updates + 78baf6c: Set Frequency + 14a2618: Rx SaveAs + 16ede08: flrig xmlrpc + + +=Version 3.23.06= + + 3f577d9: WO woes + 482d060: Smeter PWRmeter + e08e403: ARQ shutdown + +2015-11-20 John Phelps + + 0b5b329: Developer Doxygen and BerliOS clean - Cleaned and Fixed developer Doxygen files - Added GitStats to the Dev Doxygen info -- run ./scripts/doxygen/gen_doxygen_docs.sh + +2015-11-20 David Freese + + b19fff8: Documentation + 55e0d31: Compiler warnings + + +=Version 3.23.05= + + c86ec80: dock macros + 9b210f7: kml disable + 2e2c9e9: ADIF record repairs + 93342e4: gpio ptt + d6a34a4: NAVTEX/SYNOP/KML + +2015-10-19 John Phelps + + 51535ff: Add 8PSK 125FL 250FL + + +=Version 3.23.04= + + +2015-10-15 David Freese + + 2516356: CW filter + 7f23f3f: Update Check + 4862141: fsq abort + 3bed0e3: log merge + + +=Version 3.23.03= + + 551d105: thor-image + c3b610b: FSQ trigger bug + + +=Version 3.23.02= + + 0424764: fsq cqcqcq + 198c5a0: fsq sounder/heard-aging + dbb169b: FSQ directive + d47b1e3: rigcat delayed startup + e6ebe70: OS-X serial + +2015-09-23 Kamal Mostafa + + f75b92a: asciidoc timezone + + +=Version 3.23.01= + + +2015-09-22 David Freese + + 8ad0a8b: WX configure + 0caa5ea: PA debug + 838e112: WFALL-ONLY + f472a17: Logbook read + 7cb4c66: ifkp avatar depth + ea18942: IFKP image slant + + +=Version 3.23.00= + + f78aa38: Clear Tx Panel + cbff7c3: Olivia/Contestia start stop tones + 37175e2: macro bug + 3d6e0b9: FSQ updates + ed3b09d: ifkp modem + c82de8e: MXE update + 7b42e01: Macros + 0606d1a: Doxygen help + d4b6308: QSO rec + 2df24b8: MS Read logbook + 30ad2a9: WEFAX hang on INFO + 6704797: Nu opBW combos + db69617: LSB modes + + =Version 3.22.13= -2015-07-18 David Freese - 7bdf051: FSQ bug fix 9319676: XMLRPC commands diff --git a/configure.ac b/configure.ac index dc93a934..4a338347 100644 --- a/configure.ac +++ b/configure.ac @@ -8,11 +8,11 @@ AC_PREREQ(2.61) dnl major and minor must be integers; patch may dnl contain other characters or be empty m4_define(FLDIGI_MAJOR, [3]) -m4_define(FLDIGI_MINOR, [22]) -m4_define(FLDIGI_PATCH, [.13]) +m4_define(FLDIGI_MINOR, [23]) +m4_define(FLDIGI_PATCH, [.12]) m4_define(FLARQ_MAJOR, [4]) m4_define(FLARQ_MINOR, [3]) -m4_define(FLARQ_PATCH, [.5]) +m4_define(FLARQ_PATCH, [.6]) AC_INIT([dl-fldigi], FLDIGI_MAJOR.FLDIGI_MINOR[]FLDIGI_PATCH, [fldigi-devel@lists.berlios.de]) @@ -67,7 +67,7 @@ AC_DEFINE_UNQUOTED([FLDIGI_AUTHORS], ["$FLDIGI_AUTHORS"], [Fldigi authors]) AC_DEFINE_UNQUOTED([FLARQ_AUTHORS], ["$FLARQ_AUTHORS"], [Flarq authors]) AC_DEFINE_UNQUOTED([PACKAGE_HOME], ["$PACKAGE_HOME"], [Home page]) AC_DEFINE_UNQUOTED([PACKAGE_DL], ["$PACKAGE_DL"], [Download page]) -AC_DEFINE_UNQUOTED([PACKAGE_PROJ], ["$PACKAGE_PROJ"], [BerliOS page]) +AC_DEFINE_UNQUOTED([PACKAGE_PROJ], ["$PACKAGE_PROJ"], [Sourceforge page]) AC_DEFINE_UNQUOTED([PACKAGE_NEWBUG], ["$PACKAGE_NEWBUG"], [Trac new ticket page]) AC_DEFINE_UNQUOTED([PACKAGE_DOCS], ["$PACKAGE_DOCS"], [Docs index]) AC_DEFINE_UNQUOTED([PACKAGE_GUIDE], ["$PACKAGE_GUIDE"], [Beginners guide]) diff --git a/data/flarq.pdf b/data/flarq.pdf new file mode 100644 index 00000000..01a119bd --- /dev/null +++ b/data/flarq.pdf @@ -0,0 +1,2287 @@ +%PDF-1.3 % +1 0 obj <> endobj 55 0 obj <>stream + + + + + application/pdf + + + FLARQ + + + + + Adobe Illustrator CS3 + 2014-11-12T19:50:39-06:00 + 2014-11-12T19:50:39-06:00 + 2014-11-12T19:50:39-06:00 + + + + 200 + 256 + JPEG + /9j/4AAQSkZJRgABAgEASABIAAD/7QAsUGhvdG9zaG9wIDMuMAA4QklNA+0AAAAAABAASAAAAAEA AQBIAAAAAQAB/+4ADkFkb2JlAGTAAAAAAf/bAIQABgQEBAUEBgUFBgkGBQYJCwgGBggLDAoKCwoK DBAMDAwMDAwQDA4PEA8ODBMTFBQTExwbGxscHx8fHx8fHx8fHwEHBwcNDA0YEBAYGhURFRofHx8f Hx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8f/8AAEQgBAADIAwER AAIRAQMRAf/EAaIAAAAHAQEBAQEAAAAAAAAAAAQFAwIGAQAHCAkKCwEAAgIDAQEBAQEAAAAAAAAA AQACAwQFBgcICQoLEAACAQMDAgQCBgcDBAIGAnMBAgMRBAAFIRIxQVEGE2EicYEUMpGhBxWxQiPB UtHhMxZi8CRygvElQzRTkqKyY3PCNUQnk6OzNhdUZHTD0uIIJoMJChgZhJRFRqS0VtNVKBry4/PE 1OT0ZXWFlaW1xdXl9WZ2hpamtsbW5vY3R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo+Ck5SVlpeYmZ qbnJ2en5KjpKWmp6ipqqusra6voRAAICAQIDBQUEBQYECAMDbQEAAhEDBCESMUEFURNhIgZxgZEy obHwFMHR4SNCFVJicvEzJDRDghaSUyWiY7LCB3PSNeJEgxdUkwgJChgZJjZFGidkdFU38qOzwygp 0+PzhJSktMTU5PRldYWVpbXF1eX1RlZmdoaWprbG1ub2R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo +DlJWWl5iZmpucnZ6fkqOkpaanqKmqq6ytrq+v/aAAwDAQACEQMRAD8A9U4q7FXYq7FXYq7FXYq7 FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7F XYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FX Yq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXY q7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq 7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7 FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7F XYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FX Yq7FXYq7FXYq7FXYq7FXYqofX7H679Q+sR/XvT9b6rzX1fSJK8+FeXHkCK5PwpcPHR4bq+l91ovo r5BLsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVfK//OV9/d2H5g6D dWc8lrdw6cHhuIWKSIwuJKFWUgg56f7ERhLS5ITAIM+R5fSHA1d8QIW/l5/zlRrmm+lY+cIDq1mC F/SMPFLpF6fGuyS0/wBifEnJ9q+xOLJc9MeCX80/T+sfaPcjHqyNpPo/yp518r+bLD69oGoRXsIo JFUlZIye0kbUdD8xnnWu7Oz6WfDmiYn7D7jyLmwmJDZO8wmbsVdirsVdirsVdirsVdirsVdirsVW TTQwxmSZ1jQdWYgD8cVW2t3BdQiaBucZJAahFaGh64qq4q7FXYq7FXYq7FXYq7FXyR/zmLJx89aI P+1YP+oiXO89k8/BhkP6X6A4moFl4QlwfHO5w61xTBNNF1/VNHv4tQ0q7lsb6E1juIHKMPao6g9w djmXkGLUQMMgEonoWABibD6P/KL/AJyV1jV9VsPLfmWwN9eXsq29tqVmqq5ZtgZofhSndnQig/Zz gu3fZDFixyz4JcMYizGX6Dz9wPzcvFqSTRfReeeOa7FXYqhn1OxRiplBI60BP4jIHJFsGKR6KMmr wAfu1Ln32GROUMhhPVRXV5uXxIpXwFQfvyPill4IRsN/bSAfHwb+VtssEwWo4yEQCCKjceOTYOxV Qu7+zs053MqxDsCdz8h1OKsa1LzzGtUskp/xbJ1+hR/HDSLYrfa/LcOXnlMjdix2HyHQYVZ15Ln9 fy/BJ4tJ+DnIlITzFXYq7FXYq7FXYq7FXYq+Qf8AnM1qefND/wC2WP8AqIlzpuw8vDjP9b9DTlG7 wBZc6bFqmgxVkmzZYtYwMX0T/wA4keTxea1qHm+6SsGmL9U09j0NxMtZWHukRp/s80HtX2sfBjgB +reXuHL7fubMGPe300NYImb4Q0Vfh7HPOfF3dp4O3mufWD/uuP6WP8BhOVAw96XajqdwLdy8nEHY AbdcqnkNN+LELSdLr3ygScowVYrw82UnpQj5Gv8ATCJMDBFJcjJcTAwVVmU5K2BiiILuWE1jfbuv UfdkoyIYSgDzRkerSlgGRaEgEiuWDKWo4Qw78yLn0bi0uRsJEaNvmhqP+JZkBxywCfWv8rFUun1n r8WKvaPytn9fyZaSVrWSb8JGwJZZirsVdirsVdirsVdirsVfH3/OaP8Aynmh/wDbLH/URLm/7J+g +9qnzfPYJGbcSIYKsIlllSKJWklkYLGiglmZjQAAdSTl0c9MSH3v+X/luLyX5B0vQFoLqOLleMpr yuJfjnavccm4j2pnEdp6w5chn38vc52mxWfcnCzZqrdgYqqzYbYmKS3PmGQTuqRqOBKqx3OxplMs 27lR0wpCQzySyBVqzudh3JOQBtslEAMgt9LiT4pCXcgBhWg2+XzzIEHCllPRfNZAisR4t4HocJj3 Ijk70GZZI24uCrDschdNtA8lZLr3wiTEwV0uvfJCTAwYx+Zshl8tPOPtWkiSe9GPA/8AE65nh1pe Lz6x/lYUJfPq/X4sVfSH5ITet+XdjJ1rLcfhM2BLPMVdirsVdirsVdirsVdir4+/5zR/5TzQ/wDt lj/qIlzf9k/Qfe1T5vnvNqweqf8AOOXk4a75/i1K4j5afoIF5IT0M9aW6/PmC/8AscwO0s3BjrrL b9bKA3fWVxeerKTX4RsvyzisuTik7zDi4Y+bSzZXbYYqqzZK2Jih5NO0+aQyPH8bbsQSKn5A5EwB ZjJICkVaW9pbbwxhSerbk/eclEAcmucpS5oxZsnbUYqqyjJWx4WpooZ04uK+B7j5YCAVBI5JTd20 9r8X24v5x2+eVSiQ5MJiXvUkuvfIiTIwS/zCv17SL6y6tPDIif6xU8T9+bPGbiHT5RUiHzHPqpBI J3HUZNrS+bVeu+Kvrb/nHab1vyq02TrWa6/Cd8CXpWKuxV2KuxV2KuxV2KuxV8ff85o/8p5of/bL H/URLm/7J+g+9qnzfPebVg+t/wAkfLQ8sfl/bGVeOo6wfrtyaUYLIo9JD3+GOm3Zic5LtjVXMge7 9bsNDh4pX0DOlmzn7dyYqqzZK2JiqrNhtBiqrNhtiYqqzYbYmKqs2StiYqizYbYmKqs2G2JiqCUE UO4PUHDbGkn1KxMNZ4N4urp3X3+WUzjW4crFkvY80muLn4uvUZnaWVwdbrY1k975Y8910zzZqtl9 lY7h2jXwST94n/CuMyHFYvLqXvgV9r/84vy+r+TmlP4z3f8A1Evir1fFXYq7FXYq7FXYq7FXYq+O v+cz5lP5iaNBQ8k0hHJ7Ue5nA/4hnQdkj92f636A1T5vJvy18rHzL5xsNOdeVorfWL7w9CKjMD/r mifTmZq83h4yevRiBZfZR0jU5NPGoxQl7QEr8PUBercf5ffOE1eORPFzDvNBmgBw8j96AWbMG3ZG Kqs2StiYqqzYbYmKqs2G0GKqs2StiYqqzYbYmKqs2G2JiqLNhtiYr1uD6nE9CPh+Y64bYmKuJgRQ 7g5K2PCxbzHZ/VWWeL+4c0p/K3Wnyy7S7Eho1nqAPUPmT8/bVrfzTa3yCiX1sOR8ZIWKt/whTMwu A8taZj3wK+7/APnFE1/JPSD/AMX3n/US+KvXsVdirsVdirsVdirsVdir40/5zM/8mhpf/bEg/wCo u6zoeyf7o/1v0BqnzZf/AM4t/lRct5dk80X6+jFqz8bcn+8a2hYr8I/ZDyBtz2AIzD7Uz3PgH8P3 pgH01DFHDEkUShI4wFRR0AHTNU2MR84eW9N9IXkA+r3DtRgg+Btialex27Zg6nBGrGxdnotTK+E7 hg0gkhfi/wB46Zrzs7YUW1mxtTFED1ggkKME/noaffkt2G3Jcs3vjaOFVWfJWgxVVmw2xMVRZslb ExVPVDDf6CO2G2PCqJcEHix37Hxw2xMUXDoq66kti8phXjz9QDlQgim1R3y/ALk42pIEfe8N/wCc mfyn1qx8lw+YBJFdQaVcKJzHyDrDc0jLEEUp6gjHXvmeS6x8tYFfev8Azif/AOSS0j/jPef9RL4q 9fxV2KuxV2KuxV2KuxV2Kvk3/nJryxe+afz58r+XrIH6xqWmWsAcCvBDeXRkkIHaNAWPsM3vZ2QQ wSkehP3BrmN31Po+lWOkaVZ6VYR+lZWEMdtbR/yxxKEUfcM0k5GRJPMtiLyKpbr1g95ZBUqWjYNx HUr0YD3plWaHEG/T5OGTy7V7eQXfoRgyOW4oFFSTXYUHfNPkjvT0GGQ4bKKv9KtNO1FLcSmWQIhm iIFI5GAJTkPtUyc8YjKmvHllON0ndx9VhWiS12oyncHLzQcWNnoklpppuryRIyRGCeIHWg+eURhZ cqeXhjuv1DTWtE5qxIX7at1Fe+3XDOFIx5eJArNldtpiqrN74bRwqiTmtD9B8clbExV4uczpFHvI 7BUA68iaDJDdhLYW9G0rSLfToisZLyP/AHkh6mnYeAzaY8YiHSZsxmd3a5oun65o19o+pRetYahB JbXMfikilTQ9jvsexyxpfm5+YXknUvJPnDUvLeoAmSxlIhmpQTQN8UUq+zoQfY7dRir7S/5xP/8A JJaR/wAZ7z/qJfFXr+KuxV2KuxV2KuxV2KuxVhx8jLP+bjedrlQy2miQ6Zp24NJXubiS4enUFY2R QfBmzI8asXAP51/cit2Y5jpdirsVWejD6nq8F9WlOdByp8+uChzTxGqeV+c9MvbLXLi4dW9C5cyQ zfsnluVr4jwzT6rGYzJ6F6HRZYzxgdQlK3s5UsxLcdqnxPTKeIuTwBGaPrhspHLgnmtKjtvk8eXh as2DjTS31lbq7VpT+7Wpp45bHJZaJYeGOzWsyWVxA7IAsigsGHUU3645CCFwiQLHlnI6mo8cx7cz hTLR9PudUvUtYBud3fsijqxy3FAzNBozZBjjZeiaT5U03TphOC806/ZeSlFPiAAM2ePTxib6ulza ucxXIJzl7iuxV4d/zlF+TcnnTy2nmDRoPU8yaJG1IkA53VpXk8XiXjNXjH+sOrYqmX/OKAI/JLSA diJ7z/qJfFXr+KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KrZI45EKSKHRtmVgCD8wcBFpBI5JRrPlX TdQ002cUaWdG9SNoUVQHoRVlFK9cpy6eMo0NnJw6ucJ8R9XvYSPy68wfWfSPpCKv9/z+Gnjx+1+G a/8AJTt2v8pY6ve+5JNR03UNLuWguY2jIJCsQeLAd1PQ5ROEoGi5ePLHILBRWmaPrmq28rWUBlRC FYllQEnsCxAPvkseKcxsGvLmx4yOIsg8teQbxbxbnV40WGI1FsSr827cuNV4/TvmVg0Zu5OFqu0I 8NQ597Orays7VStrBHArbsIkVAf+BAzYRiByFOolOUuZtWyTF2KuxV2Koaw03T9PieGxt47aKSWS d44lCKZZmLyPQd3Ylj74qicVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirTxpIpV1DqeqsKj 8cBFpBpyIiKERQqjooFAPoGEBSbbxQ7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7 FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7F XYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FX Yq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXY q7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq 7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7 FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7F XYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FX Yq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq/wD/ 2Q== + + + + + + uuid:1DB51073376CE41187B9A68C8BD3AFDD + uuid:cf805a65-6155-fc48-92e2-0728527871f8 + + uuid:1CB51073376CE41187B9A68C8BD3AFDD + uuid:1BB51073376CE41187B9A68C8BD3AFDD + + + + Print + + + 1 + False + False + + 6.000000 + 6.000000 + Inches + + + + Cyan + Magenta + Yellow + Black + + + + + + Default Swatch Group + 0 + + + + White + RGB + PROCESS + 255 + 255 + 255 + + + Black + RGB + PROCESS + 39 + 37 + 37 + + + CMYK Red + RGB + PROCESS + 203 + 34 + 41 + + + CMYK Yellow + RGB + PROCESS + 255 + 241 + 45 + + + CMYK Green + RGB + PROCESS + 51 + 163 + 87 + + + CMYK Cyan + RGB + PROCESS + 0 + 171 + 235 + + + CMYK Blue + RGB + PROCESS + 51 + 52 + 141 + + + CMYK Magenta + RGB + PROCESS + 201 + 0 + 135 + + + C=15 M=100 Y=90 K=10 + RGB + PROCESS + 162 + 36 + 48 + + + C=0 M=90 Y=85 K=0 + RGB + PROCESS + 206 + 66 + 57 + + + C=0 M=80 Y=95 K=0 + RGB + PROCESS + 210 + 91 + 48 + + + C=0 M=50 Y=100 K=0 + RGB + PROCESS + 223 + 145 + 47 + + + C=0 M=35 Y=85 K=0 + RGB + PROCESS + 231 + 174 + 74 + + + C=5 M=0 Y=90 K=0 + RGB + PROCESS + 245 + 236 + 73 + + + C=20 M=0 Y=100 K=0 + RGB + PROCESS + 215 + 221 + 63 + + + C=50 M=0 Y=100 K=0 + RGB + PROCESS + 157 + 196 + 77 + + + C=75 M=0 Y=100 K=0 + RGB + PROCESS + 110 + 178 + 83 + + + C=85 M=10 Y=100 K=10 + RGB + PROCESS + 81 + 146 + 75 + + + C=90 M=30 Y=95 K=30 + RGB + PROCESS + 56 + 104 + 61 + + + C=75 M=0 Y=75 K=0 + RGB + PROCESS + 107 + 179 + 118 + + + C=80 M=10 Y=45 K=0 + RGB + PROCESS + 91 + 165 + 155 + + + C=70 M=15 Y=0 K=0 + RGB + PROCESS + 100 + 167 + 222 + + + C=85 M=50 Y=0 K=0 + RGB + PROCESS + 70 + 116 + 183 + + + C=100 M=95 Y=5 K=0 + RGB + PROCESS + 51 + 59 + 139 + + + C=100 M=100 Y=25 K=25 + RGB + PROCESS + 42 + 39 + 96 + + + C=75 M=100 Y=0 K=0 + RGB + PROCESS + 90 + 48 + 140 + + + C=50 M=100 Y=0 K=0 + RGB + PROCESS + 125 + 43 + 138 + + + C=35 M=100 Y=35 K=10 + RGB + PROCESS + 135 + 36 + 97 + + + C=10 M=100 Y=50 K=0 + RGB + PROCESS + 186 + 33 + 90 + + + C=0 M=95 Y=20 K=0 + RGB + PROCESS + 203 + 45 + 120 + + + C=25 M=25 Y=40 K=0 + RGB + PROCESS + 188 + 178 + 154 + + + C=40 M=45 Y=50 K=5 + RGB + PROCESS + 147 + 131 + 120 + + + C=50 M=50 Y=60 K=25 + RGB + PROCESS + 110 + 101 + 89 + + + C=55 M=60 Y=65 K=40 + RGB + PROCESS + 86 + 76 + 68 + + + C=25 M=40 Y=65 K=0 + RGB + PROCESS + 182 + 152 + 109 + + + C=30 M=50 Y=75 K=10 + RGB + PROCESS + 156 + 123 + 83 + + + C=35 M=60 Y=80 K=25 + RGB + PROCESS + 127 + 94 + 64 + + + C=40 M=65 Y=90 K=35 + RGB + PROCESS + 107 + 78 + 46 + + + C=40 M=70 Y=100 K=50 + RGB + PROCESS + 87 + 59 + 28 + + + C=50 M=70 Y=80 K=70 + RGB + PROCESS + 57 + 40 + 28 + + + + + + Print Color Group + 1 + + + + C=0 M=30 Y=70 K=0 + RGB + PROCESS + 235 + 184 + 104 + + + C=5 M=70 Y=90 K=0 + RGB + PROCESS + 204 + 109 + 58 + + + C=5 M=90 Y=75 K=0 + RGB + PROCESS + 197 + 66 + 70 + + + C=30 M=0 Y=95 K=0 + RGB + PROCESS + 196 + 213 + 75 + + + C=60 M=5 Y=95 K=0 + RGB + PROCESS + 137 + 181 + 83 + + + C=30 M=0 Y=10 K=0 + RGB + PROCESS + 188 + 222 + 227 + + + C=60 M=10 Y=5 K=0 + RGB + PROCESS + 124 + 181 + 219 + + + C=80 M=5 Y=10 K=0 + RGB + PROCESS + 81 + 174 + 213 + + + + + + Grayscale + 1 + + + + K=100 + GRAY + PROCESS + 255 + + + K=90 + GRAY + PROCESS + 229 + + + K=80 + GRAY + PROCESS + 203 + + + K=70 + GRAY + PROCESS + 178 + + + K=60 + GRAY + PROCESS + 152 + + + K=50 + GRAY + PROCESS + 127 + + + K=40 + GRAY + PROCESS + 101 + + + K=30 + GRAY + PROCESS + 76 + + + K=20 + GRAY + PROCESS + 50 + + + K=10 + GRAY + PROCESS + 25 + + + K=5 + GRAY + PROCESS + 12 + + + + + + + + + Adobe PDF library 8.00 + + + + + + + + + + + + + + + + + + + + + + + + + endstream endobj 2 0 obj <> endobj 5 0 obj <>/ArtBox[0.0 0.0 432.0 432.0]/MediaBox[0.0 0.0 432.0 432.0]/Thumb 54 0 R/TrimBox[0.0 0.0 432.0 432.0]/Resources<>/Properties<>/MC1<>/ProcSet[/PDF/ImageC]/ExtGState<>>>/AIType/HiddenLayer>>/MC2<>/MC3<>/MC4<>/MC5<>/MC6<>>>/ExtGState<>>>/Type/Page/LastModified(D:20141112195038-06'00')>> endobj 50 0 obj <>stream +HtWˎ$W $QAttFz 2wDf3X`g>"#_C޿Y~zC~Q ?%4i@ˬi*e1EfmmE@Jj}ԳG҂=o+5 ktJ ;i!59JJV攪φ3 i%CL9-@'uR7W?"XZ*d4\\feaxP+IM +w֮~"#`5kzYhSTU` 8cYI.9"cAhŒF}Vcܺ}|V{I; K]?#^=hCMe/tfu`g/]Fw7:_?߶p +ay.o4' je0V;, lvT=֌+FZ? Y`qD}N-00{=;[^o hm^x92xU +fi={r]7~a_q&n@ZaH =b;#׭"f.2H\IY#Bq^Q@SZINߏ)T$v%l e~`Z65danHdKEuL[  viM "LYJv+,RP$H?Bցy+ݳ .uM\ZQ 7`Her09b8k>?|+O8 y} ` m +{D&8w+X,WWj`: *^ !ekAܘވE8c`M9 +@!P e8gAXR\3XT=DY *8ԓ`NeSf|A :gP4I *\#Fi NryFl]0leroaw'(vX*=' W~HM3ł`DtCV, TƃoNJvcEԆm=, ;7Үš Fl*fzJߋAS!a{)H0.}7|dceքW׌o3rX2ːQ’G&^*A=@x (N1MwEYz/YǜgR5Ui.O5MvH Rʁ_\<rAG,H<gD6UÂǂpCRLo4Z09Hz#9!R,3tr Teõ;42ܼnp\yJXxu0̆D: +iYVSLșqOpuw Է Ԡ|2Z#C"7;CڲeouRy> Ԥid" ,TSA'g8M,e[GO }5ncYdč.ۊ]. 3sKF-i3-9(#KwUFSwZm1>F*.55$URQ<5#r6iRx-@(| nwg$l:$т.exU#j& PS5HreÀ=#,堌0#:*q}O9bA|ZydI&<>&!WǬA0l! >+ FD0*ُlϭȂ0)䳛g$sD'!N 0,+W!&kTlb`[^!E5B ¶M 5%G&N.Yi0Mtc|VHivZpJ3(M2\S<r˫O%_RKͩ܆뵨Ӡ*6GzBJVOrMPD|P&-PxXȶB6ttfÊ<8ad=pv\V-x&y&MtǚFPxm[^ +<3q'&$ y\0I 0Gp|q@DȂP).kk"V%݊`z7Ac0Iw%VS"WМ R. +!je[!6Of'Q"zt,n[ p_ӬΔdK2Gh>DiS$pBȸ=GSؖ? j6L+r"*6j639,t+.bzk9bܱy2J+hZ҄?A=,B[n biE>SJ4ţ*TPATЧ]LP+]Wf CE@Nz}LN1^EXJ^|"na,$qR?[dK KqWw Au!j_*e'`B5UMHaICj5rnoBmuWTĒ*<-$V̯8.P rLt2@e ⹺’>B)eA ,fn Xt1 5LMC^rR[/#2-e+ּ{sd>|rl! n}95E+CZh`R `fje8 +0{v endstream endobj 54 0 obj <>stream +8;Z\t4d+hJ&4SgK<*M.BMDj2+fOqHE*;L;/+G)b4,Da9\pA;FT62#-Fr'XKFm_ZC8 +O%1GRS=f>X@Q3Yf5RkW8)nt;M53!$%TDd-c2LN_]Je@:MJ*YYZ0I.h14:M5SqQB:2 +l>-5pR'kIkk?pVrFknQ%obGLek-e8#TX3V-[bGt]*g&Ih)LOT?[79[W#do*:dYI\I +N(TlXQkl%Fb;\XXPQZ*%RG0#Pq;eS0P<##Dg$^H1AYu>nkhle(Z)%-#+i5MtZ=P5c +cHY%EGJ:?QhVS;@@r,D+ZCEb`k[LMFQ"B+V6*\F`7&N].='Up0FYNBAO+KEW'sqW +EHC*;.1ueuXBab\:1GbBQT=)]p!HebBYKI0j\baE@+MKR7i9kn5YCS'2k`.%o?+H\ +Hu-@*d"#Q$6Ao?nlAfP'_%p,J]>,#`2PtMt=="R&2T=HLN@TjDB*ui!4&Kb"[-F%D +])?cFA7r(Il.MLQI?(\:WL$43lp^&DhS(g@]E2@7M^tt[.uT#*nl`LpY&"&(h8dKL +@Pk*qfH]a"s8*LY\d;I:rm.6]0QCh(0N?CpGb4Gan&2sA!:VrPYl~> endstream endobj 33 0 obj <> endobj 32 0 obj <>stream +q +0 46 432 340 re +W n +q +/GS0 gs +451 0 0 340 -8.5 46 cm +/Im0 Do +Q +Q + endstream endobj 49 0 obj <> endobj 31 0 obj <>/Height 340/Type/XObject>>stream +HYsFFqB82x&mUjQ$@5/I$MxOb5&]~/_ +Bkeb/ґo}ʤ\^e-EV&KnŮCR5P{^y'|:$[3k6|J~-dU 3Juedw2R3H;Vy#sMIiK-T愰K8GIei}'޿7efEmnJS.eNZTzyiΚ.Ң0^+.jtK?SvLfEJ_-I]ZצȽ52 9RP% w"E*}ތus^Jɦd]i 2̧]ʜhC*R:dJ=,uX̩a2'a< +'zrכk]JIdE],^M_i6| sRfgȔbUVNYAl;U{tM *@iG^g?i"y?<]~JM863]LiB /,*Kvl3oUar9^iṪ}w '*]eixJJ82K]mb),NQ+ף.t] vTLKͻ~G$iROB {NIR8DYW5n{JI)Rf7nj}`M&088=.cۉC袖יr TTeI!Y̢r:Peo8]q:lHp'Qwœ!Rf'l%kB(m]sܪC*-z5*UErDU*YXGN=tpA \\ݛ9^] b}YD&QܮR]OiGNRM2M4EI2%*4ױ?p8{JUȝ0g Cյ@0 +Z}Z*=KV5*eqSJUu|:.'zr./i"8&~4-yН0 yR(GIk u/R]JWu=_Q%UrӨɣz,jP瑚Gu"yaGG+l>qa,Nxy=ޙGI]AL,!(^[s+wt.]Si]EUq3&S1cUӈ&Y¦ +=x&ҕғr%w!iЫ++Ƹ8X`=E8!|DAݳX{wJyRM[wȩ0 u>Yx45R9:=W6ʭKF kM\}q%.=wn +%Bj+ğq~._nT:3ITZgƦfYXZBƲpa$AaR#E) WeXkQg0J O{vU4RrnlJ6r밵TȬQ~: 8 ][ܸMiյavAJXaj(eWB!0v@yT/Ty.CݚAWOwQ]F˴߼3*-ӤJGUi,V9Ӹ 2RE]EzT5L]X?(8eFq8-ܦQ:Qjӿ2_:3_wCNuIcZIٔ,)iVwR]Uu.Ѷ0%J-ҪۄIb)Y!԰Ʌ?qqqW##t)h'^;٣vch(È߾+KkȲe*в#Jw56]*ƝPU;UPa9 dܤc&$Yl(㸗4*'% kyDK#vA"y֤Xm{,I:ǎU;t.%*!gҤ*[W2.T˭G >ؽ +!@rqBு%YE$ME (r;3u^{k*33ɈLvTǏC +Zu,n'r2ק&k60ʼ>^6JJE<_2Cit;kߌ910E LGCc6pK]$].\S=gұ"%ݢ =2kox=P̨̩T JUc|Ne((wĚIFbbmڃ@~ "Kz +T!Įs0ٌHɴb1'8[̮iF~tJ 8zw꣞ݮ;ԶDy=YgΤZݦ[:VVwU Af{ˈma0Cz{cb- d(xUÏ .G%y/A_ =t?JgP: @E=멪Ѽ]}]خhUUUMr" ?(b3#1m'+XDA:Q8d{ boǎ1ձ_gku@>q/ioRr򾆛d?&%{%g)ngL,5|F "0Hd1!h6o~|z(}U0{W1J,JZ/4r vtUjeLՅnΊK]uO WgH^)2/ߍ% xm&o4YAC ,GvZ>:,T 3\2NѶ>eUyL\d:$[_XJJ[5K|W*]7ԮSSv (GCjE6YNuHb˒1 +z STNbѵn[SobbEPJdt6u%D0N!@͚?ODFPkvZ$^9Kϣt~Q) w ]'V;SUK):I :/qY1q 3 D䣇K17%[d"1i/zX쨉VuM{O?˒;˻֗}Jҫf_|yj/ VjѾMt80ll=ee.tuR?:Dr'? (:gvK*Dpv +IE$Ȋsy]r|"sőRt$.&6@eG)}YYi@J"ƃjv6TBCoURw[-ޔҮnժZuy%xR<02(!)4&Rl;!v}~d|2FiUoG"gY0碈:&F,ba{_VzD,JzfY:FiҀ9z!SC(4ᦲF 4=ڣTyjSv'K.Id I)O +]d27bba4}!|#dh =k?wrqFЏ;+d#ј{n4ZDSJJ n +/KgP"F^~AcmBLt2e67.াZɦ427'ZgFu^=P<[dxP0&N@=ؐ%P:jXxa#TR$BwӡZ{CQz9KRپP:͙־; g*K#_fm#W4R&_EwBJafJ͖JNu-+oZlBMts6fZCHPCk_5hUQȩv3$ 0Fk,J|$/?~MzzY:r.3ĴS(9ZQGXT +W(Mnݸ6(])Jastե9*Mf}TU@ސu8Gfa1HT/HN; Ѭ4)B9 +6+vR,,Ofq8"P^NU=ԐU'dr J?-t q3`& 3O ?|OD<9<b96Sh MTk.X0co[70.(]Reb5cfo1Πv0=7s(m +382QhG8rPp%VzR4@nJ7u6) R @P,!#I$*=%SAhZ2Ĕ~p5`TivaVjRy}J~CTJ82Y2Ĉ69()VZL9j J5,Ci^!9?\U@ aļNb1bCj'sWTy Po +VCxb@QAeq{qܞZ~k8gNNiZjTcM6{⇶Jmn퓁NRJLGox3DžQOLi8 +,BihZd.S)WHR%uBj(=z5gk>.;-JDpjU\*TMb&E? P9^M-h.W3vE".!w9k7-~'oaxE'ql_y8upU@q~lY6<'%?|O. gD!jS15n +VP*φ`'}y Y-JMkյBJDp5ix%k7~M/[G"VyAe0*i& +5 Ujb7BqFL6uᕶ9%g98u>Mwv$𸝜$ӏKҘn@ ]Ѳ4hoސ? wg&Rg֋5H2F QlȊ e D1 cY,M%ZNZ+_#.a T8E!Z$rz,:R5]&W-h! ?/3_& 1a\4ΚQ-"(GHQ/nD8v ()a(Ҕ*E~~b&&Z/.̳Qf{)E[*W`^Tb1@Q=n_?4fONt a':nūO!,|Q4* + ,]R)vN*_K'\l[8ʴO/~60LUg)j& )Jh04kQ߫BJUi>34XH3n6z+ؠiPe|a%" \PuA9C-vE''&~`)JNpEt(Ip/ۯ;LY`9|Q* 6+il%8fl:d +={h0d0,)$3p2^%@)A-^7Q+P:\y%t5[U7j"O ;B@-Rcli +,FMn8tq1E0ygƖ`bTYZ4EӴ(+(-)314(`u>r`f*:bEr +H !oZ4q;v|'z<<>,GVlG( %Dvӝ sp kğA[R (HQ8CX +##!) R09()0$uMt#PꖩAXAQqP:P1%\E5WWi H 2i +V:tbP<<Ð-O{;;ev)kŸݺj|4\K(;Rs1MApiX_ s[QoE//~r^nNl+zpOہAiQ'ONr~Q53P&"cW`n؛_ejէ y߽C/uFR|hNd0/EM( c;#v\IqHsh$L=ig<ŶXpTאȣ4Փ +DC"/1^dL ҟXeK(-R)LY$sm*U.ZN"ȣ(h +BGo4’ԥ"P1^bH#eEUtU\Q8ELtHJ:s眦U.#*3A)9Kߞҙ˔jR鲈77 TQ@)fʎf-㒦 4z@6#*F!BWu [ݎ{Q +;J'+BJ+]0 K?W];@MS;#~~wR=`l5w?@;"6pq ;!A+8hxMgv`R)z ѵ*zG0Ϧ"_i> }0rmvgU_Y0߫c!)8 +J_?Q45g zN')Ʃ(b-KT +XͲjG 33jB+k_IĂxr:{%eJ)S23SI5\$u^Ooy0 +y0Тb\攊x/R"Z荛 wgjֻQmeG)u>oFkX )URï@K4 A ME*eZW$eJgEA >:0fVQdqGF? g'SK)VU%I4<3#lDeE4DQH@]Ki0v2ZWRE0Ɍ[:FZhu "(Mrˇ  EFƹp,nrυ UPLG,> rV tY5v\u;E5gV]w!4n.0*d-ILD/{߿Ux+ޜR)&eAӬ$hYSUS4meDPG,T^ M[M P)*gX,Qe˚WQ`P/7-t :gÛ+Yq͉-Y9y{{kn^|.k*ыiD+(} ;F<,t}2p3I͜`QGB),L.5w}WFOh1WKT'+$"GO,Y6sdz4;D9{j̣G!5MA(:ћFQ``S}ߘ"6 .f[_^_K+Wk`"ie/BtJ[=%Xi[2otVK*QZRGy;p:Mu[F٨;w\:aeҗ\(B7o/@hj+ITrJ]tJLͣtN.PyXc̷3 U Gۭ`t< +7C+[0DۀR8Hu:O&WRˀi4W,Q%' *qb41 ~a9YhN@c.MyGJTw@)?U~4JSPJc3IQB)Tx)g\CDAO±JI?Ci1NMhiDӘppJt=Bitxȋ9c߯v7un%Rcj{oF{puiuqGGYo{Y=(z;%vʼnt? +He|=>q"ðT5pGXj2Jǘ-SK"4QUTQ%YL/ǘ̉0= M0y1=lšBjؙΞ[h6ܮmFqY,QBJQ*J#V9MNJ2B#O%*br~`3;J)_S6QSE .]~'xf(f4ŒY0Z|!11?fG҈n1DICxD!5y}t=*b^fS7͓crlXZL&KS5 -p Rrd< H)9|A'Mt9;B*RC$MLyHڟ%ZL7G^\*Js,-E9|-ⳬRc8 1ls +|* qx=\Qk؞cuQ*U^T6`t:Ty!_B5(|y/C'4dZm}vqv}t\kϺr- +M>*Q:ꖾ=\vPκ0y|恚Y}pXg39MSQ_e4-4EZ{/QVPFˌhTc!xb>XQ95@4"§4}W-Y/gjjFP4% +4(t 9Je#|B4tSД; ++; ) .cJ>**#JJJW@t +o2 +>Ol5L0Lى&YRfRA((p4cn\ΠiG?**}1-]nСa*aE߯QԽ`s7,WwWZ8+u^Q TѬWR2:~dx>~yGw}ӆV`[4C(SaTɤT'OG!"&:P-* iNL((HNW~۶8λx'/8ImOkUk/:lCߺa +(T;qR_uq|i'qlKxEQWx"|AHI6u|~)ꂜ2A4Ei( :^d{?(gK D?CQ/QJX +J7қ 7jf(-e4W.Rg8*R|EdR3P1(1b@;/[RpL&A)65QX J^L0&g:s)oK3[Zobح{ Q{3bZ7ך%()r6J6%@dDRYWۭ&)SrªH|OzC~oX~qCқLM0Jf*Hl0_~!Fca%eiLSX`_(9; A54(3Q\j(1QB LB8:§J}߲tM^҄J8EȜ:} /βҠJ: d@'By"yE瘀Yo>)*x][)@J%*0 '\LB (ڋ8xѯʱ.?ס՞9Mm5w 1*[J*{եZiͻ4!μ]׼fYL*K6ZC[3Z5iMgf?TG'ј#贆¥D A짟(,%(=|~yEZOJԿGK9(Hr +ϩlLds?NggxMFBCZ b3P9ǽw±*"Z2`Vm9ۦg QRXTg[s2Ph.:8Kn: i:bjM{c~P]ice3J3EOl5*}*23t_gj)P3j;Ugǵ\gNM;2! C?SIP"LLU!xdq"7ť3 +& +$2ZhpI)^p@IqSʏⰏP\^)(IR(7vP Dag FA4OD@Sz~Q >eRxQLJaYzzC+WR^-@(VcJcN + P&5pp ݅^ZcHOsk!B죴DXC7}ZV2>e,VDi4. vVѣswkKA3ӞASg&חjCYY@ԗ,(iLFs3ځ&uDRM}A#'|oe\8˂a=hcx&cQ(/Eb*5 P\VH,aq t QBPñzB3 4PO9[tЄXC\2%%(y{R& (NJ)noܯ2Ҍ ZB(3 EKc>; oۻ:˝,|{V +Rޅ ΙDqvnFOc8xTWbfW7zijܞϩwGkjw f4gj3T7jyk^mm ?IG u2Ѵoi_&#\'d4i} (hP:]k.ft@ؓ%VY8b}`:4i +0X"hAh?Ӫk>4ͅVUۗ@0*кEX*Cp 2!K0&$n)>E_pi<=5]d.j[mdd%A(XvOv,qS\y==wYi}tP󕦳6 +n:o-XOabhҚ)~󋟭T5'K3l~rGw͠tA&Q+ )_a`mh"URv +ΜSWǩiE6| SA=Fn<~d{ڳ rז1zmp|`IC1{odks1k@BȂ&-yt2>^煊xr":뭷m 8HxzydٖS']Wlհ˭cm +r~0@]4e͐c5ng'qĢxDJeEo^f~QN$3.;%ޖ+أ$uRR|-/˯Wz#tϡtvM_&s`<:8 Uy<R:`/|x3gBf@EXz?p&!Nvty"; nC+HO$Ps[(ϘP~6K,->c 68/0g{s|n>88DIR:i }u)MiӇ@i2RG +FE5]a _F:IvZd.n.(p}Nc>6CwC3 jbҸM>5g48ٯ(: +XㄅdY +礧SQ>#ƅb +킨;+!~9pcϹ#X@yI834}i@ih A鄣IJ))Wo wcJvL +^Ai>AS:)AǬ^yT% +>*y +r㹬</_|kJ[| mT1LASBNTR(>TJJ9PoN +dtnCJEsw;G6mas4ԩ9%Ft*i:4.6ꞥ 'AiTk>/|NA}A\ajz)K(hDi㪉Gy,'Ehgͅ 0?P5 hNrȁ".w˟9<*r 1GDA)/e*J?6xWөWX9:ZBԎ(J(0|hp*1z/z A@y_xrHi8kԺUvj%=M; ꁦmJdՕ]K۱mfl%!$EH$.m4 0 +μojSM$i8ihSU3šb +Zy'x ǒM4zy +"VpTX D"aX:TX#z lPY5ͥO)I_JYx؃D̑#_/e(8:3XP7Al8<'bJKӛ5Uj:t4ͫҼü'Qg |82ԸJ#MPS*K; 3a]5ÄAJkPS[&3pjF4Zs[׷ c6}ೣJ7h{܇! +DMxlJʶn|}况DҖD֖\qm]iꂖrY_a68[Z]Wj@ߩu,ذ;1NjCz0WT Y*'OF:KN|k䌚F*QXR"h +D:"^~y..]Xƚyot߷\/(T.T |y;*ǁ]p-(Nn^g}_'{o"}(^On&OWcyЬ+qe$EJ >^i8x?<{vセncAG&8c6ptsL)LD)%Uw˘PLՔʝkf2ȿ-uhZK€|~nrW_KQkè,1٩ +'Ӡ_NQ:Ҵ!OvV 6:5}QjbpBGzH(R*aQF=:Z2\sh`R=+ǺӕBe=! Nc2jZ,<3GQԡv6h; Os"C3~01s(}+CJd~[Ci)GFU: /&+(+N&M :"H)8 +Cy6$3UA^6g}FDQp* 5@P-m+"seвxtU sSU}"h~MGJSC^Ҫ5Μܾh_s2Rl/*I:QIP[ze,%7Ѻ`|K{N^!%.zY'3/)Mj:3iFۛ11IS4;#6k}S4J3k5Ԁ5tTYNP7Tztj;OrlzY]yT@Ínr()/C )A[G"˸"8yEg`̧N*7shGcuf>'o@i~RjR2Y(E>+IaK}689M.h xe&x; +;04n6M/I:TQݙ$;8&Y~O4trD)DZ)PjhzrEB@,zxJt}"mځROS)CZ2i!ܒd:R?!÷CԂX!ҙwL4gXf;j~o-)<&b4ueF}zF+nQ>@ +٭kVEs￷{nޒ|T髐»p$FNhnuXo”5J1Z@SmFO,Jqɧ S1 ЕDDa8g3-CS(|J #>`3fỲFv0pNk:J(d$cǿtRtk'/~W[<.p[v7͞v)9[s9Y CY7e™~?T¥_ +ʱ wEsXڗZb+-$5$Q餩 *>z((F#m>̬wtܔtQI]A蔊gJ[͐䟛J}U݆FvV5&D}fĸK+E֛*޻4su%s}z56{R(I:hXB v?_zt*L'bt:O#;ZեcUP5BZa(˨yP>=A#a.kyrNYܹq#grV?gkg'd4Lߴ|τArETS[2j(H4 d5e'Fith" m$U%>/$WĭuA5у X+l##L*P^>w귗*.Dp0LgY P؇GWV u2%UP&6UKO,[FEޫB,1tΒ2X/+=Ots7R<W$)${gj,DJv¥"Q aGί)-B(, =l"p?1{ͽ_m'dZFrJ ^>'i)jqA(FT)P3ҝ.TidO7FU +fN4|ւ&^zxX1zsYnRKͲԵc @KM]|1W|ӀҙNj*N^Pm1o>?inCJtVNm^'CY%1J35J)Z}@)wVhoEִBkǬVa$*h܊PL`"JGFvhŽ쩚)UD>AM0P֔Oy1s!K^_^-' Ν"gaL6w~|thY9&\3u15ڞ Jޥ룴ݡUjʼns} +iS#X)L8sL2R^w\R>XZC3TGtD##JK&-I"t;G>Oe/u j |-աmk*ޭ჊tX h*5ChVvU^S)l^@*jl⺞GJ7˴JJ5NQ_gm#wEINÙM>[lE6NOۗ.@JR4 -YeݒIldE7L:y(`8l|5V'zV-n5X .nDIj*bQy6 -)(Jv jbKN(ӡ2 +j,hityީ;1vBao#3nۛt>tF#R?j[3;>( ѾY\Fμ́:Tuǐ9(71/ (yffIK-ChJP _]3@!2-N/tϹ!WPoRM+R^,|d<( =ȐT 4cŢ)mw*ϥtV}H?G~$GwrriU 5J'Mj^rE ߠ^sfUU_[i +Raz:$ 6UMn&65"rԥtS-mE>G=1R8‘$R_"anR[uMO=}:xNtP?~J9ү}n/Z'I]/@i PQ7>Gp_ᙹO=EyfX㲒Y+]aкg(DAS視7T*HB'ɛwkyFko5:1M=](UT [w孵)3d(dtxOΊ:I"5p1#bgjQ:dor-34e T$Zr wQ72F ݌RDG!ME^FcƐ=X "#;19gٞJn4ԍr=6zA/㸂FB@ukg@_/FV!(e݉9!F玫6vĹ47?8o咮ctKЌS6JĊF*RQULkjϱm"^kncpCxe5Q(5H|UՌQbҠ&E4ŸI$#F2Qbe,mPX|GNt̟4sTwp$K.\QV>f}5t"m+%9{Շe(;ri5]CY Gy%O-Z+OsiRf0q!p%kV +WwŰe,f)2gTU0+ZCJT( +bH52Ol*55ua$jrTO5UJщuF&O4 +# hQѐm3Mcq#_ d_2R +5PCg + +qns[9J^(Qe?J.2o|1fd|Χ4PqPP/T񪘬r-5p,τs䉘:E<>!PUS-̕L7(o7 ؜g= c`ݫU/+w4ivՍױs2`Ƈ*m6v12cf NhɒEhldu$~fBd-v(y̶ѝ{h#73xM\M/-jl,%ۂVR߱􊑟Y8& tT$cao_T8ڔ)\Oz\HftGZ5&ʕ*g1J7w~5bu89{IWF@ٙPXS 88ڠRO su)WN٣U +>z^Rڹtuo8'AK@a +tNS*]/rn^ +:cj/n}+kY䴄Pӭ=nTJ'sZR: 1e?AvBm=h'zc+HUZHk)]a +[_DP: +-D'MuvQ_YUx}Um\3F1K)d7QW.cTj$ڱ @nuAiJv N UGkub 'E +>a1'$z&7^rDM'dUj)AuFBQFW)jy8ҙ ʞփ_HRpt$ ȿW~PJakَήo34:ߙޅ \_/+X"gc1:t&+ęR.Mad8` j:b(SƐ5ڤJ -ȱ:j$JHӎ=Rq[Ch#!u ;4J_?\]66M,f5L0Pc0FUڊVTmZzhD +y.cPOֆUۣ:$Tww.1A&dh)H 6iNVIG-RUWӯUgte +SP\kMݡjjD%a'C)^<(, I_TUzJ +f| _ Dl3AzsNޥ>GO''(}KYP]T0ukTJ}9|˶,@ZzQ!i9*j3pNn2QGPFZTkS嘄O 8XD $ Wk4VѣF,o)KlmX[ײ|h2m:A'Fi2g[{?Ho, _wl7q}_ (: J$r"mX;$7U1jA$Th9lVoџφ :uJ'LԛZHRQR8Z9٧tڂuZj%K6T}K+q%N*hnM$UUu$L/2H۸ +sPE7D;F3i>;;0~*bTSDFs2SID=zk^KI? {QyF.n')M#b?])]\{ٿh`N[yۚ7y[En 7=@5*5 %Jk5< O)?2B Tђ)%7Wh>]]1tQwP:I2[_S(5{j'J2$QVK%j#=A8Y q$Chkxhs e'{et)4t\\IqwL@Ӥ6u&+_uVLMݸVL1 hR )TсDk$Dm_O{ +mԭ'ԳJJ*J=>kIܿ +v{Εҽ^v#W[͖nNwwxz WnYR?*]d@;0\=#4˧B*tԚA +:pǠM ̚^zr4Et + !67z ?4xA-R6Hmx3xik^we͛16;K#{|=6l,kne4HiOxo~bHQNfhDK 7}u~ +o9%ɶ~sYKN 9a!Yi<,QeԻVm[  "ĥj1I+"2&vKMr&Q̤U>,tho^O2h/.3Xql+nɫ;L 2iǖ,;DQFR 0jWuVj5)ٝjOT;5qĎ8B,SV8x#-4}pW{ \v\{u G{>! ! ` ]c;0‹Vcavt~/ _>X^sQO^q\P:3ujr6fo@i>߫.kŠERT%$ٜAFJ\ +cL)!Zd TiM*eTCy좁J1i'whH@Y2GV22'մ')MU:6$fil'nZMY`+mF ڡHϰ$kQ +R4x)Z=\9ʣ$('SF솖4k,Tgܵj5*aԷPjXRF(j*x-LXѧi*D;(J?#WWq^w/x9 + ?s G4׾X~}[?[ +0AiY䘲9N^:RRx~ۑ~kJ/:*?JߨtvΙP;.z/V=* +~f੔jԻMgP +RZ1Hfm*#`TR⊦V4mOQGSU#Sʚ(kl>J"ƆcpN#֡tLkgnE3Z&)=Z0ۈƾ»݇ +Q:Q]@ TrrnlH@X +BB1nGI6)QS7nM(U +18`] 1_W"R$(EFJ5\|N:iv&MQz؅mw|{@F${=~+n{{4u O?w}N9Fإ9)HN:*ݝsHRh{QΟ>7P9MZdkTJ= UU)uu+`*-䅵)$8J)p&<\iN=&AT-c?ě؄Ye=b{qԳ`Cj RN$Q>0b7:r +.nDʦ( \xjz$58NL:`#Ō@8jƗ#%"Zos*ާ0ѩ`-WoPժ՗}p9&힏!0HR~u{C)r[ZZr6}阣7iyzRz~{p|QھR:\B˶W錵}z3J^>{S 2/cNT%U+)j)(a(#J4}\"rI3FbtJvRj斱.s[ѿjI! SԚuթX*M뙸I(6wz옪gwAᔗND` -b'g: A)h +Ԓq\?jb$˄W3JWN&b|-8u ;'hl'JW:Ďij +ήձT5UZv{yGJ~h:~3Q>_cz-/q`dbΦ}u#$.{({' N^txl/VG(stm?^S9Ɣk]_ ay3(5|DR3(UM*`)0{TQ{Jƒu}[Ww_ǔLJl0)m('7ubC[I}w=VHVf#$-O$r[B:Y"S* };"|am~/>B-Ij .CK媼8Ԅ4)g^a(Ʌed|1cJ1.Kυ8cg=AyYڝ*хAeXsRJ-^]#j!ivYgVBB/Ix*v)u=F[SJU:տw4ջ>gTիe9{`g7@ y#9 (/vjRg6.jYA%[Jz D9xoJy߶.lhk޿mlʹv?eO߰77MH JJ1E<)#;I[if|j%|Z,5:ᏩpBF-(E|Ya +!4N%z +HjBʀt XP\Dʮىc' n '985cj%)#|G)bِBr! +ao-☠HR7cj0?:5*LUt d4e>5%_w!p<Uو@iϸo3WU?ydu-nJ_}OߎyҁuFvp[@9}zZO*ɫ e$OJUra`,- lgj){AKs$!za+eꫮ_K}^ÐR}5OoSHe*Db5 (;N"t呪SO%8:V58GGycE&Ax§U18GfPWsrZ#bGnd$tұ`l.HyIT&=N9KM.Ԅ% pǀ?U) OB'@6{g>~]-dfmffn%_LrK9u9k,Tt=H4/MAQpTGɪy0r.QꓔsJ\]HRaf OY"cptkϻѻ?alo5?[VC Csj! +1 5vN +$V0%EC ׄH&hlEe =]y;)m`*j0GŒG!h!M%Uh1:U5nS[ +{$k/g^Ԏ}Cl=f',sL]G/2UAngnw_S}F =~}hJmVĤG6>=a|:<;_Cڳ@{JMsgRs%c.MsQN)TPj􎔎wt<Px}I/R^[ e%e4Y:5xDԡyy)! 8%?^Ȗ3ajr1(GI:ITWM]N=z]w? M_/yy{"HCMu,NXS/JUɽMZ5jo!|(\agWyu}F.J^^ͩYej)AǠf45F ~/-8R3=U!h + R>e6OВ#>A ~)P4-nɠvN +r1J13,x8:;jzRjuDwPUjћ6:^V*PGJOb77O˾"9cc!+i[t\>{DLc\sxwGޱGmzMU͐ҁޔR>j җLdzeFI5RJ |vPjԵP1jԂS$UXI&"B+parPPnA[\PsCR$5>I o|x9 6?I9VP]`C[B\_@H^qȟepK`2W($6p3 +YRRJP@YI3&$ Z/J]M%*Vl5*Iq*B0~%9DW2f|;h*ԵJ]=TiǤ(={;W;Uڹ%@?!:һ'MzJJ{߇Rڜ t:݃ @w׈k)J׈:5R*u:^ZRYʒT=$( $:4BkOZ+(+UqIU~NSl<+c'jZaɃHl@@B E}kU֩:6Ϸ @=1\e%\2_RzNI!uJQ8 iA6Zu$)<Ó)AǦFxbrL`] b*<;\~W+Uff%?0 +2ݎB/GK6iO05) +C)'U7_/&_nO\ Jt]RzGxnnRO6WUJ(?!Y93{43L1\9s~5IVM/@wy+U䍱L `ijrM alEitrf,D M$%N jAJޯyct  +5(D&%ZYy74Rq~{SHmȓsj. j1Bp?,(Ep3~upK/\].s5G'|#M s#-rZ}Ũ: +2l1$q`!F ‡~kOUc6M't̥%=h{Au&Рpt0E]G8C]?{/f{cS{)5)WҶW3&J.;ty.%J:ԨAo.˵A3 \cU%R<#(5ﭔ +3)LA$O_^sIBTK % VPSU7^GB*zL`] /wK擿NaJ9.u5xe9FjuW+iJPxшpPH8Ga!cJddFQ|<^l0ttJgLv𜛀x% I>BiH(qm_{0=7%1j8n1KL=919sw˸5ܗ&^wu] юNQnM}D< +@ܔt2Uyz@},AЮ]VCM:{'jF~2t~(s3z5DLe0|KR\1nԷ4)ޣ1jj<;)e?,&3e/c(]c8o5$pN58D4>{^%}h|K]k`׮uV= Vx{Gqg| +,&`DR>LQjF"NkZ "8:A { V,3^~>.rbvM7fE|RC:8JS7R`g(O,Nm:wLV Ӧ^=lCY+f<ͶOǿkʹgw?q1%bPo{3L.;.!ӹ>jm4DPzE +ף0ן%zIUS8"XJ1`( nVÈJ(ULXU%{Φ">R˪tRxw7/[i}OS|!ؔ_dw1i襴wU^$ZjM +;q^%*ȥMJIR@`QJ5Gч7 f[9c%-&Q>)"(DȹD(8AϑA5n"Niǔ)MG +~Ujф6~O]];_N8:t(Nһ[Ƴj|bJomJ;mbj%oYקP:٠FbA3ģpv@DuNxΫ}UjP=Jjwb_!,"GiU4+VME+zJ%^&lF !me l]ԧ1IͽLԘ*!&ݸ*.ǴB2|G`UDUIRRaG5u&sbkw- Z.j|!"b*\*AP$E;`UjQ9>8ՠڣf{Ԙ R-}E=vr{w'?!'䉣rƴ_0ML_'_!ݹEtB)nvϏ^w_Ôj::6.,zOZ)X.v_RK6o9 aTtRj"HUS)j**5N[Q"bZ^d8j)T*ϟ6]W3YCh3*9 ,#dp/%"Q$TUE +|** :i #zmj; `c[9G_6dwM~;i;m3iM`nNf/IȒuLҙ,39:B?dՆS*GKeG3TSmd<[SUJiUm +^d1VZ!5mS4HY-6@;‹/pSB+*؈`$?P@_0w(Ǽ}p#Mth'@.Xv&Az= +'G7.t[ceTRsjԐiґoq.`H)lJ܏/ANn,hUWsF}!+:ޠXPUաIfWwȶS, };oljdSL]M<-᧋E L]\ݔA+)RN'[sev.V$}Vy⦠TP8J'5ꂬ7'xJϹY:u*˧(llKShdzH&tl+ yG2Yۖ*R +Ko$fo'(6CG&wvX^ww˯6}w}PVzu%|khZAD sL/P >[MvnXoVn h: 4'(55j)[髹l-kd:(Q#RT?~M fFhCdzkۺ¸E-"5IaTU`WԵyB mQɮjYzh,d9mKZH)!e6{=l=: +@B[Edz*2fE(ޟR?T;T$SgS)uIGFpjN7 2~dшVPUIaGl_ Ұv|69u+ EAaoyAyRʙvhQ3TUڭRiꯤWI?<(Vz{˜Sg}WJ/vrJ3+Q)*lMR(JN@_SqA舮Xn!"zJ춊 ,nM"md^Zm'գ$9c0%(*.vULP +4bC)ÆS*qI*cIbz&ggh,/%$ Ŵ>[DOK#gIq>ʤt'0d>xDiFS2˟wgNLķqVR+hq:-67>j~=~GAPg8JQD?!J-O&،sV1/]J#5Mi75p{PC޸;zv00gA~w9>n6}J)(u5꜋O]2x'xm |fuX@_i,wwY__|UUϋV`. 81I'IwaR=Zwv|`< 35dça+t4 WÎ6p꜆:gqxw1 +|$3>:=D5M#kүT JQNGo_t)^UQzObYhH>$XS$I~#p(VΩ8AoAEtYh4ڌ,z1٨#PMвZգ0RR/X^?9.mGo?^ļ0wqKiD'Xrƾ w.ӏ"g:Ei( iDB)3)վs\OozmLDf,7+Jᓲret¨)B4/iΧcht2޳Rw*_@ΥuB)HALƲtDJTF TTKjb+^5 +IF7iILi^3k+w)q;FtRG侺ߟV;%g۸\@s1' 3:GаLRu)Ҥw=Ft)T~q1hL'$tt SbyO ɘĽ;W+E{Dzhp5Mդ:i :tj2 +];)ڦ zEA&ScEBx_JVi+/0DPlbJ9ҋK2FxH eJG {^/fSMQ :S#mPY=ޥ1qI j qϏSL)7 Y]K[v?޵kϾ?O덜Z$9#2u:BW_d4tTKU`dmV3ZUլQ!sF׉ˆ4^[)+8L9T-j'ZiszMlA<V.S-bi (,ZaAtbD X2-$t: + @|^iKUf[mK+fnZV7rN*e 4P`G붼Oݯ_%scmlGz_R poR<&·}-8 +#)dH{@5:.{cJiȗK3N(JM\#bJAttJA-֫ohOmM9P:At@T$cFjjU|U ;TѰhjlzS1@mŽĠ:` tH- VJi#h +TZJ)Mb0`8.4~ALIbr{U@P*sKզ߇1oK݂ GVJAVg krf%cVÐr lP+*7-߯И"(A95qQ{gT[~Jp~;b?Iט5fܮܬ{O*C:[VÛ."K117RXçNzoع]a9tS5ga|:tO}T-BkM4Tm]oj[ږͰim 5la#jY馤6#;@URޭQJKH,ŧK|BNY”ʩnLJaTS\B<+%ՎȀ<,o&)% -RF'eVSZ0@KT+-5_'mcwIK{|(j A1C ZEz1?29X3g"Y,k8I3MRw'ђi-I~%vUԄ4^S:itGCf &`Cw?zL +8SJ^)<Ӕ ϻCo}fM)uU:YPg}?v ӑ09 3=:GP~)_Ρ?G7Ϙ;ʗ_)ZJҊ8UJI$") f#jV>݊Ψ>0t8U:ij{asV2*i,Ө SP[E_=Y)M WjSb); Zij +(Ul@H/ չ;giC a*CJE Ɵ|K'-ii>Z.IکÉ`3e -LYJ:`=%U3JdTt\S$)3T1  iJɣ5t ,+aޓY54F)JK8gkJfE"J 6rPSmJtϞ_|Scϳ}lG)u(uCG'\__ ZiIbA=,.ؔR}?q`iVbd)%#s%Nы4&ok8EaFhPrl"xLVeaSӈSk:%("W$pa+`2[!6#JK.둚X6VeR:CJޣϩ u;XD>+n +| =aB}Q+؄l]X(؂u*\ uB)C:"/3:8#ݔI44q03 %Eaڝ[C;;笞NK~hoS_Di(/?Z5ᴌ 14WiBݖX8FYؽðx|XRR&5v2ҏe:sV1*MPhzEJPUNR) [g`g&%#KZUJm|'?mp +\RS+1=(KJmQdI`3hу}/9>o"+dA$^Jql v5#`I.,Ud*[9!`jV\HR2qC=YreSJ9%hFxBFB2p2 Rq)*RJ? (rٓsV)'񴚞{uۥ3CTi#6íKi$[צױ)%M/i3A^føRq1cQgP :6oӆX5+<| UV'2bh(Ez@>B WF)u8$*]L$ +5h?zi;WM% YHl5h>y <} `| TD56x.2U-KB K*5%PP2Kb-=FWОq$v+(A?֦T])]%))oEPRWt\50qJ`k J1ugsJ۝@QI߽zy E}9ߤI}j?6iLBTz9v^S{m.i=rk]_O W-~E +p>(MQ14EQp748qbI( I +gܹCIgT=|#2v ̗W63۶~f{`а <P>46q)}&0)_Ngǂv6 }}mPٰ ync!HG 6s&&aYKۖa ^v e+@%hV6 o-ڔ m&6cY)5\pc@Qhҧ&y%&ۼ\l\^o̯<6z4ױ9h, + ,hK+N3JBVM#ǝIkR +"8OWsȚDMtjf_nvbW/K]J y-c.ef͹;;.ǜZj7et/n(e+RLwtҷ?ks 690س  + +U,$бNX4l`7X)$$kѮnv y=#6 +k u, C- _50 *y"ʼn@GA:!Vs&L&0xe#ZGR2:p n^˨͖L'= +o#_C:P)tr(z#gig )o;(}PJUsfy#;rK;.*2]T^.dI)T\a&;(:}|07^ׯ }^#ۈ Ulq8.}+b%TZTYSğ7// ~rG>4&Mg LM-`Y| L7ފ+MqfEcL[Ǯ_{ͩ(-dʹI{%yUrN`5`&b* ) S)P +L@V_ueݪ#v +5 (B٘VCA=H!N>=.if*%EX9q# S`0D5O#O2.}ܖt R0&1J{ZHPP DZ>7{,رdu! q+mX#2 7/}GS)+3@iDf; |)3j%X!g%m&rv٨ߋONSǏƑFlcf[/ŬePa +c (4X^ VX?&zƨ'ndi)/*Y:WEMyoO6T.UO#J{.#=w4yrPUp _,5Ҍh{^\ig~fKJt4ҵkLثﱏ?m: +䟟;T:Go _o&jFNY"YKG6c[(qmu$~0fշk/G[ +)]i$0TίB*aS)Sַ~!?JSYqX[6E&ɒR[Ȍ*QVTP1 P&AHCMa +5L'I՝RH@t +S'XƩDK1~pHO3:vx[Ҧ }W6k c(.Z +Š,u}C>HuvGFn)HiY & Kl($ׁ JoxPP2az*~JѠ?ވOT'5y`L#)#F +a_0:cX0@ci( V돏2Y)m^*肋N-Ok^sjvɚ׶A Jv;sS"W|9`pyC[e,AA_|f$xߎ=cw.*o*Բ=-o%HH  eLf6IqVZ=LN~Ob{dOc;N>>7HW? ėO@U0}=?=ܦ3Oj"Sr3Y\w@Ofە=}k6\Qj GLݶHq 2:nYQ9dy ^ 51PV1:OWӁMkb` _r2\o5|݃65&z:AoҵUy1ݵ(GVs+njT #!hj\(b^L$1UDR/KcBC -D&u^w--Q2{p^`5Pz`E;{L,:&!~̳ӎGAc%+x/+p lxX`u't +{JjdMi+.27L7oAa2a*ѐ;^lhQGmԳT aFSIiڡaxF44՞I MS1hF~E +OQ*FzW#I|5N?R#$`1ˍE9Q1蒾B"cQ .,[H»5-rx $h OiC^rn u !ˇ1kG/!x#ptՁ,#VZDqaP걦ƪHR21 gmmQ UI1I>!"q\ks_FRMhRbqS1Ƕ˫xD`eȑX <^| +wՇ*2b0B> Xj1VSIΪT”Մjف%<߱.yG;vm@Z-ݧ:z7@(H +:Ub{te;-\  wjP]S26S@o5_Z.*)5[J=sG ԯ~IS +ɪS'i trcôxyT>P||,jPtB]rJ׎œ^?<=43o[kM}-jGZUyl],cM-_B ÄR$4=߳sJF(m5o=?҅c!I:Fbhdt05uhѽm5%rM:TCk +qJ(TEгBK*PdC mctP +:Gp,=PlC2Z`#T5Z=9؜RYH~eMTC# X@S<H5(„2Y*'u7Jzj)/b.=̽BMvlbR"].2Q:q섥]Xfd롡 4݌)EeRV."KOm+SH-3մ Ⱦaʱ,L2$"^ql* \Je)mxKc$=Jad4$xT3M;r%`e0BQN@>#P@AtZ( M%t%uy:VZ9nA +v ۇO7;Mm|)w:w`[\4v&tfP;p pp|KhL^%i_AϭfωKsj:L9:~ϩ’6Ru6lF#?# +X@ 8JUѴ_6 ?j +N?.fLqN(-SaҘ +wVm/xHJm(m{ŇHtJȳtmleB:Uc2T7a-33c]3tRIMbPjhr}>fzlq`H#۶u\WKܜEXm肢뺡XÀ0`{C!LZQdY"%I1JMR׶n;s{CH>LuYMCiߒa 挦Z ՉFd"攋ݬx72w1:{OM/:X֗て co P./z'k缅hRDθrZ)) _2h8̀fB q:P!#rpr_Z +S1MRR-QO̽mod!L_Pi#[0UچE4Fp@EaB4B!sRP*x!:Q7t4s4z6Ee{oyx%\I^, 3XcC^($RTD6u%9; +<` !"6 } Ȉm)mfW7~Jz^)ŏ%Rf}Y~:WFjbNs\[0ZiI Z^@(]_e%r/~`D,26>J!gGWQNo|ʣlH`s?6ғ1;%Gcr )v@QTj0,\)L0ZP$ՕDGwRZ@S1,TD |N 8܎OEٔFïZٜ%`k%eD\ʱMl؍_Ţtډl$vVQ;Oo갾IKopĚ_[Q}:ռSM% M'G3fo#9"z?Ep~:I wcf<a6#W D1 H*O}9MPzd'/MNJCDPGt>DjbzX/d>]6>3yyVԖ7  Z-*METXS,UDh*(9f~\n8P( +o|[-ðaMJdvt%2"td#6RUɮ:+;bH7En(|2L{c#wQdw;,:LB7)@g0Ҵ7$Np&\YDm0*\hjd4ԥx/\pϞup yw{Nj{zq/AzZ! F /xNDM-IkZE[To: _|Њ& 0C$+ &-'2":6yPe1 ^:@{?#J.T'g0ܶq"8غ$BRF()CBxWY,izue٧q>` +}A8@= +ECO3NmefY k6EsR͇su)}cI4-sgrzSƛK֛FKY +r4Ģ?D)xs =G[-a`eLkv IwAYSZ"qF\݁щ1<U_61!ɸr<'Vx5cEY2i<2RoTƑ^5[G,{CcVN35`)˟VwsMD~drY%;b7-{Xz`]6}K1#\~iՔ$7gǩT(Sv<^v8>H}Vpk+5ca5L/n?}u}ׄL\ͧtLә)byA.7٧(m*WҦz_i6ngV77FO*׭˦oȁYGx Cduj9Y骂]SRG@:*ڈpSlP6^)oGjm]7=J98w*+cC {OVRwsglM (] R!W##:DL(Ƀ1r(l/i8\Ǐ +^ڔw)vf^ =뀯j:\+OT =r8:P0+ps+abc<ӌ Qd|HT|1c_ +Нg#˂ RP*pJRX"pZPȅ:MHQIT59a,KMᑾgH%TZj D'P}IHI4%&+8yzX;"Ю,;4iJ! \@V x>-/ނecI{.$\GP#‰C0+Μl"Iߨq+MS*V*|\;T7|#vL8͚rw:3Rɬʂ|]շH7]K8,Ww 'xŔ޾}#ޟˤ2 oӯ$~ Uo֙oAdc<*B _zYLфF>Yʢ|3_(13չڿײ6ݫ=`0uCggxSLT6ɔ pϬij%Y"ƲlEr=Xs|SLUnlKىu5cH]҅.Y,Z/?S7uS*2 *`!b@mMuJy U  ܔt5TC Qői 084 =` rӾ"ayҚҝbn6X奰gRP̙t*UW=y vA $iQr/pxpU~ڧ)'O@U .]cAJOB|fX&Dc9g}#@ (` ٺQUm]c\jIɧeO!"CňU5ɉ{ha9WbçR$LQ0E]U#cJb~!٨VKamlQptjI=)Ryw +YS!4xªs::5Cfz^S2@x8}t3+p +:m~;-Ϣ Gٝ"`sع>޽aJ*uRTJDj{@S~~(2/Uw>/&l/@/!Rb.Wf1ͼIe_Onu-[GsW B`ȹ$ / Mvu˲u9.mZvݔ㤅&h;%k?]]//?浾B((ֵіs8~^9K)X:,eH%-;ߴjm~muܡ< o7׾vZ"٘[xQynd萉qW0$a7R-U_R +u Bt܈ARQ%(.HA='g6=갃cއPA#XQLIL$͆,z^b(k#,' Je(4,JP!!nƱIw%:lRʍ %b+(FkGLW9Km3 + UB[g|Sz* \L9vM+7^kw}ŸCAHRtHk]V-K;ǻ%D's>-$qaw0M$Lr&T*AV>Y?dWm(,{\T@) (}\~}o/׺RH'B7ז׺O+6b{ްv [zS KW^]כÖm;9FM9q,UzT(IV%M-:v,b끌aY8o?%yA%b1KeRbuL#f@ZБlm.-Yv\zv3SUHoB)#PXf*3gFm\+}#@'KL9!G8d=w0J 3 :Ru3}LmKd~:u.7mnk+|}Q}1+7+aL9qP|JGjEҹ<:WRsqLPE!ۻJP _n<+~pkMwwj?*2Y'G)}W${kZ߹nk܍#*]0A,k0yhˋ-tkn6&=ltN[BTt7tw<$)š}$SΙ6sglJ"cZrI3TU [<ڊ/eƀ1/ @)G mJ:΁!MٲXn6{I&SJ!Lz)WbbeSL&Q5Wf J Yu=̤tf`CY +Y|PS°7TջmV ƽ{d RVE䊍ܤ*'g:d𫟇h%s$"zV3Sda,Zh !a`]v7^[)D+*^RKi+R$URPeZ +3)?QڮC&y D{ KX%uf4a N\~Nw1#߶XL))]-lNo/ J QH@iqܶR0̎[pME)M~rRaHZUkb`H]]?_ܹpm9pSJ;U\Sg:^I(%~>z8;`5$aCITo_A*Q0A +d.~+aFi3-\Wb-f\kk2g]ˢJg_+E}%V JNg^^)9q(3\H=QFèp< RHRr'0-dOd4<}.D?RtJwU0ȝy9r2_G|-6iRMDZa=:Ƣސ0zwn8<^ֽ/'U +\-=۩պ34Jj )ؘ8*ɚ Z5M[)+,-T6 eJ)[vN)TiJ=Y{"2tR}5)ӍV(j:T<*H$R^R7-|RE>T`Pp\R)F*'x1$ +Ɓ,$n&H/:L~dp rR)y{2 b۞ajҴe<# RDO(8:@UH +!st}rjKKUڧ}JJa 8Sp$F(~$c}&Qkcu> +U bOR@)br՝V"PbF,PPO2*f\ V^+טT^-,ܒٺmQ U~Li֐j|Ӑ2i{L)J}J3m,3Sˋ)m]:uR:p SyQRRn%14LPXHu% +hrG p|7Ewe[yY(4)c`}s+pRAuWlt{.Joc`PLeǓ*=#SU7 --㍆g]Hi z]6ՄoY5T8RuSooN<~Gyry(P%RJ!jPZ0Iy +;ll8ڮHl ]Jg Ӽdr!ԤWPVbYa}9SgP +) +嵂>7U9Vph8q '\P( $S*" +W?O)T~_۝ kzdJSO> |~u;E|e4$g|Gd( E`F (b@)*0}ijk`gzՇ$izu#zrH-.en:>$+0K~uM5ԌXOjQ/+\OJ[[-'"J7*YTl3JQrBU&U(U p+HlPj[YU¡tJ҄ƄR:q\GߙF[bx޻!E˱ tQU(L0I$l q݋| )W +e9F4o%F^^@<-7 +,G7znq2y;Kp(؃iP}jT8Lq>"U둧Io"(^^JdwUŧJQ(TXq2Bq`R$I5 +Rh 2 +DGT|8Sѿ::_2EDw}cV޼PؔgȠ->NLS.%gKՒQSeWYPU{S~J+)*M M]$Uz+nI.of҄RCǔ@|H{M&i t%PW):E&WO)RPRzJyvBl14M9Xtxt(HGdVDe'&JO&)9Qp8h +}B`@cSjoI㍦ >)=h9锾iO>%@) I +{JC #dǔAXxS8g ˒eѸWյZWKƩwh" VN|j1E*s*!|/Mt\u.m5 V),WQVnHhbKSHNTUJPW))[FfB);zR$-$Q \SZ{Qp ;T| (G?w8?uM_ ot#;_ /R +?^*(P w6;؏Fc/ +=L&>?muθx~zg~._XhElz2D wc5'`G8үfs[:Mn{$sө>yꑦ?1^2/g:^M%Cec7E% QeGĘB6 rw';LϷʭfL TjRK's$ M0GŲt\'p&=1{NVw0D*JR%eUWʊbFQڌB΅o*L̘)$@#ѮӀfU$7Ol"alc*XD^VlIK${\Ċ"Wteځ{c= +pTYx׉GiN:$ + p[io-ٖ!h0X~WrpN%9%:u":5&vnՔW`24kw &sBɎrc຦@8˶?H#f'?h;t (mf(kyٞЃ4X8O,[cpt<P:1I{F)DWuu%oZ:j"T"ɞ$tW7<{V?G3İiNMcFJ#v7;egB1HU2:`銃qΓHU"$EBbKPzuΆ(jfxᓝBXF[xz<>>svkZ 1.7C#qj$6ecSNf't%Bf{0G;K|SBדҙg05_LW*&.łX'K _6~kWJ՜R;,C/}Τb$ԓ=5eגܢV_MĵXTBU2apUH՗K%i* (`5o&H( z TJCVdoN'ˉsJ.Pʃ;+fQAdy&/u0(lbɤӣ#RA KN_tJ|X@sMt=Z6)+ Й xɭZިiRMsFMז^ZŦdm$m\ݒnuՂY)mX(1T4 +x>U"Tj뼴a.'6rv$mR,L p<& U2\ 2Fx΁@w6ǷL˕jj[c$Ɵ|<@I;EkƆ]YZ9_Rn{Mk#%bP)$AV䣏脐`Ώp*ۦfXz<\. Q$Q* Ɗ Cםӧ3v6d#ImEXnTiejyThMv͍t)iNI@LxusеTD4L'uJ) 5SpXR:.\1㦎nW}!ѝ Abw7&FF.[[/3h{)&;㾯38qb娖mdwKD+تoVU%J)I`{<͵haB$&{/ݗ={f =z9`XtH2ےjE't`kgCjz?,wesHG6bqhgiX3 /YɃTW̢rnalh9#Z ^ٻ"wȭT"TEZUzm,brU}e]/kU$YAS!tg -ph:_ؙD?;m@ݦ&D,I$$D(ݛXj]N|~uq|qxZ R}J5Bi_jhEtuɸ^/4{31Ҝy`J!Fv\ϘTܢ9R8X5'J[D?jktZ7P*}U&9SZ%'UWyz]R{e's=qtd_ 3&3UvO!9S,ɤzl<U9yblꨢYON*'c^ҁHoy ;RǏ[a" +^<TZ( !".gjȄĻ/f~쾤:RFM$ ١ )$'̆$9!AMZljzWVш7 qx>3 OXخ(X/MKV,t%N#q IA;) + 9gi^IVQٞ& 7UTѱJYH.(9oqÖ )ͳo X CCBg] $nMW{}c\Z.{։u]+W+>WrU{0OV*h֕+rS_RH)RP8N&{"$FRȧFn "~.pJPC("RX}['D\}N~_dD#h*I"h4yt?p;ZH<;TӗUz@PU?_/(-N;,XX|*ImChCYJSf[euVՀܴm4?6zkZ2cPGwJgnK+eRѿJeb_Ž3w6jsk,{ڪS@ʼ#Ϻ*vD*ǐ`Xu`YP]]qOȥ +2\ +**h7I0}Mu-%aw'=!ōʼ-pv6my/a&JxLYOS=ۣu+x|M$=X 8S!#lUd~6UCHRd0:К!\}E)]E +=ٻ{V Fe:<#Y_ NNu,h-,6 n-a' +Aqt{QcOaj()RXjƑ#G犡oXj*5GϬfm6\ԑ2Hc@6{ n1CXjOhMj A`+0' Uu@ȦmJ\TXjB=Sr<7;hl8 +^ZCFB iC k,ִ6{F>}4MB`X\&!(Z)uXk!Aimm]g-K; $oc/ t͖AY@@ì%F("2e5 d>>GPoc1}L]_sMBr 3÷*NoZٍ5}eɸ.ᛐKEQ4xhl.;%zݷ>oWxJWh署p2ڨ株+.H 04!=\K]K6kՠaR`[ZbUxּ wu:Zhb4IJ/uuG|Ie[,wHE~|Eİr(Q$%D'iERe )Yj7_WF0׾^!]/2(۬cKC #pց!4UR@gC"blfSJ#G1Y 93ZIXbRF"BҏQ%/ +K?i/6](LEX; |G@N۾}Y[l+BvYn]hUUd[EQ/zA4 +*ں|whx޵O AeDi43 ,/j.ܮ8:b89/"DgR:[0ٶ}sW6׍d\HiIPʬ6bcURnӉZj0Nڼ6Lǚ yJzQGwi?DD믵w0:͑_$ӯҧ.ԋ)= II6_>Rz2;Z$#v$kńe/Gyb߻? yS_w'vN5Q]ƚ5]JVkewsկ:[E(8MG4f-[EXur$oVzF;0v b7[9T[i[v9hvW9{9{M*FlE-@a*,Rz0bmQIcQۤQlcSb<2Cukvڞlm[آ#w"s$o\Y]uYٕ85:(X=bewpAs|"%'|&xx3(#$\'vDmĂ-GW4ZɩfѦf^Xr)EV]~5je-ϨyPŤm:#+6Ҝ܆ЄĸUbٲ +h!2PmUj Daɩ8.hI +&=ӰW4T]"Τ:'9ٱE\1UX $醚FbGzPCWđ扣_m#8Iђ|ƒH /Id[e;i(/}.hY$M,Ƿdk--M]`밮nKj|1^"-~8EFZZ5g#4[ok?1(]vQj_J<ΌOR_(ϒ,h7\Ax;GИx>+4ƤWb|\(B29w.% R*LnM+%%)`Y7nyQaMcJdQgmbGټ~fcSo h&jZPe~Bwe_?:IƼ+Z10Zv-ߙX+Yc Q@/dSKb֪H+ Hktl8hEMgjVP>s Bt۪x/TBgpWՏ#T3 ͕ +q'eIϳ z8tF2HJcqp7eeJ鼚4 ;_VH"w-֊"_VJUn)˥&8^]R_|A7ٔ6 C5[U=#zzڢ)٤{H5\s%DP|?r~R33JrN^g<xA@c+6 d4zX3UۂVodDFX=b;q3wmD,2e`r?BHj) |Iݗ>R{@JԽ mNrrƤTPAЀPg}ZcM#CjB+eaBMT+9ARhbQjвd؏O +uTAP\[jղܖ9DCSb9#RFR,Qn5Ԃ"=);d`*9:%eju5kk +*_ +Q^(0zۨVPѹAĚ஺H?YQqVAYHE^bN2(Kg\*68 =((e i;q +.Q(sbʔR$g5\2)P>=1.%O5eR܏ UyUJjl=Pq_SQ`tRc gqt `>,J[4'rR^Z*V.JR[儃u;EO+s@`7"BkAe;jlڢzW^]BQu'&z*1ukTSaZ=Lk;hj%5GȔVؓ8JRllMHkpfY (͹XdkQJ[ȞVVjw|l@ Rm5@xǯg d:pz6?Y> +jSxXZaUIfbOMf-FQ_s# +yEQ_rƻ,2ޅ<*<d:u2>Y +hVbP ^rzc=*r}4)&+-r)-MRv9c}GXMwo\kg Eɼl\3c%3*)MFզR h݈Z;eVA[r@AL։?ZkPge15}J$k _l}ρ[9bTӫ=7(9QA:N+wNDa;KIXϨRcO:HmQfo(e&Ҿ#S ;!/7#h+}.ʥk-j(k,OԖQjnGe8JWU +(TiOs"룬|o>hJ|cQz].&JXH)GZy%Ο68lc 8ƶN[6!i mvN;vvg7M;,gMRp}tv7)]H}^Fu8N_RͣXHy?*Hޔ24~w1WD7o4c Z U`B_=?; >#-I?%gneFKRNYbv^;Jcb3ZB˷\cuS9j'M*uGROPIe$'Q][P_]E{T7TOLK%ސ85C,dۑ;To!(nLlDxmhմd'KQw?ѳ%6!sr>-lGBQԩa +QfȨ2zd&FX,555u45uZ觏VPAP("Q +L#ƪuMNJ=Z%R@ҥ̞ P_!JQN-eҬE3&x]>2@P'2s#BVZJq#54qR$YkPqeGF6b|I8.'a*}ӟU*S';^ !; +TJ[?E%\@-~]Vv¾ |C GeG<}D%\hA0Mˁlo>}0з?kFB&uCtJ e&4>zJp”èq=B={lz6K;Z"ݔzN(ih|1=2C-.R9|'P|B%B%C+jqoe_LO3c,sR;;iuJMS'M5j::@uoU7~AΓ@ +#P`GiKPڙwO( |CS (ɱ^z&W[V ͌HJ/PPFlêψ;Zg5}QƎQ{ieXn,պ^(LMF 41аN)1: ):?vbA3( ~11p@_J>/3+Hp Y1MjqɛRxմ 4 G5+Z0 FI4 Z +XԗSLNWc jorR~Bȏ͈F-M݈PͪTKSJӾtMRT[SB[Mg*šK8K6٧a5) >{R(,+" /'YRHT +.޻Zx~Q +$|Y/ݚ-bKHM5ťQ L  4~ +Nhpb +s0v~?ͱ?p䋜0.&6эsi~NحmWZ%iyT\Կ) +!oM[*]+HU(fY auP. uty\Ig$ʻrm[Uo6G⾕j;ˏƎSlc-Kmv؁c}-NK꘰>,nV:bI|_kgg/Bb>|t McnRCDw,TXSժ8vZ¨EYaRz +7DD@att>pPvJhܠ3D EZeT/F0Ȱ1)F98jaSRWzĩ'OAہ-Vz10)F‘iF-i +wpBAjdBɦD{@#psή~m!?ڿ8(}əqanLX@.InMG䯇F ͭ ;}m]qEI~ʢ$E=-'vCbؿ_ +ˆmXdŲ8zYf˚!Y`s%Q92-ɤ#-8 d>p?rL0C&Jl@iJP +eJp`Y&Rq jw_Kפ[}?\M|uXWoW=+T>qWnkp0沠J>SZ!2F9!AP3=F]L@DXNWfuv,&NEDm7fUX"U#Z5j\!![RF wbY +D16_\U k.5 jz OJJܷ5drG{(X ,OU wJ]$֘Z- F5%RӤI|~?*URpǜ^!MֿܰyjkHi#a_d G̣##K;q.Pz|]98W]"EiZ@ i۔0R|ĸRA] e=Z1o`σRX0(Y(QWJt|rR&" +>(b)5VГf! Bg#ptT 6m9>fb (Ou`0qG >|6ڇ/^?}"XF}jU ^'SkItLl,53 O+2tsdiuH4@ sTjnHH]84|jR%ѧTz*U9Z\2KY6@+U +JS*j +ׅ]NwoԔ*4RN~ + +]7G@GLan!gc1Gm'vR樓GVJY(rR)7or +NI;j=JǀQ,C@§̈́v?# K wT3)`: +Wf=>wCDHM; z]:WjGBBXuHzJ鉦g蘦HP12V:5#aԡṱPX`D[z?Is01sImDs& $(?q./p]qZuCS,|lJM(ݥrUZL$9gUFQ,ރQЧ;1u<"R5eE,gvwfNǝv/H)N_5{6"i$z;u(}jR"PFvv7pLvGJٹC}>ߴ-K::[XT:ٻ i­^{n/Xp)Z 1`/| gYhJ4E<z' 7BpZɄ7o/~sr޵5i㒺p`uκY]͊>:O3>SWͬ)5VqrcƦfa%ɧ|Fͧ|_I}аJk*+OSSzsFL}U_1e >Bu O{S~s=2Ni +H,i{P\z,AN*y^Ċ$rMuP1<Ԫ Ba]޿,އxVKˠ`Vpgx;p.kR9nJKI.ѿ}qkya AJXG ~vo[| mY8f8/|KhA;8̔ f„PiX~1K;ljEMP8 +eyv+8 ]k_뭷m8d,Qn`E"rVۍv^=yplJ)q匶rV?:`w5@3,G(z@顦>Ԡ-z|bJ2R%'jyԼLo3rDP}JSquyK;(]C. N#hFTSAV۪pKɉm񷌶Sj"BF(P*Nn +cgڵdyA4fF⩴Q̒hQqzi(b~%M_(m Pj'0<X^Nu۳<=,bVBz$L&è*WG ++>.ҿ2v.ln?}7٪κk_,;s砦A)t.0r8MAY]HS5^ɫȣ7TBf-%c ^/}J@94ԀA <~ԧ +( u(rO=hTTo[XSJŽL"* SЭlj63,ΖMOJD\Yre^QBZE0=ɡߦ*:n*wvP:UӏдDƣ4 :TS-وQg9xEakY˗>2>J>R>JQP(i:s:0$(DO KZ<42AuX/p+<qveY[YVWKk}Vt(*UC// j4^0*y&f6W6$rϧK9b|`VE$Abiuh$,!41ɿtNiP*5UiR-JMOm6iu(K\W f&!WX%3e. <)R(̢Q*m:05#zG*UI#C լ\LG{4Szj9g{ղPڲ&A)mZF}ζ=G#c^SSK9Ĉ"e}c]=_+CK^R)OnEs-^<^9.hI=JW%SRr^[-@_b\6өpS%,G)j׋^$E{`ThCkrZp*p7;Z0}kLJ HW@Sq[uqt&4KmbҨԖ +/ȦF26SI4]̒i˦%@-TYW*O5{?8o:޻m66v9j˲7i9"PX}P=J;mFS7=e#X~4<<&Kl>%4^ |K{{t.tzbt;VݎO:׻+[g,+d/|x&S/SGJkWNTKG!)jk%}m!`J&ls7k*5`\EaD*D0S pNJ>RľTr(5)S lRMVR5MeuҮz+5e=M'ipPռF\+ Z*VX0byI.yRHQNEB- UtITa/=Ӊv}{y¾cKS/NLmxmĔm;&:.73 IWWן󻻼e͵ۑJH0@Pjhץ:Tz'uBHO8{OiNvQ;:ظvmnKдL8>ut +^! @-qYP:X|yEγGש~.͓H`rTz,.i:ܩ^]8MЮ\RE˹T9+vA( +*΄z@$JK}J4Pyx4+ȩk> KW TM*Īږ*ҕN J$i{bp*RՌqQjjbLSryIQ %YzR67}C0&)Q]^nvcc޼`_;O? g} G1_)Gƣ$LX/G.YЋ$;1;>>h-La5Ƒ\q+^ZV(K:M;iY=J=YcMlj7왆j8ezmۼN-VlΖ%&iuCڋ]bw.{2 d T[nIK us['KeQ4,x@|IJ4il6Gbof_~\ꀡ zo=W?5kUZPjUZ\5U{/ԘqaJs~?a|Ma+IK^&&lrY_i͌ +^P,(wDy +7#,:ɀ+BI̜`<#,OKǴt/#/ $MqsףB'1&zbX={J] 3jo!ޡZ:*x}Rf=$nPDp;)Ǟ7|&3OC)M>' +Uš2.:$Pux!]_j|D^-vNЛoIF P +q5T +Jj1 )VJ-]fr+uٕ_y'nwnkAo}o݀J`Ѩˏ_;jjԓ{*Q2uxmֱfe,Dl\KyM6+mPT, IiF3/.HcD+)SLydjSSP MrZDieMpQ:it6ivJ#%Պe M-JOh&3w<`XM_=o>+3ULdGJ") +sƅzE~OTV<5L S҈R `i.FhDz =Q\$\6q곷oCOFl{{=1o(Q[jo(utGapԘ4ZrMG=#&65L0˅V,=m6[> +VҌtw^P4;YiQ + uOiae_)9c6FZXOK !k1+q+H\:G V#6>{A5U0G{P: K)5}[ْܑC},@= d}C:rPe4J)M$Vx"&4jj&n) JWYxZ,?vg,'(?Ƽ^ZvGuV&FG!V?)4)sOZV*Nu>r~h6cQ &'جVA8\뱴QGZkֿS;ϫJ ʝjKs<ֳ2$͡ɕ4ڧ!(dAeMJ`-dU*si5!2Q* f-Σ$nSyB~ZASJjGX31.ēaf>%j;G~ZaO.ݠ&GDvWv / $4V㿖-Cd8*@c$4ѧŃZRhPZB80 +%fJO#< +NRC=~%@Q0l{{} hI4ĈZ$jTJJ Jk@'`l֧B}bK.n˗z +3Gsry-6QAi쇛ĮeLJogdJ Jfd䨁蜀tSJ(M2#@e`ҕM}I!7wG% 9TR܌$՘hP ۉ;㮒j#jfB|ޞ23DU=mt8:PJmm,IzMQ7/Lh͠& ҹk:MiIZK2QLtJiK3@r^4wrypYY b|])`!!uv Pjzh:ZX:FVS׿"ƽ ;am 1zKXT;gBC·n.(EJJZ\IʫqOָf"ԃ8V9>j)CS>V J&SȜAצŵpȭ%a5W{RzMA4]^-P5( ډpFOu4`kNyT>V: !ޞ8K86$`\{N_vNi?ׇ6I- &IKNnsHsuCf0qU =WW*tKUMRrdpfäƗ (+JBiB.Eh8Ph:"36bZqxm3S-;ނ]wպe$h0;'=ۯ]j_|1vP?/BĹvWSCȼML ?3I5>bP9ͫ%JS2P*߻'ŵD*HLR. F#Z,,gW5VDQM"QxB+eX5| l ̅;[ NJgA;Ɨl dKiwqem9BsP:M554Ԭɶ;)M## ~mM24<њ*Wm=2.0G߂RIҔ-K{ 1|`\^aŪH7•7R,V]թrΎ󼝐8h*[!B%|DQjIXCO6/آԘn [}Upfv0DfwR.׶@oAҞ>zvspzn^F٩ӴLr;cKZ^OOR_zvK+t*rź}Qo%ʼnYJIJ/ΡܜBT[ى1X|BIVهTWȃe7|+$g_%;-CFE),iQ b.9MQ+"$(vJj ILREdrZlT2 Ա bi 6Ea0XgM7pJݒ6΁xM0G$A5/ʈV꾐H,Fx=Є +h 5U|$T0Kbdt#,۪㞳%UCMnM{I*$BhH,H7H/F §ff&Q 9ŌשB^f|̄ϳО(?(V_Fz(yItwwQ sE7:H"Z8 +s(oIaIŨDJ,!}(Og8ky3C 1)>{58$Ur0l.imDՂKS-{cy)%A,aU 5 .B$vFն}vG-3"4A#jX-1!=}wQ̓yR!q9рMhJjRUkX +_UB̑7 G*2nTTfT)|NpKb!ʖ!C T w1 'י*ZOL6ZԑmR +O>~G35(s΃vZi_%%~p{tS&Mô4EìhnosRzJoߺ>Y J钚Nʫ42sJ6. )l)Wbi e_eAJH'{)u5!€@Es9%7&-rŐv*c9D>Uf pč *ن*d,JJpC牗15 Mԭn% 'X;n"tj_N!CCua cRC Sj~M1 *nxK@:t_T؈ X*mo[ŔPs9l dkvMG!1 _j|m{Cjsz,yX;O99'FpggY5L2t٢ˡ1bJ\ IO섪(PB D5 J9C(CYiH}5)v7ٯ6;K.%z>ˇDJ"-;Ah(r{i=c !rK!GdQ_DQlb5=-"%fHr`[^0]$3yTj:i"lFsti}|_mc=|:` +A1SR6ͩ4S5B:/c\PNƄlR)$i/d ;;@%'pju'h)?g>qQ,`o(Bi^K.RFfB] `$(ǡ^7;EK~4Ni3OmNp,z]fcyh)=ZqlZ2nIA*8JH +1u#^ (8!H`b.gKJڨ:wPz Isͣˍ0JUMǪ J%A6jP + +I :^HSղ]A=vɩK+-3zEs]KRŅ^qt.r#$Բ6O:;;H. Z$"5).¢7xռDRoOR 攁hJ)[P>}HaNP?9=oq'JiOO>a>v2˼?UJ}xJ!tv {_w) nn_}T8gs<@$ͣmvjz2lms—8uI)􈞉k7QJAGMq4Ba%%Cv`.fp!&cޟ ,RzΣH 8nYZh +BnuiI?RC,.brc0I>浳oBLQn#?y 4Mìq.\"NJiH0 -Q=+ٱPvLȏp<:,TW7bm@~{C`[EnǞ9aJb{O/{_R +!ڇ`Wݧm6;s;Ʀn ? >'s=۩ҚNW7b&/+ֵ1q{NcpӔٸ>3`!&͈8TPJ) ap=šZ&7nj)}fDSh~}M7n㩤~;NҝB,EuȣKD*r)uu ¯OM e"A4n d=$r(5qs +S%S(jr"sN+glK8Ek~*(yfBLn,@~Xd|ZCmm֏ٗ!cw-LO;P)<;Pc5A-馂 Ge7*OitX^_!n\όwlǼyGۘ75ZaqZ^T'\bL-&Ÿ:7nNiRGS<>`k:Z2O0H@;Oi_PAzR[vWG* 񴬲 h!O+Zs)FjEۉX +/ /z{ݝ{ŤER/ϨsR:&d"|&*dbcjsJX)R@0j\R(HvɑˈD[[<dTjV؎W|\\Kʩ$JETĵL  TcL]IUSD/Ib[B_Y3Wh*n +6"%hTf8FL'dEM!$Ц/1(2cAac tjsi|b.p^l H+QA=ҴGwdz0Y(*F6+QlMa*p6W6=ү2WS9XRBcDVEޣI|ĂWjU ըX(01f# JqD>hy~rjDFcִM!7QWqt]8ntqTJ!:z)]m=S5=oS.JñqǟJORx@FG|wZKX%͋3外Q2Q/J :bD-)T*5SjLCcGeܒq<&7aTwO?,$+?A_+IZÔ&P*!",V@L1̕\TڜO!ٿ*|AG6Da "X5t"q5[AEExNEU2xU<8X?^yc > + 𓮧$@`viw7)LA%m~ٳgl;KN:t>VVO8;:z>ب +:T)CLp0DE\")*sKC*G]D7S*H|9=pbB,VRQO߲"V枷YOB)#Zq_@W!RKJa^, i~3Dnu8-gԴ:S Д'?gʡP㹅2!#6%м&ٝa%TXpRi>"e|P| PFf̾ƎoIݡ:Nf;Pn<u25AC$1ۛ C {'ҽv/?!oKmXJ' Yֹ;gԋzrB[jŠVQnޒ>-h +!ƋaMR+\5 W4\bŠQPMNE u66u5sB򴑄bqG),*\.TB/o u+4v[ +*HC'RTG%M% <Wg#JdDN¸(*㫲\RUxYC^/ 蕊($-l6RHbDoPYJ)}>gj6d9kKYGo:tJ$ƅtQ ޗjH7_?+Y񑻙.qQ(AP&/b$2)"7l/m - +[n 뙢[yO{̯ŴY#o`ԳzCm6;Ow }Io{𒴵Ν'^{xMN.t^h}6lsb R{ݸ=yC!҄Sӄfz`B2HiYG]I$ y弅!MyB5~pEH/2>x_ M<0y-sR4FW有mɖ2mhUCRK7EX%( )pMb/rI%]Xj%`(}NNJ3ńy)&WTx1jL\bYHB Ɨ,`KHs}TVtUP%1d6P#&Z2j@A:(Sa@ܣqHM[=)Ѿ:Tב<3pf̌R?|BLO+騔 +騒R!%`IGIslDˍ!"[Iu&.ユom<߷ߧߧvw)߳ .@v<'SSdyЀ+bcg40mi.=@o*Ru80uE;)tɳN3 XqطunU+XbP6u&"*ɐDkMX]f?=@N`9 mQ덇WJ ~6B ^ӥZ,DUKAУ )b +^5V%KX+ȢL% r9$+ ;pbpU()Bق {F<\)!J{aWH] +_xeJTX'$DσzS%b) @J3 2lK' P՟=]M_0< O*")m.u>Rs?O>f}oQz&Ca&( m?gpB$m57{賥-0'M'.E76}X+9%rP6ɫbU:[6r.19M-L")P˫REc5C(9 A,sD#:LPD_nm[g'EIu<l΅D")9H&"z(]B, #-`VU5DI-:% +APDTPٲ:Z`PH#pƍsYn)M/JIC⊔X+|ܝ +8@f$j\b_LjBf@ϪGuhє!Q<5,yLӷF^Vb%?I/sb,Op[β xF)ʈF:rSI K,q9´)c5rz /nueP}nM]HQC^oo^wX)sw0L݂}pC]wVz,TzdGۡ#Lz#)6 '=\Ӏ7mDe0Gp%bo%Py8veh{νa2,[%h)lW-ҫBQy(jÔtasprbYaBJ|FnAheiEع8 -Pj4 *fRƨZ=zXH ı&64iAVr[`b7F% >QԀĉ X$VM5!EkRTh#[ǝ(=|?KdsyrocgcQ NiSf-UnIuhTsk|ݒfRꌮDIJr T^P QRn g" خc3[L_f4Ja1֦ >"Md+kRΚNDE"m-q<{!n--m[D9|3)rK[ITW_Ssf,K$2D(HpohbKSVջ\n$t72XDOҧ)4)7pJhk \ 8le/k@i(9m|D:D2k“*Ey=OOB-dY Z'd9MrS*j"/Gڬ!|}HДЧj1o?T٦.Y}hJWVtoW~smQOI[O(Ӄ#ч_?q,u(p9}=ݼ -d՚)`W*A? @sT!!kˉvRigsbC }ݳm_evg{ɝ9cF!24rF)R~ Gu4.ྟhE` ܜ7cP UT8hݔkIya) $MrR1&ӑ9EHikҊ" zn(t\f>b:Ϩ5{YoLJ). #%uZ%@ӢH( +h|>@+3}u_SAlB9E.EQpBb~5׭945zM)sc{?tbhd@̮׏\kT+ozmsz ( fKV[[5@@]lFz=~voR|𳧇p;[I/6K;3ŗ58?`4 7cԨpzl}nwv`>H3qbj!+J!&lА$t--_K)%? -B)LJPL!91Ń K:/pêg(oW` g䑄\L +WHYI󅌄 5zxt!+'ղ-O-ŔQS,|Qfrܖ'RM4DWav83@χ/|VC5#] ȍ ;(mmFt%O[^Bƺܤ֙m,Po{c2R`$q( +0 |b>7Yw[{ + l CE) kP5)RȊ.Dcړ0SEy^~Z)Ej-NfvTKȭ&e+G2iT39ANGY!r-^4#&3S:)TIC0"2:S!b +UM/ MAtEB(EYQRqhJt| Ld!~cRL, hŸ4༟O9|V˧Upz S3W;/ > >K9`l=w +#pbabfeRxrĀc"c@R(f>ڪ#z\lrC[nIwʐy9uMTą G6dcy._J3(%:mP[Uj5qR(Ɛxt=M.lo?o~骯k R " PH7j確hHt;h$"\q/y9-̵|-#iu 8XM*=R)!3;g-9dպ4IAѿxP;i*Qi*OuQ +\)XEJP03.\پE^(P,'f6~q<.xqr:=a[󥄈K+q0;ϖbw_'+^[$=4h^y:| +E)͡:1+uv!v'j ŘP Xu/f|Ou2nX8ѱ +GKYpk`b0oK"粳z FD>nҥJXwb>_%Xҗi'a)Ff7f. yq;M^w^@j_{ ~F3,be9l&4,^r+;lt$>A-DVMŘJ?3m=RDJ,S(M:i[2B)>JaTg^#+`4wO ޓ%.ćQ +{V@,Qwm!P*17TUP*R3w"AN류6axH +lEc*:5eWL4t0J`Ovꛣ8W +6i iqhи2h\=gt؉Q +q);Hbi-gs9#ZPjɥ1oLWOVM[^Jq z;\ǩxżŋ`2Իwr_fm\g6۬gr8$EֺNWi/һEz']ޤE6qdYVKd[l+n7pɒN33(r48|磛<;% .$=+} eJY0M^8K닣]'kHFYʀ-*JĠ|VWWRm>m4KW~ngJah͊9칆UR\S"e4H E)l"!Q2Fi}i +UAs0&{אwݎؾ!o><^}>y̴d`6ѕ蕎x)r WX;Q,e㐲B)@S㪒.X[5.ÖQ +a{en?~#t^8KÀ> +w*Ѫ$=& MŭU +: +&&߀vj:uƃNii\.2 e96CڜOSRdtID<@1 =!eD٩0G1LtLwrW ([]}k"u6 EBﮉ~R( ˬAм.@5p4hףݱ.8n?4)SN:ApMBQBQI7LF|qpg`_' +)nЅ =k +BCeCLwZ#=!=]6l+(baX}]-8:PN 6@L^|>'. rQZ)c>}ȻL;Ȅ{X=\-4Ee)Fi]5CڝìVIZ⥰nMh7,+<B>*EU).Mf^e;2IhGegcS-cȠєb@K l2CQqAqT89_VW0M1i:PjuRMJaT0J%F)T|Mly7Jm+e>* (7-iŤt-Ve5tY Yeghse2Dy=`ޱț]T[IijqJ>!M&u~<9c@;1>fBcYqM;El!;1t^T)nnlE.mX]5 WR;;DK Kmza:;LG1It|BPZ`S5/ryvO3m/%^UX_<%bCz :;{Q/5d}t^~[Q>U9:!{ll9+V&RSMcTT3Q4K3:)qV.b;ZA'JxXKpEfH|uK֫HW6@@L맼wUh*v^f/iҼtt Z'*.s+xBm?24b~C;b] q*-\qYu\2=پپ'ЩDf>Oe0|rP&r|Oݓ\c [?@߿ݴCN:J 3 +}WnXeIKmP;6Dc/{E~΀J6q"%Qs{= gq_nmdexsNҲV[$x@H,+!$xDBK4mMvl$\&P*Ti_Ϝ$ͦ@P=xL-9E^&0'xpZEMQ(&uF))(@ qC4U9 68~ &6ke0Zڄ(Y=Us~wEUɷt Ƹ7XY<* +ƘVj~3NkܜLkg,+8#^IFKY%86H1R2ZW[FiwϏMM_/%#1_!+9p (j pZO]e]rvX Q 4m:C P8jln:O60 t{D?}w!L% C_᰾-C>#cGxgcԹv!NbTM*PwQ*2!N!yrvvIADa5u cѧ~ncsn4 Z,[{9 +B/+)`QZws)q6< a@)iiu4-f9-B!#@WҴ Wq*$`C-("an~*d)"LE FLU +Vez7OTUd%802=/1:^2E[e:]uƃJ{pܫ{Y,^D=M*l0ᦴX(Cƀj +9=PY,"qJkQ0bZ4 ~E|FOp=:7᧲_ҶUpjfeCt9͖=\~Nà:?lv?#~$;.7|EN}Dz|/|0Hcs P H5 G4p=uoۚqJOùRąr~a@C1_3Eh4=VcMΎ VKB)iDD4@ iYӲD J`(AY3JG[(Ueg_eDYAΛ4 +5oS*̆9iԂ@FS ^rS/rƠnZPe8g 5YZ/.(C$?*%5P0]Ϩd1KcwY=vmZQo#vv`k:`0J!oq]|u7{}"4ںDzη\\upց8Zk vm2󩘗mX,˗N F䡜nMӴnfeu`&G{ eNm5g' +$ {F)1l ڛuᴮkl|4BJJ8XJdF9MxQkEزOXY}>bnsU'6Vtmq>S[(KRVQ.gU01YyĖTy$⮧&d#q$"Sp5cʸR0TD8JM΀Mu +\80p4̙/ʕbW*nKo-ք@e2H +TdjAU@Y}CC”LJxOJ/]+M(`-$Q;sjRpʚu(hjRii +dS)T-Kђ+0ց-|MఢNp6Nfԝ;?TZYs-$?OrI&Z3P*—!>]A#6b&d_96E%@T菘!Wfs᜕SMIi:! J:u95u1p1R7j64Lpf!YASȩA 3*A0/˴27%NƳ"+"Sp3x8-rKtoIMq5D#>qqu}_mM {VY<0wC ,(b.^[/|ۛFUct=}L6(cY/ҽDZ~Rtǘk.F_פ'& eҁ,v;.GR3gTc,SK/ٜN N)M 0@0(GRʦjsn7y~♧3p,񝵶 )$ehTUv} _gOJ)~_9;L(}DZ6r*-ˊHӴT4oTAeP!o.cJc)PZmGiв4%TD/A)cORpEfV@0s(R޷!xu QZ/hRʩlۦ*xo +^D-؂@GR+8g.{iO 3L>:I>k/0lx{M(F'>(|` iG0SŻ7X=2whx~0[W_:E48r\?**D9**"nqN?vyzmGjt[ ʑVoo&T\;.w_.>yt@H:搩}dV> jp>ß +i +mJ9jP t1ZD)4^(6S)L#ֲB(E/ GqG , SQ*绩 )s ѳ.ʾ}) mAg (} += " T3BҞS) vti *W@GRi= \7⽤xO%QQuتRF*~"r\FŢg1`÷m/nQjjq;;M[JGRFPnW֜qm-ۀKe}lk&qQY9^xWkaW~HsFfs#Hrz 2UáنΦTA jx5%Km\IRO+"!r(ojjxNS +f>m!B~T + +,@PGJA'8 +A*P*_ ~1̯ +UJu >TwAmrMQѷK?$}UvDA!8dvQ.44(HS -et>c0t&:/%O%ueݮiY@4693&F=3(9ro%cR>%+ѣR!$R5Rv|awO;EDoCpdGRlsTvtirQ፹ǻƇCcȐڠ42'xj@* +Qkƈ88iU¦Τ)dSpԊ\1@ثW:+U+F0ubP#iؠiJ/`JQ%.޳&x}ёKohF(+JY-ѺQQ\ua1WZr & LKrIvqp%qo[V4vtJD_!3@VM-dYJ%K% Oy. A/9J zoTw~7 ׻M,KX!ZWCMi;EhSw{}\sI ;|d䅎׆C#!eA)r^Ӵ*%RՐj:*LDiRNI(nce;@Bkfj!UfuQ"ӒH-O,CXHRV%bE4+f>i bW!z2XM@\uްjQiј ~LsGg0p7]*, +}©v>2A.оNf$/Ԍ8&D)eNC»[ >cբNj@%Pa~p/J[xN˪AP,W{Pr7ߐB^Dix^gt(fe^(u+\3I0Bv喙17wr jlɃ;>O&o[;BTAvCeJAE*eGM`:6 S¶bܓeJ]\yA P䬍ncU4EC*QU0- ĒH"PAS@P(샣D˪2'،]J!t[d-N_RV8i3I!ZȴdJYi+[zM@.CQSMi4HAXi%,|xl`Gx()pVo F[7u/Ui!iq\ϩqzsLjRhOMͻX&Xtlg{Ut"Qh eD+̆K7r-Uv +MOvwU[_e^<+ps% ENa(, aiRiUGa[TT-/]LE0uEM]l[YӤ(l%PafyH#BTdMMEJ!%[WRvV2%wsGS8Ğ]*v'KモU7]Nnj8'3YusV*i筦y;A$KUٴ(g`G,qĪhZL+fkM +@:Sv:m2y7uV9RknUAur刢vfQo43.㴟NA6Ҕ4#6uW|?u%$]w=2nI.ٌmC{-`b>zkB1Bvk'۹dOco%N];;Ł RPk$קOC|ML`$} Ptܹs{l!JSPG莒XRZo)jhqV=jٻs֦K|?% X3 .u0hHm!΍cq?1=O|zHЬSRMeJ}J(T]-'T +9 +Niڈ9L);Z P DyY();ыfӲXV9T(!}e˒~YwyRm*/_AvMLȘA^w>"aj I^v*(h 6m,NuKAbzG]ئ> w~wԴmPmcuy\RԵn"2:qR)$Ua)Z_v67-h?jtņԝVbU(#*?_A5-+`eTy|?eFs?ic>w8)f>PaR0N3cAŐ4.f~nOXB_fmg.EDI$w\"./Q]7MQ0H^CR$A'umGRdI:,M1&EIڒxn!WkYn-L#>,fG 9o~4;C=j>;ײ汮UuUUf'gyy+ย9= u3C+R |0gۦ;/dl..Yd[ +[T23,|pA6)::rU l)`P@bjOAT;?kJڀ=ÈC='NT(OJ6ÝFЙ3W4JV_jMFəAJZ=i*Q50 +],*E`(QM%/?۾AGs?t;";͉'7 HិGg3?~-83+MhߍD<MJSASJS|$@@iJP_pHӽ-))8%(dvNO/ ] +K~ng +}z0J/Yo{J +S1a(;$;'wI]>./%\sQa.ħC g\>z?i(񨏦1G0" +''2mMʫR6l՟+ֺ6/Fmgtu5: G߰ +-0fduʹaqGTR*PЎ( SSJ"\&\C)F5 @SHXO\ZEkߝYs&d[6.`T]<  pA -Ȍg.V3dψ|ίӕ;RTBܹ72jTrɸ01s!ue]O-u?{VwI0,W#~zm2mM[&#U(7)yS뷷| +wASɸ1l(t6QSR@5QWi QwMnh-(GlN&ř 8e;Ff=UƒgGT'v|ƒ>ZׇU65g|uzy!&IlL cdȑ +9B+våy5暗RQ0YM$U3/9YȨ4TkVzձiֹ^lQ"Ȅ \|*LIBJYḪälV(f҄g*M$374s'UWœS5PsT[Wzgz1a{Е+K/_O@%J$_ay$TCRT߯UJǬc#gCh8w_VQS@K90MDv|%h J  @ UEn1ЅW>49,zրO=M(iM:1JeT { -{cF^ɩPH5}zy"F~У'lUoc׮a5 D:G1P ++2WS](EXgO: 㶉cw>DUhqa:4j  ('/ȎL˄Lm7DIc>z$~!g.Š-ktLII +AlMׂۊ0U_g HZu&\X1xT+=,AI~"/| GQ +G{_h<wn;ΏO'DD{JSNU574zZ!\5b7j( iMKtSWZ SծIڕ8ItmXp֮k@!$l3vl7Nc'MG\&86ճ^䁞9se{J ԪFd]!*P7f=M:<61^zk(z*ͭӏe˲Rv)Ka!7 ge!zãtBO";bo!JP +(:`;U?YM[_Ζ˲>kySދڣcg[)rW<\tI$RCiQA)":PʴSb-nܭ CƝiUxi[gxx1b>*e~|-R u3`oXlllKtGkld):pŧSD +K|`rzpLmhرߏ(, 9V)Pþot~lF~L_^\G~uoJ+@*(R+.G)8 + rƦ^(杖[b"8458 +n5OY[&0kaQqQc'LN[4_ >68!/K!*V_U +d(BpPBrvt3j?~QuVR".϶MiNj_4#k ;58ʏSn݊{]~D7]ʭQMuf-K㔥9Ϊ^2#B413p+##6'xwS 9;/]SdJ~(=hY /pE7"(Ek֎"XU,̄ RqlQ +bW,Jkڣ5Tt:'zMOƻ~ܷEb TQ~w~i%9mtgJ|>]Gl).4ES6;_>o^T]s%8U8H]8i>7h;7CvMc'8k /52Ȓ .C@DAr/tRLzsTnfb +[* xC(8`m\IR泙bvIVzmOygVeN"+ ol]Way$IK‹fg-`w-SժK_ mjWdDeh` On+^ikۄMgɨ{]wXHK-ȚrزT;Tp~|nQZ^e*I1IvRTOaRU7J~=7uqwm̭e|#.0-yI<9H^<-@mv22CiiIl l0Fҹ)c6Flwv{V{ٯΥi.DZkf !F? 4 +}]´a[;xt^`@ +{ߓ(ۂd917y~hbnbr/_] |SOî憻;Mnw]OXJ2x55p3IU5jI 28Pؔ *tel[h VPTg.}8ȯ! A QC B0}Mr 1Lt:}čA\ = %7BY o׋mQ͍:?sg|7 g5h x]{ڏ푝 +|2a,7~<-tB 5ք]COYne|בKA؎u-n9pMˋɐ~_q45V|-~>2ꑳ<:7lt.=DDdbXюLNvO uΌtw^JW-;vK?=r?&$V<8~oX)R@`'m 0D[*,s>D*-x(*87xG;k_ʥUUhgV?SWO?8;13=3;;?37{HCZ>I&f&ϽKvN LowG&'NFTʥYqn{LejJ| +4`>"JQ甹&*# L=Qԝ{+=3فK/ o;{g9|Vrlq̉I4/PG*iAB-ʎu +('mK'p4 ׍1{WfcmgOtd'ZNl95>{١HNv2y@gZyi_m1KV߯|s3AYQȟXS(FOPdxn^q]ZU={mHѻeіn^~ȼzt+SooI^66DfK{ tD@4_3PsB (-{>ۥJAc2S(eGQS C^'Ӥ\ʒ hQ4-#JNq8P$\ٔ\ZW/t w,5Q B0B +|{%؛ +U/4}_0OM>bhZk!,ֵK9Fay[.eT (d?aDkbcc*m)ˈTPjYv]ʱ@GUr*I_ /Xv׆Kj_ʥoCMoDpK_642!ˉJqGJT\V8 +J@ih#h1wKj_ʥ[PɈMVZ*eq6x +a%@td)R.U})+% *p0r$PKP(s9cUx:$qN㨐rRKH;(XϘa*m9JRKj_ʥom"Ak[DUHT\Za ^v]āeYjl$'Wqgۢu)sB릙,*ġSX8~ZZ}D*55y0^6ߟ{)Gr(p<S r@oMoA&V3RbB,CC QOX,CßfF(|2}GC]]b2>MW'Nлgэ{Ɉu}ݼ)[>P?q=c k*it$,BQro-!i*w"KEErB Ԑ&͈05f>ޝ]o||yy~_N-[W6Ÿq9t;*CcРٳc֬ '^BYKOiզUPZmNiQyq dO<1 xq~mm!Fy+a@5o gDÆ[9𬳒O==zK~Qvg_}+9K^~973y&>Y& cAռylY5oؐFK/ȟ}6G=y&L~tfHs6Q*qc@6IC쇺vX! `9 |ѢEƤVQZڍ7&T[2!ѺuJF?Y|y +lpCҥٍl*^}uN#g]0"Op`~=;sLxuWQ̫9 4.\uUFU=\~cgS7nB\J:jpJYr<,&,FL1J?Io&*䓼N)t@+V:)m ˫(ƥT2e.XӸ4x'+YN_oa!N'IaNYe㎜ ,I1?bDb X?>JY,J:vRDqFD?d)SgX?xx; rK]OaT$1X"^Gm~7ߊ@NgU'dh߾98+M>C~bEdPסܼN14K:UQRK"O[kT<(T+bD{,j*(맔TN%l\/LA)Nsa(*4V#.LQ|O"}AQuU!:L.Qpi) i<?d_] aa6AtZ/8>y:U `֢Epw،ôi.-."ZH-~R֬5mN^vY}yT q,,d?.kdsP|,ԐwM)U!>|%`fժ|ʑR 6j93==;Iݺ)n flڈf*UbG"rhsHl)N휲e˴Lwg alkVyq-EIgn7n>h"'Ik!l|gM ф\ 4Qe jeEߋ#V66p>ztydL3fT6,w/[-㶌ܤMJCuj2Ҏl]Nd6*B "*>E|4Pn)[QtҔMED|MbU,GeEK)ڴ +JXtm8*% jIWl[4{ܹRV#^HЏ?$}c„X49`-iS&ѳI6$:;-ei28th29Iƍz.XY޼yqlYܤI6<.HN LB.]*'{^e:4"6̺wOhÆ\ rӦ ![7ħx'>EhoD%;8Ktsi)r}FdF*5Y|7kV~H)8]K侬_ct~ܲ{W%ENiJ.rJ,hipժd\mis/$ +B%E]{~hYR;dUVХ/08e:n`Zh0ʝFa$>![57DX WMκ NK0*W:`D&>CU2t]]w +WC|7\K= endstream endobj 34 0 obj <> endobj 37 0 obj <> endobj 40 0 obj <> endobj 43 0 obj <> endobj 46 0 obj <> endobj 30 0 obj /DeviceRGB endobj 47 0 obj <> endobj 48 0 obj <> endobj 44 0 obj <> endobj 45 0 obj <> endobj 41 0 obj <> endobj 42 0 obj <> endobj 38 0 obj <> endobj 39 0 obj <> endobj 35 0 obj <> endobj 36 0 obj <> endobj 52 0 obj [/Indexed/DeviceRGB 255 53 0 R] endobj 53 0 obj <>stream +8;X]O>EqN@%''O_@%e@?J;%+8(9e>X=MR6S?i^YgA3=].HDXF.R$lIL@"pJ+EP(%0 +b]6ajmNZn*!='OQZeQ^Y*,=]?C.B+\Ulg9dhD*"iC[;*=3`oP1[!S^)?1)IZ4dup` +E1r!/,*0[*9.aFIR2&b-C#soRZ7Dl%MLY\.?d>Mn +6%Q2oYfNRF$$+ON<+]RUJmC0InDZ4OTs0S!saG>GGKUlQ*Q?45:CI&4J'_2j$XKrcYp0n+Xl_nU*O( +l[$6Nn+Z_Nq0]s7hs]`XX1nZ8&94a\~> endstream endobj 6 0 obj <> endobj 7 0 obj <> endobj 8 0 obj <>stream +%!PS-Adobe-3.0 %%Creator: Adobe Illustrator(R) 13.0 %%AI8_CreatorVersion: 13.0.2 %%For: (robert) () %%Title: (FLARQ.pdf) %%CreationDate: 11/12/14 7:50 PM %%BoundingBox: -89 -180 523 612 %%HiResBoundingBox: -89 -180 523 612 %%DocumentProcessColors: Cyan Magenta Yellow Black %AI5_FileFormat 9.0 %AI12_BuildNumber: 434 %AI3_ColorUsage: Color %AI7_ImageSettings: 0 %%RGBProcessColor: 0 0 0 ([Registration]) %AI3_TemplateBox: 216.5 215.5 216.5 215.5 %AI3_TileBox: -72 -140 504 594 %AI3_DocumentPreview: None %AI5_ArtSize: 432 432 %AI5_RulerUnits: 0 %AI9_ColorModel: 1 %AI5_ArtFlags: 0 0 0 1 0 0 1 0 0 %AI5_TargetResolution: 800 %AI5_NumLayers: 6 %AI9_OpenToView: -150 386 2.55 1416 992 18 0 0 6 75 0 0 1 1 1 0 1 %AI5_OpenViewLayers: 777772 %%PageOrigin:0 0 %AI7_GridSettings: 72 16 72 16 1 1 0 0 0 0.5 0.5 0.5 %AI9_Flatten: 1 %AI12_CMSettings: 00.MO %%EndComments endstream endobj 18 0 obj <>stream +HWks۸i(D8vZيJZfg;$@_ >DRA:q/DYRbF)&)Dd8E +.dHӒm}q%͂*[ +K(2g<4,WǮTa>.6CI+%qu.^o|gGHA[$KaȯԘWD " 92+ 3Dc6Xi_.[sGHlɾ]4m!Fm;~_#WLom|c`8#?:5l]@dgtj/51Ѧg8_+ܪ{=HVm"Yw$a &o@G)l5; Md =}Jo"jqK8B?JGT8H0ޅ|O F{{x.c˙jZ ȒjnYl p^.סMS]"9v+0gTc1հ6afTX<^)dP^#IإHL%r!m1>GHH$ Dday4dqʗF2Nstzv$wS;ձ|9?kURz4LCtZ: 6ɯg~@ =+k]R.hD#\\zlzFoz\k?pP7N:"LXyBؔVtG',М" "3oЮ/3pNCG%hІ3+<{Y +ݜɤvY뜚ygݭe +qfNtyr:q Hv+5 +0ǂPq,5p잞WGje{MsfXjr6YSwǸaKq̸ɛXP#n)5@shE5EA+AۙA7s*KX W\yTw&1 V2F + +|:57L V1GYLu`8oa i̝{#1Ldxa&M@cNNAXhn;jD3N\抸Qŵ(((,z159~_OoOzyxp_RX_Gx@ EhWJlfR,*~yK6et*%02sE] A8 rE٢_EZؼxa_Ǩ:b˱n((ŋ_@nsv`A'*s3IiU{_RC ~6,FKxA23Á!ty+n?S*KK1Sxm._bpOr(vKko9Xrç4^)ؐ$,oSW淀ʻt:ťi$"crRA~&o7tƿnR9A"_FͶzw8_b#_1LbD4GiiK xL;JR+%2% +-Sٙt8W[ &KGF9 p5륨 +{ $G$?fkV$ȾFƜGw3BÃ҂D1g\й +F2C@~ hAJM/6ϱ1i9 +}נ<ŝ:DP*z*55In4\V +Rc9J$5(`_bf>G/i:9 sP6Cxc?.ض!g^e3*ӈD|uy .w(_I,TXtuKD>?beAd?R# O?<;cJzVKuWtM. 1 F1# $6.4ajn͌7 MOT%]1 ,Lf2uPm7b^V3lLU9aj]n +$"lr0eEnU(+b)TrӫnatXb@:(FVO7,-5Jjƺ~:0'/ <|PN}oIm9yPlfcEyTrq?o-aЩS )+S|2Ր;Cs=w?%ه盗D3-ؘjx:NzP+UuCsBZ(dC:ƲMFImCzv}2*[SɖjdД[Bf$O'4)i^1%;WMQAtHU) (lCjv@OjЇǴ- @o*%LW`f)Nc2 +Rt;1 +&( ) 3Q/تAiYb~xa~u0Np(*/ReY>8W.RWJLѓikطiVTvˏ`frpvPo,0-LR*ү(2UZ$ )b53IXt#RP?k GK]DYߥ!"D ktѓ )ChKJ{f, +`,. *u$7,e~MnUӇF@dZUr?OS,2.`i5#`a)ȴ~ޏvݸhx G KFL-Og+p.Tv^^OĎ淗/@8IeE>]^(^#}6vڬIWρw +x +*5MR_v.T0K=جsގRz/C?By3vU}0QJe]]jMGXc-| &ˆajt.dG1۪@&ߕ?mt@6zS"OQaWY%ԝW^v H&.3\Ǟ9dhn8 Ü'#?-s*-,ur4 GC!f:!oEPX]mz[RfGUhЧu4Ѧ +ٸgS]1p6.qg #3-jEtvfP&U?-]v<M*D09ZDAҡXݵt7eLBf8|dV?  M }Űk6v@P>;euOl%%mGesRx.c[@BXWe/$1n@K//7Dr +*26<mzúF&T|5nh;@?WzJ|]|4<)A۩(AG%Uq|^J(wJԇgaʂe:5ԅ)9 NTވmns%I|_-v"v.}K/ taLn&ڛCgeQ_Pk.]:5pPi[|!6'AQ2Q\PQ*)y Z8x4>lȋwQVgW`o?ўOA$!n\!8}CjuJ3.׫p]`e,^y]d,af3G$s9F2? rz'CÒeu(a^PdgV.v4|5d 1L,#:T䲕W)S_bɥ%Q"#;Y݅Lēi"~ЊT4~aFb3 vh齇2\wt1N +JtޗeGS۝Mo V'[3w~s0e_dt ST҅~H.f,"+ux +k$(F7tdm,S<*y_3̚MmJ}K:bέ]Z 6!swYK?(vհk<\7ÈУ!`"z*v3˦be6WwntŰ +nktAA&?I[l>ؾJ60dbB&! +A-2aTJDir주4/*CL$dGϨ4.uf y4! 5"}Woj:W*cZi379r8e},>!T0lݍ}2Ŗw҂4߉^q(h69~?MIzSzѓ b@{Ye{?Dw1G[l`>:j*{2-(ۂ+Sbõ+b'DZCs+*(^, [NSwU&ـg%}qzPe'glDq"WYGҁJ/cww/7ły,T*AWGts.r`҉0rK nq`OAVK/b2Ϗ%KcӍaSz\85?9Xgw~TA!MJDžS?wLe( _Ys}~Ƀ\A:n^sԩxJc3r_@535纄=0E\l(;8"C'M;ӱϓ#۽`D@= @1JƿaiHk.;Xa^da<_|AbżQB0XRW0a#:FaW2:mԜ7Gx6kvcDNT-48ʹN`- \ PEth)b8iF[eqPqF  Um$b=w]ޛ/9^#Y)Ε{"~ Gt._cTT-槠a3U jwOLM +.I¨ݺ(U.K)}1dsJDdzmYX]9n|=LXk8PfR~KrM%fˮ{b | gKzvHVN\z!(d%g+rTPd!3 PFs/F%?óؑؑM4ۮ e hvX6^'a7À/kpf(!U \|s$pP3MY\` cR!k8_62 0Qo(= e ]CGX/u& _6lӛ tBKB/B k}k?mpAJWzf^F3eX:"!8*M BΒlaCx8쥇p=xyT'Jpx;_W8^TJ>SGx;+a#>+WG?f <$nR `ݕWpy 4ܠ8_l(N/ِ fzmI/@G=V֓Dք+XNtۦWs'` 9%,H2>L]J \a ک9ł1a7/,Ҭty&_2=6ʩ0 =. K^)M1ltR'swv؛_KzЁPW CLN䖶8X;vp7Ts*0AALV3q0E$Z3H43F1:1lk.˾gӠ`_ [hhh0KqZKΎm.M&%L78g4P idfT4 iҪdSt=c mZHZlhh@#vUe<c|%7bv ZA?4ݙˊUBs4t9g]Kj!ocsBCA_zLcՊ 3z49ZX;XE!0A.~Hhc2,:Sˠth\-CY,#sw" ^ +( |]~Z4CV)1^\ +47`*B>G +oR' +M),[# +4|B=M'5 +)*.BiTᒿU›zdmI^A,j ,fS>5=$A=k<'Ϛ[0_=<_!jFb̬ZmTFk+ʮŧJbXwgSU[{oXkݳϰxԬ&"mY|+ST_R۾Ҝ3čbeGٕ*WlE\u\H/!srcӱn\[(ۖ)kR;Zl{+F:k*c7Z6Ze3VX`.Ŵs™4Y=Qy|*˽9jvX^9FyOh=hiVJO 5 u=ᄙ'|L|o%[E߮ӛR#TޢT>:O>9Џq|XgN:h0ǾAiRl(~܊V aI3BCC! +. cʓ +7tv ƚ(+4hvHO5W= pB bu +,B5EXShPx XS */x/u#\jw{n?7#i{ᵚwjȁYZݹs\YT }4-ѹ?OPJMZHJ+:%xپ +עA4xHo\tY\`-룣: ^.@ +w^ȕ_v~`C{v_Qv"xt5L&qJB9WLN] u^֑+POu*ZNιOÇ|耉A`㳐ZZ?5>caF 2Y)71ܦ]rO_J~YZ^nd%G<ƫne,=3-KO[z,?nq\^]6H)ݴ{U`?ޢWy1{v-۸Sp`BX f{kq1EtQ O~J2ZïBU;`{i{=<(kM#;ʲ / O9L^]Ř{C-%d5 [=wߟ:pW.ox>FDZ,P o(| ($U67ZK:XN<3_J ita[M| 햬{K6&YHtGϨ {-Y/5){BoƥS+[՟{Z:loz~o_ӖR2/ ʻ3^(K1 Rb3?TX~|hbo'XP?e0kh4{]?1]>?WyWL,a_-j"Һ +uA}£L0[xʝ0T6ƫB|ls&g~o sL {K;G6eّ<vRE=#[~1a~=QHvzHnY(Yuk?`?p>p.N0"0\Tn; 3HR= fKۍ)e]8 a5=rCWo-ɻ;*fG,UkSn+Ip'\ʼ_*j7K³]IY!N5 C-4{e{;~Tx켐cSI6A=W?E+ m@t.Tz[ZUu ?{PA`.iϊT,Ԟ' *+=b )hO;ZLCt4emY+ "|d 3 gt9~ c;awOIf#[,'^iyi=E=ﳺ'*zᦃݡEo85ݶԉ,#t*"S !u4YzJ^7tA:b Rd1⩝Tz\Eh<`ǿh r<5hjr3Їdl*8aDפ qtJ`?ޞ"$r8!+8|~1iqjn S C (泌V+ Y_Q*2H0g4ze +hCѼ5g 8Mh0Q-?x NpFs h0 +f4G+C3EF5Rs\{jA x)I>%ЗJLCά ps3X`F@$kB&Ѱ43>xR$o08z^W\NxQVSO Gbɱ`a]j%}^ڡ/oiaw BO Qb(UGW ZfZ )--DUCzCŗei眏 LגtOrn9'`aM}%Ӳ$+̲sLk@?Gayj#G*p#`-jx,wdY(jݕd5O[{VmbcEfo,Vj&TL0_6XM̺6?nR?ӧ#i>MG0iAl0'đoa;FUd3x^ ڲFoHnt׎W"^ۄDr/_:zɵ.P9@L(y>{xyTX% ~{-jԪ.ߒx^&{_{148v'z4{<8={ ?Z>jGOeᣥWJzK{E>Vģ4Gľ{64hŕvMOZϒJ?◯֝-aR G;,dq'gIk{x>vE %"JM_ojoʈ{;pSėv-&),v" ]w)պǮ[vlTu+{t/ b֊{99BRb/h[syI/ѧ/j]{@i6}/`w Vg*ܷ>pNxoz1xJV&,\'k( +cMs 6pMߐY6rKP+03hߌ""gğK6407m1yi-6;/$D(rU]U©h5wZWR ,ΘZ?Cxm!6f:MUgHl~({'/&ݣbjޓN\sL +8!:(]rnfWS1Eb?k>rmG3duO vHg&&y5E8%zOb($o5 @ /AQT-*LIn[M%&J0cThnp~ѯ|~95{,`C{Lc~By&z;V~'1kC3^s[41K܅PiS~l? b?m`~ jxB`޺+Ͻ]c_|coW0L%ABfӡ@0Lw|[ -䄦%x͑`iv7c6LvȜ (v.lAy%uǩF冉KSirN%)B?WҺ7\5Ï"ǻЏO/;)AJ~>+`0xأ0HJt@ fITMɹdI5 {eb֍Ͻ=ڙqn:j7ΎwåSNRpqQ̹aj x 11!ğK|<=Di)^iHwvrU]U© +tJR3ۧޖf +`OJy%^[U3gB%ݘZݘfp7pM)2m+ǿ6%,}Y1e0Lf!CΥ~ԙ%VOJ#Li-MTr 'hD0vAjJ[Зvcmߤhk~K""Hּi +[HꚠvA'9,jYNIhs0k:q(pYl$XP1=G58a/)glR=1DqmjXIQ P"f& &Rš\ga0|J47a* 2~L[2VD@u$_Y,XF!2{A粸@1N umޒh`u) V韅žM_2!qrkɇc(NC*J2{m@hZs} ʰ0S !q00wDex`4 5xLɻ. %n;ؽ]M%Oq{8b8%l kSkJ:>CWz:} @i c’B._%$Yї59s&_;x'B)}褌^ `^Hi; TIT|M95b)WS#w8.bWegƩtz;foEKPN͍qSynv=rxeA暪NooNh<9QN-ٴuT|4L2}S` +em 1;8/ԗ٧lm}Vg3+X] u.$wR +6:r8yNŗܾ~<UH%|36շչDHp^܃"DvH@89vQvuR/I_VHuA);{*}VP'X *Qxչ!<7og؛}O~B"$ NC-bV8uEb +"bz)kNma粒Mn34^lA KdXJZ(9)*_b9)bjjKC9c4T+ݾ@Γށن,dCxm$d|A1R&h-0H\n#VOxӫǬ&T9]9d +4|PY@KLOۑF`4J$+R1R:"?f0s!}, JJC@7WX܀79c V_њ%n[ʒ&1 G#X+% i8IӡYI zeL,}l\bbba芘%6.w{qغv g;4Yx9Yp]ybݱ,_0M%GϋpkRXo|ЬElsLq) 0聼^]MF;qQ PLP?_1=u``5x=p`@c,8r y; +` sHȹ.N^IyzL?/.Nrs. U0W u!*Fɾ,WB)1頨dqQPOqN!b ('teNu2#/V_RQ ?#.uW ux*\8~kOy%Y")ɿ$b-ǕaFhJ[P29BDTsH9s2/7H(U-ye9 0rt;D(l$С̉!p; +ݬAgBJwby$5/'f8[tSam)X~R;Cѡ{U][BDkģڕ; n@#R@s;3 JrigU J:T+ŝ;q%7oV 4U܍t+4ĦRb2:|zKc ཷJ2/i71|%v@ +ylIQ]#*;$˔c1Rj s1=f=M8cyVxoFK  endstream endobj 19 0 obj <>stream +HWZJ}<@ִ@ "|$gfrfr1ոuvEyJ|+gu5+Ǥh=ICɗnd/ӃQ0zǓr4*O:^EA,}h1jUCt!u۷-T~ rN:VFʉ~a~Da1]LOS%؋aMYS~1ۈ距3Q4U?l_U]|oQ1HY A=9`.$M0NUGrU|7H:@FQ˽(x;qpc}Y8$78jl=g-uP;Uz4P UKOh( +N)%;e[ Y4HOCP\(Rvg>c\i̟& CUuvM/QqiHpBӐB 4(6 )b5VݳP-㓕'龎3G,0H322+x{B~"&p昲R_<гc=j]/Pl҆ VL|^yI+Ĝl,ʤ2"˲Pl+!p17S8JqQ G%i]F.=J,٫P`S+|Qeg26. TZʧ,R$Df2!.-Fnn, _3%J-U ҆r:IJAZ>T_xRAX:d⛹* TM(bkڴ)# CN?iHs*~Pyif|`1 6AJ$X ؾ,vXP5(V?{~[ӭ$ΕtT˼/g9jd=A\A JF); qmϖ~q.lz-߹mWAlT囟ͣ|~jR95 +R%0O1.a?!S!ntryx"F|8Uhp񑺛I'gK>P벝I!JU2h\9>԰rU_q.wX5W=y}<==& fEZ_8Mcа c -ouVG3]iAZsI׏k2ƨ7 YzT$an`Be'ob(TZw@0c +JY`V02P!$-t>6are}qQA.,W)N9Mzp ++; |P]9\dgy=P#5HKM1\'~ɲTvw,5_5Nw]BÝr@Q|KX +VA/JXPb>fPV1#~*2Ʀg-ua&ZČ]f!5iYX61,@~:ػW 3w*{,RI60)SǺҜ.&tX3Pi5 uŮ4[V/LS'y]-E3OJ^>~tw!n? +X1]ycHJҥ՞r ldGGE'͠S5{WM$ K"|_nX,P.Wx0q~05.C X}C1"O6`4`ahHйl4٦w:w IX8@sX$|-拣piHI{' S#mxLg'vb%։!i^jslN-bDe\.y)RޠEwp!c}qn0\&,cap47Դ8Z'cj\rC_JkicV +N)(ײi?U]J;M`&4#1k_Aq_ys! ieu@NQ&M^Hp֔]5Z8c.&lŴ`A?,yL,~J䃟-K\ LPPLr^ +/ƈ-g'#y"if| zvgd)84++wfԥpT +'S9O|/eLiF:7ars״\ X؅ń`gz?6g5ĉ=@w׉R f{$\W񞽐,sjO-EJh2b PnIs!08 MVUvFA[y^&yHg,8YRك"-^#|;FJʺA}샯A̻=  +pQt"RR?fbTgI%i1[;g~;Jz|w$+뼚m'}}0R-ZT>H 1`f3";9W~DX +ErnV'@ +m9Wͮ''1,vZ%+7 -ar!q70Vt +i+Yo9 y͸ 혽AdnAYhCC'y 9y7Pq{Mf/cW?6p*`"e󶤀ZM{:b>QG=Ȳ5ved EJ! +/Yy"ujG2[M՚~1+6 d:=~YD^{ޗh򂛺RG)S,POĮ=xpN+sxX+MD9&4}fUi%"y}w^ngWOIFl@oFa}: uvB>Vg(ͬ8bfG_WL-dBB5N{i"Е +;PD8 5+j!"w[q]Ewphd+]`v +~'b%Q"KBy6k %|s]gtS(=p=0n"J;i#^z;M]=S*rdO|!^* B`XLLR uWVǐ/):7I@'p8Ӊ| V#~X!Q6;P災^l{Ԏٚ+ϧ1̨j|"{3jjS6[gD"-2~^yBT:9p&7jL I?Q Ǵ{]|\>[,6Pޜ%ZQ#>(l6v Q蠃ivphVH +\Shߘ8XhWO !Y1 L8F9hnea;+{X2H6 +y5Ryx}NnVp12'ý9p&10Qk" SC[?Y:CQˎHD +AcF. dn@p @$몟 ‡x*2ߩ<Sb7f? aM>p4bWk&Ħ 1{4ooB7i-=?ˇ7=8 M_ | ˯I4j?,!_>c"2L.K=rHKwGM&J9 Xm\$6[H.)u>XJXoXt\NYRZ$:L +Hޙ}o{3tq__h6Yсk▚|9ހ ;}rMj=+)W=[-v/,kKiɷ԰fRV>T*-aK~[o%o*I-,]2.&N}@bse>.ݓGke Koͺ\N~ʖKvt# hIΔڵӲ\NĒB^*k!5sfK^lKU=+l_^k {&g0|V0 c9;7y«{740aʴaޘCEVXpY^s ze׃ +u8ޠPS^;dр[RBW=UMU(~Bs|)K.{*sٳ]!8~ϟȼ%We;#[G3ioMM9W;$o5j',9<%'jKq–\'hMVnOؒqB%W srwa-9c0ҒץLT7.+0]oeRl*gX 7b |[?8-.۫)}58̱cUXρ>O5;k?3D-3vβbWZlŷ8ʿZ6Yuڴ D獾kcÌ71vd7Mm|'КU; msO\ӬbhVxϊ$kP \o O\fY|_q)1{pRJZC\&&o̭&kY;=>4{}b<8}\ƊzZ{2  ͹%Ar Z|{D%TBqҌ(5ìqL2_]Yt,׆+zLNׇ] uvӀmv K.Ensn4s V ]{Fx<p6Xf^p<ަ}t6Mg$PJ^F<~_E(D"PD=;;;\8եI$铒֖8N$~eK"'D" %i"XLB4/'HB`JQ(@˱DpF^K %Hҍ(tV8UE %H@E@D,%Mbx<6ȗHOY$$)8V+(7 )D"}:@EEU +={V=p=D"} x<~ + SO]ӝ*OO$A:N }0墍pHwu++Xv4$kGؔ_,S˥Q"KH$cN$=Pa#իF*t̙n1̭c+ ֥8K"H'OJLvt@j%JR`tȊD"~@M.UXČ;2ax\X'D"$Q%f)Z&  M$mTH$,aD4 *E/QAz" +k 8.@* ɀȇ|)D%P EQ|Km&JұvH&r@&2=~y1`Tn@4D_D"KpѥQ=! =*L)Xʽ&ʐߛH?D[;]NФ"ȇD"2J@8d)tbX +6]XYyD;U0d3WD"Ez*%DRGT Yb݃<{o}a݅5okO~Żhr֝]Xԭ=-RtVSe+H9N:uL +1~~jqo,<_|<;KO_r3o>D(?H4:vHn/֖V=X/ wq :p~qmG痯$%HJx<D677s(9]̌&ވ,~K}ݝ>_X/Ķ)l%e\V(`&MÚ\hTo(Et9> GM9 :p5e)" H2"dbRV.4LX+YV?!zlc8:87bYzÆs*܊pƥN*,!Od ŕʱKm|y`ήW1j]umaڮ}t} #L endstream endobj 20 0 obj <>stream +H]sX?F/]I. 73.`o~ .vlc[%zlMnJlN+'gx?2Ѧ'0 lΝ;34xt5[|Y#]YPHPDF Y t4Vw^WEQXhBx QH~8{@h#'#jYF Pqb,biA׻a7£Xhb&abexxx>̐>vd9:n߾=OKTB R,Y/])Z{U(b͝wvO3~ab|}= YtLDx0 Rb)ᔕfP#wR&_$SPJT4 + 3a)}b)*_Kkx/:A6#G㘧\ GHD'(9E)5 ҤXHIMU[TlrQ,~uQ~.4uA]EX =gԬM +@4KJU| +}XnJKG%*!bI5+hѿ&g]es!N(6DM4*ٴ!e&@J5S#@KQa“Yӭ::0R Z1Q2[}S( !k4G^`-]Qgg:'.2aӁN#h%bZ6OSexZn 5׺S)ʊX +)K,k>tHStpX6(..d/e ;&q귌RK>A m  `#UNOUY ֬^'OˆGK(qе ;pԢ +>Vx5:Iv]b&!qEyG<[Y=Az֭~Zp;k[T8tT*V +eb0zYsq%AE)%k?_4 +x4F#pG/,OaJ9$Z-4vQ6D1GƎ7t' ~e5wÅ2b daUn 4K/uo`)*#1N/(J e%Ȟr ފn;H)]ɾ_LCe;E2e0H#,價yjn \\][= uoRo)c8խ" +*Eiص@.QA[* +墨F5vN:ိ%\P/2Ói`m(lc2/?~o};w?ZX\FHWЮ-,,8- uT8*SK4.>@ +~HmoK5^NDCA Z %Hn!o(WC/K>OÓQ-^w7Tzs}\G|ړť[6VVѮ/..7R7xֶQ8MׄAJilCMUmhVU1k8-~2^*R- IਢliZG~:n0zd iI>)s ¯~s߽=&sss֟R?ͭ=^ZZq _վ;4NNX +l`)D8ER +HN QU:X +)K.@jupZ Azixu]D<<<$N 'd4/ۏ>ssW`@%8daq5AQaO?r'R Y<Հ}8P +]{dp끢} l:m]i.Hr!@cCK1wQH(Q7?i4FQj+GR6q>]4r^K΅EF]rL&Lhܞ exBZL**ʩR@QX +BQP*V!9pKSZ2^M"L1-ERHM +xo*6RfFgq'g6fc6&Ņ$IVB`ċ/<D %?a)ntF' +5CɊXkTmX +H)Nvwpjs5+T)vAL=v܏Px Z.,LL슚䧍P`aЊ7X]uy}h0T_ԏKjmVSmrNS2N+&bG/ D1Igt5#\2-ZTQ5sp)mrJl|+Fx$ + jJ=AC]4.zr0l֯.BzN 6KnhɊ7jJxZ%HP +?Z_w^,r:)*TQM)襉`%-m竈Si4)vocbd ǧ) oŬ>_+D}Չ|LjJqxaρI(;Ճ&W_} 3<[dHz`xFpzpĜESP>P~CuXXaA88UwT[GTX^ +N! +A:)őY5M&T!ųUs BEP&&*pGa Brr?,uON(Z(?MLVR_!}'RVAl~*C׆OviGhn_C/fJBF꛿淟>3PI"noFJKB<0‹(WеMdeW>D懹~pdti{UөکR,.R +b, ʔ2V,E/ +EVAǐ,MH6Εހ +|6$MS}ʸQ m  .HgD0Y:٠{x֪vV)*F!gGZ!Zj[ +Kġkǵ~)] n 9Ûp/5M8Je9\XtOqDdsTM)^_m.o!P ]sqAhG2ab㔋:ɩ!N?$KB3!gTC5ő)A +l)R: +HSQfDpI#l4JQS7(js* 53lw57_jp*[*e6v7m9Wy_<tЧAŠINKE햬(Jh(啯iRv4qrq@eyxnMZ:j&*'y@-"#wٷҥCTAx.cR[4ȋ(t93S> K ByzZ[x<~ǟo蝻#P% 1¥ +nN6 )ys~y ,ŵ嵿n,,=>HbuzvTfNXJ:5mBhѰ9,.Y9JEjQJQ ^)8V^<1.p1I+Fsq' N:K5hF]6kJLVO$O1|P^J JĥF=,ȡ$_)!F\&8%()*R"4ij _w,Wrl^U]\\?޻`j9>>hQiBԡ +9y?),ABW ꣧kOv$'JP> A&WST"RE,J-B!OyrNB8Ģ)pPn ]Bi?QMd]˗;yi>*/؊kdZC-V Ia1vTyޝ 縝B`[TZd*Q I +Űq`lRJlGV>Һ0s̥&|jH5'x_By +ՓS<+l$Vh=9|8x02l:B$A\cQ*RfQ?fgsn̯مUd'_Z_X~ ϥ rt}+H?]EJX\JuJEʸv2ڥXTHHb I٥0'RNQ')n|GjU/F:ZH4R% ntgzu4ke5r/3dN)/r(:YJÇx (=L^ +IY0sFj BrGb8/95 +ȟN R]cEM,[-Gf`MOܹsJ0{sb ПsrjzNH+iǤB+Ty՟)+O6EJ8>HJE3ҥҡ^5;z]EJ[2"etHLAK-i +<(6y1gusq  J~e:BqFgY^jԛ|BFTJ8̇rv?yr{Ё*Ո}U & +¡" xw%UtAzX´E̥Cd3*@IJQ-j5VrޖZ][o{zY KbOCMӰh\.Ϗ?wGv޿?C:&habu + +b-Jj'7޴%hSNׄ6%q2R~pſY l܎ܭ@ɷUlք=5[wKn-. {_m) +Z巀]ԥԊC]*_q0֑_IjM[ؑ+R~Vm,R(,l6_C##ccXE1*RęI@9@p՟ ̢.?-  >~rtn~E' OV[/JJQ=J-^eKtNBHe$"RK™b$ڌC7b'6Q +1B YPDAhv;=D)6'uI_w1:zKw).ynMr>DF1Il^ڶPwE)П% v43ژJ_;'#m] >)rbj\e!\#5\oOng؃Wq:(o/6}=K p&I)vL:%DB`مisn930(` J L +K6:1k9:19>MIDJ-.e"DfJE.5KRlbI]%t8+`P$}XSRj(Fq-]oimMo^oE7P}[D_ƿ|%k r`ˮց`!:vrpRR5.TGTR<#j.U/ڧUvx1h"汳OvB6.r36_$2M+Sqd3M7 C|G|!sH!dzԸPZqKhTz,մft{cWX|^e`BuV*~?ѣ"'3l? b;~+hOý' 6YhUPo$mYAoGƟRf)DZf1[ 8=>R3:IlGRVY-մ\r V*JB]jҵpJ#yb?ZN[TޤerRU@*nR8N]=fNJʁNXj*/Ka/D#;@U:)c kR[Cw,a)5V~7P(m-XP4|>|4770_6큑AgӧyXW4ŏ953c6}rfdtbc@z5\5үR[S$ CNIGLT +HBBVj%\a=KCrF T)٣JzG,zv-gW,\Si~ki\_-e,4OBU8ti.1^CþltpQ-T;.'l6ꭶv]GOjpɓ'6m~3@rhXP2inLQ#G GOO+?Os%2>#̅qcͅgjn=!,vbk8%9TͽQ  CQp^ẓR)K"FԪZ"HRZ#KVw| F;@Ugy){?x.YrөkEED2WKe;*kW>}jON>eU&_ K@5s;(a|ڦx!G9;:0 xnd~R[*(*(P?2Bw's;5 u?'&1r{x kҌIOK$g1JBNUi$crCqN"'$Tq& +K+襕VM>S/qjՒZԑwΏ_Rg癍$֟^nVb%ѿ XE Ҵ5giSfK?tn9Ild^Lfb%gaoA? *r{u6R +W\oщ A#)):A'O(Od"b/`q.\R1K::n'B!a|`H]`y4iJ!g&DŽgZ +j'Sɚ?XRb3OzpTDcH4CG 3@0Z6 "+TMquUxkb#jx{CZR4N_Ѯ[r]Sw=%.S: dZJ"ZN_\3KEԟe+DGUojF[Wd )g{"ﮛX nRzj"E6j90ʪ'w9R;ivW~/vŸY;Rކ{luB/k5IHZvǥŁevA F>o0z`1p>:72 UP -g&'UPF( +iZ|8OOO="P[CC#_|k|JH ZړS6Xf endstream endobj 21 0 obj <>stream +Hr$k[^*ɖfɃ$d67"w[EI%RN($$e%\7h1Aq '$GB4`LDmoDJz0&ñt0*hRmJVjfzh4aF2Vۊԛ Z sONYlwePZ=ob>QW +e]*ȱ\r#e˹7_'Ve?#_%瞈9%=bH /y"/ +Qܯ[DuO"{^YtD|<kE}tDYfQ3,uu79#Sԍd lߣD7jm7kfwmP0-\jsXo `_tX X&'RkF\J?ym֍[^|?]}ڍ+obc䦕7nutح7n߻y(w~upOȽ?<)Foq66\yecWG\~Us×^ts)'^8q3>:5=۶ڷoF0)YVIIQt$3<>Lk}##O|Af$*Yʇ e">p= E`$FR͕*bR 52lE;յhVgِͶFz-khKrKom +b>5Ʉ=P4BE3YijIr\/(t!+; +AJqX^z ┢x?~))Ҿ*<}'nj88-W.FsfԊfIl65VZfw'Št.="6-T"ѨʩT #7@wud{%HPgwP)KFϋ~(GOC?|Z wl4ۀTi-e[uҞ|v88E^TyN,E6" ?xwz4vwHrv]vسFڲ7Z9|TPܡ,% + nr-&}(nND>ë87Aq*rRGο\7tKgTZ9*AvKaZ?ΩOI6K*jY)i4:vc OP#XXXXX.BeFQzb=GTJzJJ!N-  M=g[~z^lZrvU^ᰉDzyV[y{W;)t|MMSuU:);ә_F .LpQ ,&RU!jZ0xsM۬7IVa\áh&_|=:fFQ)%iaO訃uTr:XiuJfҼ_KJا%6tlK#hԶi]Yݚj?$'*Xf׷>9CKz0Aȉ F(+'>~#'#Z(!'?yBy?yB O#::t7?+hR^vc)St_A4.vipڈ3ySl 9jwi3+HE;Kx[E4aiw> ,5VìF ZB6#rvq.1O6KWnmyRM/@ +-ONҾ~tz.V\‡G@l֊SN/e,Qeo'NNۢf)}kT*k& ->'zxIGdz%'9,fJިۍ +]YV UǣGۨ6baa)bAbo ~F\XxLß~ՑqjH򄒟0OsUP"x8|  ~o߾J!DUKqtRi_Nwi)Nh:+Je@7{!uG_HȂ(!s +zH:RoE\베Zdwe.) IAD)&]X`cm 5 "t<8Xy—Y +H)NK]OӮgHP19[$ߺOCmYJGCCg5%^}?AnVXHYKs:K[2j,AYj?|v1IJ9d& +ϴe+t3R>+.Zc,!fօtKq9Q)E4ڟ[ vf>V^i˯ lY H:J#3/UsՈَ}װ^hcId«c? +FRN E2\zr9\O[iyjFj J ]|¥|Yb~[;'Ͼ}̹7O=1SCҎs T +)ՕBŗ'o>_s VfDŽ cNg)[ڄyCH3Kd8}ۥ[2K)t^{s~'&]T8XBKrxIz<ԍH W7 kJ'Kr㍟}xίO~KU#MPPI O>'=y~OT(#ݽGسo߁RX1E}5KwcUaFvJSt h:JryayaBQ@4#rBJKLesMILI^,B-W,)%}Nܯ=O׸F6^SdEVafYNF6rE9] -\,8|F7J]= fBA;P87~X{R?/ ^xj+''3N>&'(K(<|;}pW{M4ݢ k4Nv#MS: RmD4Nrk(|"%NX?fY)/Y[bƃ׳>&ZnbKMioRإ-rbbЁϬ&f^b2d$hBOf0?7RL MXpJ.Qd$;W'0سRTp>M!_Oҳ2'U RF,Dt:N%2S#T)JkΈvZ 'BSL,fCBd#\Ȃw͠c#iYoCSRq$(5&YnH?l|-B/\>?p cSKP?)9v;ӧgoב<ԭkϞO7?EAIdb qKKc`W¾hR`q%A T]IQZ*PxrTF.\H>-K}yy&{L[gzMY􄜇]dAHgs =C!ĉ:ΩkYtt7eY桸^r?e-m,*Mji|z֩T_FDcЍ(ʹ ^D՗stFuAj$*)U]-RByC9Sn[; EA+Y_nÇCJ1/np fѡ(UJԿ7o}x.]1x.\:0x''?GxvHP ~j +?YB>J#t?p75x}F)D]8jkuYCl;!e9moViA TORwpä잔}!QEsd)0烖\6!wdN)jpe >@k!}h'LSC4irCv61s?ixBQeB8Ҕ?ӟ6;O&لg RBU>Ҫ}>Xm p{l0K~~(gx$a^4SL}iXFKEP-QZz$P.3(4@()rtJ-J9I=1D;0K!˫JEw{> +xb!ze~vo︇ԟ e| km'zgcu}SuMCUu}UumEŷo39R_ )8UD*9B(4AJ?י8(JA((\tg3 #ɨsTtBQRR┉*qS^ =`eGR}z`` _2(Rta9(CZBN,q+_!% UH[Rr]|eQq"E116|H}1vԜ IuS^Z=%- HyKhjiZ\&,M}MystYJEګ)b+䴐VҘMD߳0ݏϿLJTSKGherC[C[JEʏ0Y:4(Paiib) E1욄jFY*q:_LYg"/sGHZTQőNG_ID)jї%?yBB1"TV*Ohc~~OS NzMS* -'MeH򐖟-Up"*.NK/<.;tv녙qh£ ǑE +1Ep=)h -Ĝ+Kcsߚ c§au NmF1v}EjT(JAZ>4l싛^>S\d~ ~Z!SᔇT%M܊saSp6U,bSp*C娓(#H1q +v*Q S@*zolɵ]f%_7?w!J%BB19AgmWϛ[.cM𳵡R}CK]}3?yB,>={s'OgXRUҹe(:_]iF|QoT5NK* , WO$Dž4mآ]pEqH̍ +Y8Ǔ& 1:= +iqK9N 4`I-IO܆y`qipSAcx=_c5DOPjR|}/'p]4L} -T:be*5*M X5NWyNiYsnfXaq)8@U +Kvki-({۹l6ڢsKt".Ye?O$rrowhV#UVꋮZu$1m|'؀|sĐd2qLE:exJḊ/<&x;/',YRd*,UUuWD -ڟR<dKJU{E+Bj\J!fRK JSKR(Q;]BP7A)iNZJ.ij/7?#JJT(!*J jB a??BՊv ?{߇%^ ]AtAvj4^TQJr Ċ ERk*@! T̩'{MdFR:]QcN^Yׄ⢾[9l3UUm*Q +!1P#b)!>U8WH4ʫ\Ou=!Յ~ XVD) Em>}5:ImRKTm3>fʼRJSXTmi5b؅a T) #E!b]Y׼rһ-l7׻(=(᧚СGCc@Hp!LC($xj*JO[ +=nܼvO)42Ptu#; L'Ӽ\ d:JEmsjhUKՁvU()9zi bҝVs{wrfjvjlY=)Y9n* fUJ2 c!-ʩgThV[_976n6ݦ6mӼ*8q΍#er1W1dA3cFvL [tO&0/ +,NNt%vNE۲ϔfҜIF=z%BU:+3{{MX|ς{c=e xd/F={ $1P( JJxbիţ'*R)myI!G9`pJ!r5_6_7{;- +_MqHFWYNHx$ε$KըH tjKW,ܦ #?|Б : +1Х`!6gm;Zjք\6>'ϊwH})B(P1D=kFRSƺgB=hS5R]Ku9@J-m|vXJ.j̎/iѿ`BE|ͣ.1` u+wUtL`)TJ)ޫߕ +lٓf:E=_fphd#94r BqP +%~BџBN=8ko^rl6_z_ 5T=vN)K)]rJ!յT All5pj5VV]K my|Ȋ,[jL5"PPKk^Zڇ3+d9{E +-)F=[z<B|Ӳ S!e&I2 -x-}22o_"3 ?y":E *xSh5ŧ3Jdl+Mے"ỳ=Z3iU/U#NEYmQѢR1dW;aPBH Qܡ(^Vb9i[J!MvQK)LPM("ƽlYTK5FSp 804<:29|o#9WVj/ m_VꋕV]Vi6L`cc`sc㤿qf3$Z~B8vl_?~/ٔ~?I~Bi? Oݹl]n#JGit?+deiF[jԄITKT-9gI '٨רC} HLA2irFΏHYhu$iKq&l V^އ'= ETp7$⸹Lxk*ȇ6ʾ1 E:R޳ H-95e*f iƾ |Jͷ&7uCb` +?+j)ĞUt1 BT<-9%Qn`5f]u`gd&Q-u6P-2;](X5 .2o_$=*通 b8&H KhNP}ki\D3>4ZH*g'3gco_pcp{#Db$? wpqs׮]H! NJs +H)-*]DRTkTU6-;H`xi2l u)mRvj)w+­ ER Bg^N!C᪶E +I7wI(ZMiP%.g|6,䣵|TBL])x}SH)|HErWnWut( ׅSJ4ʇLWfGċ* +37R[~:r0FsjLZd*]3Ԥ҄Na†(@SAq'ժFus*rp cZ!9tOGYzmZ(^p"#&$N5*&I%PȉRҭ;W^( %/lErJ%Ԅ9G;!t0ZUI얚АҖA%E0+ݍd^9pnE ؀qeq@Tb~\>z6JgzNG9wrZ Xensv3%D +m޷E:&SsA%ݯrz[`}<^b\-DCΒZ#H-uՁiԋ4*>(fT?SHe+wWW'.ȫHSLtĪ1[`m(/mLER=v߼Lҳ9jxjۅ^d| o~;86APPIJ'(M('M($t .\tʕ+#NM] +HOqjuN}Iw*K˸&H Nm4uT|*mBNR\QEANhclBtLd#ěHӟ/Jp~z0SҥYjiE_Ͽ+Z:fS/Ýs2)e5?T]>u!K)(#ƷjM1℥F;Lf+,t--c4JCF E*E'ոsI;Zʋ)I.uw.(i|Hg93qq!"է!V!)XOS@j(^HpxqG]ߑ < O9~40x [X\ D˗ MYJCJ[JCJ[jҐqwǓQCc̶r RVn-mMr[OoJtHRPDܧ$EtBd IO-RfbE9,{ʞ'qͽR^uHk>鬥51Ę?K~ 6io +:۩B+pj;v)?de{_XpbW88gd6 5YjW4i&FTɤ[j&lqR9Em$wѴΖۛt3WBQ? )m) )mRP ׳aY?s* (xFq0ǣS׿{G?䇠ӟ|w=:AA? <OPIv"^ruK.C\6>hg,XXZTVҨZy;:֕SUi)$hP&m4/f@J%Sm R<3mMΧAhX4eIpBfvEGTi75.FH4fSoUxzX;t=(o?MCe{lZջbL=1&Vl_͒&?z %_0 +.69Тif(%PF^BkUm8qE`SS8:]ئ] \ NFsQ['M}pQd9WݮGmW}&Z+fsp6'l=~04G'_\;kT:{)1DZE5xp~嚱 랓`?8<> F?q~o +kGD"5i*M +eR?Y2?{Bt/pOy-@zS=>~AN *Tۨ*HՖ˔R)SYimIM)1Qj!eTN,HnXZ3T k&=O©An _ +y?@iԦ`9Tt + +) 0ԚiQ0`2'-y_WsٻIA9:vvH b|7j%W]98_!o6z-f Yy@e34jBWYVŠlD)Ňp*H?XzR| -=N?ӕxvt|r? yxt-- +Hg&fTR?1XUJ'KP(ؤ=%ǟ=ܐF7yKlT)*p*}SiO8~͈9G@jԥ# m% ВZUXJ3$AISRl{Ft?Oۦ~3c%pZHUl Uqj,_VINx{/r;EW:0$=I_nAʢnGR*zOB $JtrF*-KW46`XY[AŰs>u{umR&ꅐ-BjĩVT\+g#8z78ι{xBQ:n{fs_o ̤r )d~bOOU޻nw&p޼ysff䋂OTΦ4)Щ8U85 +ԬXRZza2HUOҫB_7&R2E(,m֩YZq/Ҵ+v !ev3|"c2caY:%؞A*-|q~JSfxYr 'HV[Ȗ*Qf]1[NU{%ωm=8_ER$IҁS-jAP PIQ SqŌ i`fqZҝU/Nrum)>*D`fUJPAӧr)P K&o$d*MPd~2B'='߽wwR ?N +i4ɥrp*NqTQ)lZQ֩n~^%6y!UYji3l%Im*SfC3ո$Nv2+M_;j4a))ڞ'NJc2gT a7/#:M+8_IKDT2yA9]\-q,r|ҮZ!=tZJ#+;n>Iŕ^TN\@Ѽ M+2SJpZ +jHk"):RTE:00&öB|3:NKm)JJ닒 ~:N9SqU)-iuo/ r\[ S3HSR}Ti\y+N ZBtRH15?H&Q'%*+T7Aw&ׯ_~gK)Q}NJK/LSL)ۅU*aPV,Թkak^Rv4gYwËsJUOyvvҲopM3 r'Y3|ȅq3gy&X'1B:S StSbI_K·BTԣ u6;Dvtk:*I|V6΅$~!MpTͨL *Ti?\-0OWZ#-4WDE(Z +ZiGVMVfSW Rq*)◛iZ `w?h( ps#;xL꧊P*O'F~*z89o޺ڵkӟJ< R>Z1HUjU e,e!ݕb-2Mzh9hQh#Nm]tr|pI7^H+ O-of֔*-Efm RgdH\|"cR::rNZJӮi>]t*-iUDb];bhK8@* іp"ТD Kkd3F>gw}jyzشշK^[c^Խ/6dWtidf,BtV* to_:`В-ac3loQZiqQ Uv +FȎ#tR>]EBg8ZQm'AڋuT h&QHN`-m!y+O?~c$$9쿿B*o4'#'Ss)٣O=~2H_zu:J;|}nHrjRQCZ4K V +EoiG!GjHp!,ARKo).|H: ۽b_Q۽P'hme4 E|]SE \sRR]^*P,<6nimwТ Jv!RIcwm [I!Y!OH7핣.$h \")!j3`C 6'!0غ]'PKo  :K}i)+h kv& H|[vNl1[Z\@@jũQԚϦ):'o y5[qsYT +rW=~W)'|Zo*7`'ZfXN Qx K1(*\"N!h)C"D¶I85T)k,8mnYzVkU +H鐔 Ocb:pYxD_w7O? 7 QIGcc߿/ +dzpjꙫ%bSSQiOStR*)Z$k U:`Q|E*\$KRn):@J,=#M[9+vz\ %l>ɯNɊs:˭R˜Α1c^Evtw6D< E[ +V/'U>5(NX HB^4+o̰śMmQGeecYࢰ$`tEA\}Q +%XFxNGsj5{y5YUGۤkUc6 jh29(Jpgn<9959QOJ(O&A4I ~M2@ +B={<~=靿>D~HNER+DrJW) mwշmr*\Zuȩ AjjՐ2R2#4PX?WYI`֎sK}b%R3Qi>cJf~H_4H7mV_{ ;RMt˱n)l!TK |[JuX?4~a= +r\=AF?İF`֎KCoۉ +<-m(ܶH錢3X +Q[JE6ngS{)~àG!e,5h?p7o~_+'Ԩ蓯bO6ɠ%-7>F`l ctaaĻx}>H㩽x:BɑT/*"S**S LRT tzH1iMt + ߊ|/cV!WsKG9Rҫ-v>eOQmI{A!3Tye +e4FmTST)ws?/8犫o':ZO)|\v|bXIR4+Ho yֲj-C-9>޻Z]%셄jyu\dbQCg!*EVaZ4THG^%eKL%c,uz9SݦHHi/7aB%E bxvpNȅ#;?xHd*(zf~^z磱HpTX Tߪn7qBIq)k)i$[)Pc85!,mFfj^+C.$Ԅ1lMJBZB߽޺<bK4bC:BѹgO'B_Li2KRٳ3ʺ:,jhʡj]yIf4hPT֚uUǿNAu7o:}=X3A +)iS uz]xTҬ[t\إ_Jtr{3Z{leBսXs/T<+wY.mUbw^6%z,B8YKx[Gε]v)̶?U2; IR)$'>^%4U.YPZġa|6JdSN԰S3ՒsqYieP#eBfRY,,pU޵o|$Ak׷*J x>(D?`dGx`^㓕#ysss3338LMM}ܨCմCrʡʊʹjZK,!ջoF'z<Y!{HIjݢXXHX=;0r;ZU qRp,y *lg U6 +]I"-ъeM U(}vZm]ϣRB'&tqfGd#썶 endstream endobj 9 0 obj <>stream +%%BoundingBox: -89 -180 523 612 %%HiResBoundingBox: -89 -180 523 612 %AI7_Thumbnail: 100 128 8 %%BeginData: 6246 Hex Bytes %0000330000660000990000CC0033000033330033660033990033CC0033FF %0066000066330066660066990066CC0066FF009900009933009966009999 %0099CC0099FF00CC0000CC3300CC6600CC9900CCCC00CCFF00FF3300FF66 %00FF9900FFCC3300003300333300663300993300CC3300FF333300333333 %3333663333993333CC3333FF3366003366333366663366993366CC3366FF %3399003399333399663399993399CC3399FF33CC0033CC3333CC6633CC99 %33CCCC33CCFF33FF0033FF3333FF6633FF9933FFCC33FFFF660000660033 %6600666600996600CC6600FF6633006633336633666633996633CC6633FF %6666006666336666666666996666CC6666FF669900669933669966669999 %6699CC6699FF66CC0066CC3366CC6666CC9966CCCC66CCFF66FF0066FF33 %66FF6666FF9966FFCC66FFFF9900009900339900669900999900CC9900FF %9933009933339933669933999933CC9933FF996600996633996666996699 %9966CC9966FF9999009999339999669999999999CC9999FF99CC0099CC33 %99CC6699CC9999CCCC99CCFF99FF0099FF3399FF6699FF9999FFCC99FFFF %CC0000CC0033CC0066CC0099CC00CCCC00FFCC3300CC3333CC3366CC3399 %CC33CCCC33FFCC6600CC6633CC6666CC6699CC66CCCC66FFCC9900CC9933 %CC9966CC9999CC99CCCC99FFCCCC00CCCC33CCCC66CCCC99CCCCCCCCCCFF %CCFF00CCFF33CCFF66CCFF99CCFFCCCCFFFFFF0033FF0066FF0099FF00CC %FF3300FF3333FF3366FF3399FF33CCFF33FFFF6600FF6633FF6666FF6699 %FF66CCFF66FFFF9900FF9933FF9966FF9999FF99CCFF99FFFFCC00FFCC33 %FFCC66FFCC99FFCCCCFFCCFFFFFF33FFFF66FFFF99FFFFCC110000001100 %000011111111220000002200000022222222440000004400000044444444 %550000005500000055555555770000007700000077777777880000008800 %000088888888AA000000AA000000AAAAAAAABB000000BB000000BBBBBBBB %DD000000DD000000DDDDDDDDEE000000EE000000EEEEEEEE0000000000FF %00FF0000FFFFFF0000FF00FFFFFF00FFFFFF %524C45FDFCFFFDFCFFFDFCFFFDFCFFFDFCFFFDFCFFFDFCFFFDFCFFFDFCFF %FDFCFFFDFCFFFDFCFFFDFCFFFDFCFFFDFCFFFD89FFA97FFD62FF7FF955FD %61FF7FF9F9F955A9FD5EFF7FFD04F92B55FD5DFF7F03FD06F97FA9FD33FF %A8AFA8FD24FF7E0303F9F92BF9F9F92B7FFD31FFFD04A8FD24FF7E02FD04 %03FD05F92B7FFD16FFCAFFCAFD13FFA8A884A87DA87DFD24FF7E0202FD04 %0309FD05F92BA9FD13FFCACFCACFCAFD11FFA8A87DA884A87DA8FD24FF7E %010202030203020303F903F9F97FFD0CFFA8CAA8CAA7CAA8CAA8CFA8CAA8 %CFCAFFA8FD09FFA8A87DA87DA87D847D7D7DFD24FF7E0202070203022A03 %03032B032BFD0CFFFD05CACFCACFCAFFCACFCAFFCACFCAFFCAFD07FFA8A8 %7DA87DA87DA8FD047DFD24FF7E010101FD0402030203020354FFFFFFCFFD %05FFA8CFCACAA1CAA7CAA7CAA8CAA7CACACAA8CFCACAA8CFCACFCAFFCFFF %FFFFFD0A7D52FD24FF7E01010201FD040203020302FFFFFFCACFCAFFCACF %CACFCAFFC9CAA7CAC9CAA7FD04CACFCACFCACFCACFCACFCACFCACFCAFFA8 %A8FD067D597D537DA8FD23FF7E00FD040102010201020254FFFFA8CAA8CA %A8CAA8CFA8CAA7C9A1C9A1CAA7C9A1CAA7CAA7CAA7CAA7CAA8CAA8CFA8CA %A8CFA8FF7D7D537D527D527D525952FD24FF7EFD06010201070202A8FFCA %CACACFCACFCAFFCACFCACFCACAA1CAC9CAA1CAC9CAC9FD04CACFCACFCACF %CACFCAFFCAFFFFA8597D527D527D527D527DA8FD23FF7E0001010100FD05 %0129FFA8CAA7CAA7CAA8CAA8CFCACAA7CAA1C9A1C9A1CAA7CFCACAA7CAA7 %CAA7CAA7CAA7CAA8CAA8CFA8FF7D7D52525253FD0552FD24FF7EFD0A01A8 %FFCFA7FD04CACFFD04CAA1C9A1C9A1C9A1CFCACFCAFFCACFA7CAC9CAA7CA %CACAA7FD04CAFFA8A8527DFD06522E52A8FD23FF7E000100010001000100 %28A8FFA7CAA7CAA7CAA7CAA7CAA1C3A0C3A0C3A0CAA8CFA8CAA8CFA8CAA7 %CAA1C9A1CAA7CAA7CAA7CAA8A8A852275252522752275227FD24FF7EFD09 %0153FFCACAC9CACACAC9FD05CAA1C3A0C9A1CACACFCACFCAFFCACFCAFFCA %CAA7CAC9CAC9CAC9CAC9CFA8FFFD0452275228522752A8FD23FF7E000100 %010101000101A8A8CAA1C9A1CAA7CAA7CAA7CAA7CAA7CAA7CAA8CAA7CACA %CAA8CFCACAA8CFCACAA1C9A1C9A1CAA7CAA7A8A87D2752272E2752272727 %FD24FF7DFD07010053FFCAA1CAC9CAA7CAC9CAA7CAC9CAA7CACACAA7FD04 %CACFCACFCACFCACFCACFCACFA7C9C9C9A1CAC9CAA8A87D52275227272728 %2727A8FD23FF7E00010001000100017DCFA1C9A1C9A1C9A1CAA1C9A1CAA7 %CAA1CAA7CAA7CAA7CAA7CAA7CAA7CAA8CAA8CAA8CAA7C9A1C9A1C9A1A87D %A8FD0627F82727A8FD23FF7EFD070128FFA8C9A1CAC9CAA7CAC9CAA7CAC9 %CAC9CAC9CAC9CACACAC9CFCACACACFCACFCACFCACFCAFFCAC9A1CAC9CAA8 %A8A852FD0827A8FD23FF7E000101010001007EA8C9A1C9A1C9A1C9A1C9A1 %C9A1CAA1C9A1CAA7CAA1CAA7CAA7CAA7CAA7CAA7CAA7CAA8CAA8CFA8C9A0 %C9A1A87DA85227F827F827F827F8A8FD23FF7EFD05010029A8CAA1C9A1C9 %A1C9A1C9A1CAC9C9A1CAC9CAA7CAC9CAA7CAC9CAA7CACACAA7FD04CACFCA %CACACFCAC9A0C9A1A87D7DF827F827F827F827A8FD23FF7E000100010001 %53A8A1C3A0C9A1C3A0C9A1C9A1C9A1C9A1C9A1C9A1C9A1C9A1CAA1C9A1CA %A7CAA1CAA7CAA7CAA7CAA7CAA8C3A0A77D847D27F8F8F800F8F8F8A8FD23 %FF7EFD0601A8A7C9A1C9A1C9A1C9C3C9A1C9C3C9A1CAC9C9A1CAC9CAA7CA %C9CAC9CAC9CAC9CACACAC9FD04CACFCACFCAC9A1A87DA82727F827F805F8 %27A8FD23FF7E000100010053A7C3A0C3A0C3A0C3A0C9A1C3A0C9A1C9A1C9 %A1C9A1C9A1C9A1C9A1C9A1CAA7C9A1CAA7CAA7CAA7CAA7CAA7CAA7C37D7D %7D52FD07F8A8FD23FF53FD05017DA8A1C9A0C3A0C9A1C9A0C9A1C9A1C9A1 %C9A1C9A1C9A1C9C3C9A1CAC9CAA1CAC9CAA7CAC9CAA1CAC9CAA7CACACAA7 %A17DA852FD07F8A8FD23FF770001000128A87DFFCAC9A0A0A0C3A0C3A0C3 %A0C3A0C3A0C3A0C9A1C3A1C9A1C9A1C9A1C9A1C9A1C9A1CAA1C9A1CAA7CA %A1CAA7CAFD047DFD07F8A8FD23FF53FD04017EA7FD04FFCFA0C3A0C3A0C9 %A1C9A1C9A1C9A1C9A1C9A1C9C3C9A1C9C3C9A1CAC9CAA1CAC9CAA7CAC9CA %C9CAC9CAC9CA7D7D7D27FD06F8A8FD23FF7D000100287DA8FD06FFA1C3A0 %C3A0C3A0C3A0C3A0C3A0C9A0C3A0C9A1C3A1C9A1C9A1C9A1C9A1C9A1C9A1 %C9A1C9A1CAA7CAA1A77D7DFD07F8A8FD23FF5301010153FD09FFA1C9A0C3 %A0C3A0C3A0C3A0C3A0C9A1C9A1C9A1C9A1C9A1C9A1C9A1C9A1CAC9C9A1CA %A1CAA7CAC9CFFFFFA87DFD06F8A8FD23FF7E000101FD09FFA8C9A1C3A0A0 %A0C3A0A0A0C9A1C3A0C3A0C3A0C3A0C3A0C9A1C3A0C9A1C9A1C9A1C9A1C9 %A1C9A1C9A8FFFFFFA8FD06F8A8FD23FF5301007EFD09FFCFA1C9A1C3A0C3 %A0C3A1CAC9CAC9C9A0C3A0C9A1C9A1C9A1C9A1C9A1C9A1C9C3C9A1CAC9C9 %A1C9C9FD05FF52FD04F827A8FD23FF7E0001A8FD09FFCAC9A1C3A0A0A1C3 %A0C9A7CAA1CAA1C3A0C3A1C9A0C3A0C3A0C3A0C9A1C3A0C9A1C9A1C9A1C3 %A1FD07FFFD05F8A8FD23FF530153FD0BFFCACAA0C3A0FFCAC9A1CFCACAC9 %C9A0C9C9CAA7C9A0C3A0C9A1C3A0C9A1C9A0C9A1C9A1C9C3FD08FF7DFD04 %F8A8FD23FF5300A8FD0CFFA7C39AC9CAC3A0C9A7C9A1C9A0C3A1CFA8CAA1 %C3A0A1A0C3A0C3A0C3A0C3A0C3A0C3A0CAFD09FF27F8F8F8A8FD23FF5329 %FD0EFFCAFFFFCFA0C3A0C9A1C9A1C9A0CFCACFCACAC9CAA7C9A0C3A0C9A1 %C9A1C9A1C3A0C9FD0AFF7DF8F8F8A8FD23FF5353FD11FFA8A09AC2A0A0A0 %C3A0A1A1CAA7C9A1CACACAA1C3A0A0A0C3A0C3A0C3A1CACAFD0BFF27F8F8 %A8FD23FF7EFD13FFA0C2A0C3A0C3A0C3A0C3A1C9A1C9A7CAC9CAA0C3A0C3 %A0C3A0C3CAFD0FFFF8F8A8FD38FFA0A099C2A0A09AC29AA09AC3A0C9A1C9 %A1C39AC2A0A09AC2A1FD10FFA8F8A8FD39FFFD04CA9AC3A0C3A0C3A0C3A0 %C9A1C9A0C3A0C2A1CACAFD12FFA8A8FD3CFFCAC399C29AA09AC2A0A0A0C3 %A0A09AC2A0FD55FFCAA0C9CAC99AC2A0C2A0C9A0C3A1FD5AFFCAC9A0C29A %C9CAFFCFFD5EFFCAFDFCFFFDFCFFFDFCFFFDFCFFFDFCFFFDFCFFFDFCFFFD %FCFFFDFCFFFDFCFFFDFCFFFDFCFFFDFCFFFDFCFFFDFCFFFDFCFFFDFCFFFD %3FFFFF %%EndData endstream endobj 22 0 obj <>stream +HYo;QZUjoӪYZUu !xx=KsQ5o&I$/3cC??cA}!L8Kܖ;unk\/-$^k\HuϊjꬍVaUvOpxUc^몇P-a>{`yw:JQHuVVV>'{e1(FRl8QhehxE9Z4'RM:Og8\[ TҜHERV(\AqŊXK:Tk˵h5fj0ݳnR`_bLqYZȎ=Z-V:H;⯵G$5Eܹ5B?e)mN%i95ܨRKהS9*HrRBJ5R:*sYs=O T)EglN g*4ɩRpzU~˺K_ؓm#ky™Wyl,ڟ-jyDnKuɪ +ۏyӣiy"X7 +`CS:Q>Ɗv^@J3 U +J)Xø=ۇܒeRWոNZeZKVe:m1~9t)N28)'8AxG\qLeO=Z$ClQ@ +QP4&ϫޙ{gDW +O_0N2tT'.Tvba%_xEf%#TgZ +HI,$״v7S&uO]%+ydz}#k[Gˆ`^֧䖷x|_9٪wZx_RabhWtN3ZKujNWj)-kׇh#[e+n5d"@J-E-&S-ZKHbv 8{zLZc *?T<})>Gq{}ɹ+ښNq`"̼T-\~(YׅZ*M3 C}͠߀ 1d5h=XEΗ3 }S5Ƭ9MW +4N EnT2XG)9SڰTaSQE d"@8SdӓSFo{ 7)jK!tRQ-H!'ZJ!5T˩p<=iIQgT7T +W*k0,ɿ H b5 Z:VivM5:'iW#`3n괛(DO )de:[U VO64纙x CN[:H/-e𶨫kS;kE^ H[mQE 8MRGpHC?寐 tiy~":B +j } &lBz}KizuHd0/ش9@mJh{uz|hcNTvKqb^Rb(ILtە\tずۗ3{0a>JDU!׉(JjTK)\rGA-iV,>L4=%(EU0Hr+&bgHŧl+k+[ۛrzQٱ8QCZ8?AQiG5TTR )a)N9z#6TF#P+.w(}!EbHRb ]R +R҅-B!].G^ק1L)`;K!ك ҠJ@-Ő CK]0^֭kkLSA +CNRiboU4>q'ኆA;>=H"W. +|V(BЙJtL)Yz_TOQ-OU>XY#ӵMKE66,ł٥)KiZ afC-]R'm![*R*) ǂ+o[Q fwܽUhEb AZ-.-Epr UIw*IԀ_1ҳ&3qu)ԯ( 'Rxd_ﭬl?^Y +|noml~^E-N';}EXuXs霁:TxR:tܱiN5ml[[ B_iҠRR )ɩCJpj634 mIR/RMzcNzWseH!9BU&w ]R[EŐ8 +KZ8cT/(ܩ޽tlu'qG_Q kC{R|C؟͕ ҍAS4W +<{i4t ^vOs r}b'n{SJQ +A:9C귔[_r٤J@-HQR9 s ulxk>R[sŚ۫a.a.:Hx)Ґi: +*VoR*3= *g\~3H]& + +Ct(趂{ ) +½ּ$/N~_o,RO!im0s KC9ŖQ}QAT,4J_9$ 5 Uѭ1 o|;-U+9HQ rJ[ƥWS )a郐Ҋ!}S:lhKC o,z[xw"?b`]18uG4ShҖ*m8HqAQKuĥb#n_mu,պлRtRO3 t}s} w-y|Ԑ:)4WB_PT@]j9Ŗ9 Ս(H1`=1mKJ=9.`8 BJ-$PZPKC9iPKI[ B)- 9塻ANu:ZyU3d"JzG"HY6YJqlcpQH.%8$lv#JpK??ʌӕ'?!@tG5|A-V ?PLqwi4ŐVד4At4u[OA~#%iLDR,}Ro)4`ifih4Ko)ǂtY`,HEvMz+D^t~L>J:"RtK""H 6-bze׬ u*:d00eеRFc&@ +4\Hс!MJifLCbN1.QBJYz[|y- SFPE@ZTTk1R_..J)EQ*RMȕ𔹘ZCCr`֒*fXXT~ (̼8,RZeʟL7YĹ`ǝ,BW)H^ώZg8HvS;VBB*xx)ٝ` +eNnuNz5x+V-nH‹-3g_kgsH|R Ucw73+˅=`d"bi*eZB&L뗓vCMD(f Yhy‡>tApjdt//Ёx[[[Kp5lC:48Pҗ6@ +]݈:{R]tPas;*^bK-U(TL*}Rn)[XJ@-5[i:6ZWipU"EۥjuR%{4xԨ٢DQRSQ+BGiI@hwΝ;o@T#8jJPSSTb]T VTdJ E?ӾPkJ՘qW3c\rHWXcDQҥDN+(KAl!ŖBQ QSPH+1N6Q8E֍" IydW@z-K?kKAj4FsReNm:]WpjTiXvKT.?W@鳑vyF:K=uV+eK{]lS 3(oosz!HX[Ɩ--i=nhPtfGUzYTJCI=5,4@"h Rt(q虙:SZuFpm~&'ba*F"7i;#R-DѢ;dˢ ^ (Y :F| _@x!Z3H4FiU8"9*+}P;H!J֒dQV$E<) OqFX%[ǩ RkZ9]&Tc1rR:3Mlt_'#GveN ˖2tqY;A|dՊ!k|Na+VKMH. ],0jў +\ҒHSsqeb'cX:]eHN ׸rƣ ^^ni.Ѩ<!iG瀱2HRq&N/y[!%ZܥSNkVs AJ P)+VNMKTSR+ujrJj|ZmQ@7D͂Iԋ>t ItR9l]H-`v5@f$He{frwbfx/o*j@:,^ԴL1EF lY3W&M:ȅvi6^)ҏi3zk ?\.*vAAh㯳< = +DcOS +H[RQiGb^}Ԅ4gi$l].Pmjv45-595t9PMKi). %Qzj%eBo5(:dGVHHwRe}W_o?{D|?,Ggs2GBJ쁔 ^e&#!K5!LB\pOХpՠ:~lH`)|;|}a~LQ*ΧBE}"p7Xr' nΚx.Π9KĞڔc6K *uyq #7v> t ӆׄj(R9H)n. +iSZ(ZN2R(C߄;H#`Q Y8&#hUq)Wr2+l7DQDik0k@OjW>]I9)Y/mPg?u1q@b8ݔ[ep~g\&8*s>p@āvj9?8pu!q1<)E(nq<#dBT)x>9j^&5jZ?n"MZAZuZ!4HS˱W[%RjQ}s E{Oь""@/? Ϝ9?R''ϛN::,wo+i=.;~sa)8%f˨sȲjWw+ +D>b0gK.R}'E0d>udb`V ]s [o7S+IlXRMRXn5#3ѥK/堄DԯʡY>dk$s>?xϾ~3^c(w +OE5 +3H.*G_(G / i/ߎc^ +ݘd>HXI/qdqJ')d8VxvϏ9J^>ಮRD|)@fKׅm<~Brf?U 0dC臁hF u{Y Hyὴq"15._@*EI%<.Tϸg3p,,2faQiQhH,Wqd h QTIXOdO̫{;OWwi瘜CZ 7Wq)o[1Q3m)mc(GLDlX(Bx+ 9Լ[i6E;C{zpyp[UZ2ɷ?@2Zoyl^jM|ʊ5()bRi0o=3;{?'iHGW@jw`_r#,&5K9KzhFqKi,&\̷acF5HJ鍖6t%gi-&a 3T)HPt_!Bft?00̈blH*+O8> RTK2C&`heNY]gT؟* -9($}biYSwHgwb@漼ꋢoPny-{]Q g-s퍖N#gȪF.8nTLvS9ԹcbW42D,i6&./G+6C Ls!0.RëBsq,*5}ۛWYe1܋<5}Fu&d,5RYz 㔧vmmou;˶U|VN78ʸS BV&i-#eE +b)vxdXM7?}~HߍJ/]n?鍢i52!%z;htZo;픿|L ]XzIkQY@ʏ . +j'Fʯ$e@i_|XzH]ZxOQ}эlƒp`韝3Q-4u,rC O H9"*YX:4}n\OR +}%<-=-({47= ~՝i%}$M>9,)]YK2ҧTbhEQT/%I A>8V*r*OQNQ#ǦaN1ub~NRH@$!\˘M(l<̳Frc;RTöZR N*ӆ~6ZmmSfd*[vt}A.zESc;b7ݸ]5Ϲah=$UL;hS=y'Ә9`2VOn~|OQd\8rtXRӽ'wH'U S^;xÌ*p6y8R5mu+ 4F3((j^}ED}#)*1Tv/,a)L۴k\6 헳WE9QU +o:ًj{OQJwk_N/Ӛzi=oZ/qODE?oq? y^oI5aRߢ0j~!8,Eٟ{&X7G}47޴ R^ԫ]jFM9tgJ&$iBp16G9 (MH{qDiڋjnէ/n)E.sSX\Ԡzt&˘'lB 1R&)XY:3,M8"(>q+Bߪw{Cʚ +қ.Bkf\œ'F8E޽{i_\MO!.^ +AvhVQ?{QyX2BRmto#ڽ`8Ah42]$w:AVKa19sv99JDT3A(ɭ ۏNIzVQڷ/ L4 9H7d|K9\&Vȴ* M>J5@TfQ; M/B(;Q;*ۡ +ЀNJnwYb5bJ4UxE+=_8A +䕘E ɨb i= +|J[SBՠUG +31:!0gʹ&!* 0ZŸ OĎduQ=X*Yދ&ſ.a)VMyj=%CZq#Jގ*P#'=dKu[xxC^"Sz hN vHwӡ߈2|ZM8(mBHΉk7:y GlYΓ(a4Z,]2V3lw~4<}e! ERR:Mz6?<Fw9[;d6[O` FlҍyN;=2`̲ˈ)H 1HBh;=@*)^WT# RdzbpLzdmb 0P|_[zk/-?))V\oF(>KsIIXfE,tHEFLU8xϘl'8k3!_ ==Ө~hZJ#}U:ckFW9{|:I((^#ރƽdiDL;a['ၺtoR 9WI!P,vsOQBl /#$TE5~_[v \K9X>y}֩,k6<R!dz4_zm~}2U1xb<5̇ϬGl͚ f$zEi%Y.i,]VnJd.4=Pԩ~ǮS5*Xjl*(hA + Z7SGG@q:O[»q ʿClc#v{?4e?#en&I+ȕcq[XP<UXN).7=,ȗS~o+"g0hR ՏӶ#Ӈ6$ns^Q(@*q1k"OB9F7neZVݕ7 - P߿=T_?]xtq>7Q JANI UB1dE ]TӺBVWxK gPG>X9-^c)U"ǓŴqNU(}7x!G;c-ЋZ'Ǚ`uou5w^͓y/#X{S̼S)/jduwݰ-zH #PuFM?ޏȯצ4b%/vFz6-*/t +Q=W.O=u8`SY}w\zߩ"!}N^PQ|F51,Jsq'mv+k@JoK|wU'] -EC$qT0Ѝ$/”2wDߺjbc~TӱmC;G1`inI*3] YAq:xS^a>?.?70TYO]TdW7MRCmvЫXG!kU>af4O,Ϗ-YR> q +M1P2-c,Go|h/liŝ'Y ՀMտ8gz\mxHr +: r$Nۙ`Z:hwZgFVS2Qc&+A0-Y~ᇯ +;0oy??'*QRI?Ϩ@*YSvރt =휜60<^|)Rt%%[%fآ~*ԒϢS_h|FaHO$2ǀ%umKQ5@f3ԠsK3Ս UW[ LƮy AsNAgJp]H{Z*&mqL䴹QeR-(B`)яBCp/q`)PPjʋ$^r}XYwIв&Y:;bz=(*HK}aa82QZڃKӶ9yf?Wh2MR]pr)vZ.9rEFn6tR}߷ŠضW!iIB~{$ ~lɪQz 9)946H@*5)~QX K%9Ԍլh23Ѻ\$UO̢C볫ZFM!ë#1xO7<eM!Ldm::rBʢcOmc}ϾZ, Yr*CMJv:Ъch^!HbnAo/aDNïOvW݁;끨HcrɊ~O-!4~GK%NST.k;{F RgA#[f )qTt'"IgBP'cd +(ea yQo]w)E%~(J( +8OeZ+Iu=M6kgRmf,StWR}~N8 +>øA>sH/2T(R +.JU'H!H C̯[7z ߶J@q|OWd!*V $?)ORDày|㭋h +7~cvOJXK\,Śym;_sW{|MfJ#ψ#ׅ`7rEp*Cz[i6x0xq/V3`[ ԙڋ ɐ\lVZ >rjSTQv*i(K (c7|2QpZr}.ꧨ~!>wiRLg rugwgEZD43͐B 2zYm f{LKRmW3EL 1 \{qy)r^^sͼ`uuH)‚z2&Rv 邘j|>娅D16֓WQH@z^y:uJ9yMJAMyB} luT^#W2+7 )*iR!jͥͅe+f,~wX|H?Gf{tFfNjɆ @O$-';Q.*2PV}yR[c)VxHܰe Mq,pߋQ)\kpoIb's+U̮,5/³Au.Y_{,{H,%CN5ތ'v>˻v0/)Dr"=]k+kx<έg 1r+-Ktd" bA DoD+HJL]l0:gg<{s~kTB}B!ha73Q-םǥԁF:/yZ +HIIiwǯxխ=^#.LwWQE՜;xXw;nmKK@n@׊y,PXw"^!moo'08!Tҿ ކTkv, w,5-뗢NPuNP'R`4Kg‚;t;'gULB" ] )2 zwήP/R+Ii? +W.e-|V 2G1M/[ @b!&VQFlFi&!D7 iR iyHʗ7yO=‰|Q:qkIB Ƅ[p D+K;Yu=gy^'Ee +(_n=CiXj$'E7,uWNvu=

D0]=@q2Rٮ1h)mKS3ۢ ot"ӱ@(Ke +jH-W+;muhԌ/k*e[CQ҆CPT&._Ob']-vyiZQ 56:ȍj7!6T<A5/Q=zokSiy@2"`1~h4Jg5OM1^`;* tj#r)HewiiN:/ 4CQ= iRIۗߴ2G<xC7pߊDbn_%_(/9ZUǯMb}ayt?s|=b8bxz~]ٲC]-}H>}ߣNTOx $5;&SD2z~ ]Y]355|~GCH5&ԯz6Q'T, El![B(Ԫ{\aeVɲZJ U&MG3Q{ #A >^p'QYr5GiY^> a=͹я8jg0iF^rqPǭ +nRRʿH/J{r굧h~$=(Oӎ5m-µQ fǐ/^NyIKtOMe\,4[Bi3zY14EWC+r]ܠ)tŐe;tBl<6FrteSJM!LVk׍놰J]x3qhG1HC3aH&q"0A9JYpf>h sqŒq 24nXEm8CrCF Z>`=`l)a2xHB_t{y/BMpTp +^6BuAf4؛@3y7la=#(cV<ړ44J~}7 +B)NrJ=Z UR-T'N(X!U@gvnzI:5Rjo i8K@ʗz]\JjdL)R-H/3w澄Sw NXɚneǧjyvĝ^@>I8~MŽӋ1s?i]TEM̀6AV7qO봩e_ #uub'@ 8F ]HDH$$o@ⴱMj&oS?; Т>ܓթm3ڹ\4 9?0Ÿ\dm'֏Bf/R4g<)iE)\әrRA@ +l,9/^6kRN!5|rp} ‚ըMV8H1qto#۫/yI1긬OGLhYӀ7X}tsVb?rN:95(Vo{8 {Ny \i FԴ>'o 'W )I[O^[4c\~|f\.N5`F:ry) W`cQKZ(e?-TP +r^U#bg.y.$=" +[d0"yZ:ZN*szud3=ݺ6gTGmY.KL.ƬsLqb?{e#ɩT36~j$yl:zq39//JyyY rq_)IܣYx_3P=qňq覾S~}ɾVu MeײҢ-of>_ }¦r*SG[TeXŦF\Y\\T( )ɐaHX +)FȻ"Ư@j_^d}@Zځtguӈm5Z]4= B(9 +zc|ڮk>փj̛OIf!*ɧAQ>cel]P,:]j*0nEx^1eU0.X,"vB@NCBؑE{T9ɫt{LΉ9' 6ܹsMHuClh  ]09;#8Ro,uK9e,n1 +Q#"M!TJJV"iTM J5_'R}^g60(ҌyAN w0Y{Pt}g 钿C=?esr0j͸!QԎU.鎗]݋2@zY]op+ -H]_Cu{kQ7wRD.4{ڐj~ƪO27dp`8=ͅ˳&Ct@Jqm'DmG^LsfЪJm[0w§e |\a_p`9 'Ҭ퐊4,Ϥ~.2 7rT7?_Qc]?^W*jLNVR-:eNG&!ʤL + -4ev?d8S/ǟyŭQeU30Q6 Hϒ~/  I@^ ݏHj>RXq߂]SHsAlI1l/I{l90 ~uRE1҂T;&#)L. Ʃ6 ۜDh (6bfFeբ|SH!LjhBBʩ!wDiuvYXbm{2 NJ1!ۜ.A_RHIf +Hh#` |;H9Mm~g Y#Cdr MERJ1ˢblR9>*&@w}-7L}|*48?2I038Y\k8UuiZsj.uŭa{od~k:$B*Od`H;9nxx(zW^H.ͪ%ʰ:d)s]*,*4]ĘV Q*tB+:}a)mﴊT@e5_-j|AZ <)ӘٶvenMu"TԒ!Myb8'O(or>O$NvRnȓ7.+qnH|ve}"m)[%_%_]=j\|߆37XOb.e24Miζ\u>2'`MH;]SV e Q6"T E +KMFpvN544pwmy?%RGU:+)#Tp.jm.S"&G}(RD;L./ )CZS[)bR_4 CiHHi8iu*c%d۱)C~դxdiͣn.Mf{-kAQܥz- U?Rt}@5+Y'_]iU؂2) )9' =J_)̖SwVDfv aYrxjR~nqR ce18d*YY1xQ\V(;}ⵘۻ4Tμ,iUs^pt qytDMd^`%ۑ-9t0cdzHʐȿ2>"^ȑ%EJciheἺͻ&JQs (npbc-ʹXy@^aN>gu_Z-{NNtē遢p\ڲCUuJ6Ĵ m4!ͻdHה5!l|!բT藑"( +l2Z###pz?5鷖.AkQ[,CjZqi@4}4W(2FFmRoa/eH-fCi,md:uMAɯ4[ zNV{jzLbjb) f` !r$Ѵ''+6p6]]m^&8峿=Cѯ97V=~έoqBGTBڌڦiRD~Bz E]VI\?1->|#Hǥ €ģHk/޴gthQ@.ڸ U㯛r"%-2}7lE#iVEM@j\~Y'ln#l 0WSe5U^'{u3K?ҾGw*A)ۜ%? ѩF2 9Ñv "Rي2LRݻwwa՘2ZfA:t3N?)'hu^ux.Q4}E0C|T(\V8mz2*+[MY>X(9^`K!kZMl^@Ycm/a #nH?pfjy&۶;s}fs /Q񳷡 *c6L SBg&$ĀSHC(r4B]N*KKKw܁opR̮D3Ng~-elLd*9Y; +V-UZlsBTmrѢ%nH1iV5|:TTŭEfU5N9v7o+)1f?'`S=;+8WA8yLXFP#sh~+RmxTƶaհl/c a#'72*b7Gp> +H0^qS#}H])m ]a,*q*p-o_bB+F8_`VWqOvh5k9ƃ>stream +HW]s۸Cf{I O3?l6nNgZV< EYr4}H3$Ž88|r;DxQlnM^/mOM/ߝ$Mk{o7/I\l='4_lw98F£lkY]&Tbu\ ~}/V7~yrj]r42O]yz}}ۭlroΓl,[\KrvOUXvvME\䕿_,?"D劚+ B[\v-aBj.Ŋ?{uǥWZ bV Yh Z_څg6y?kZa~򚦩O|_#K#̭t1?z +3}8RHX(p[-~vqq}l#Ǒµ/ kverUbof>[}46nmVv݄2[͓uMiXͱBx=q}{G[irqv1ǖ|F/gYp%z/ImT_Awz*tWa| h*,ď춛'7 #;Ǜ2sH 0㷛|Pg@v>%PO5nxڊ;B2l1"$I60hi96>W:(--D.99U(%#Bp E+P*Fq\1C'AG.<ê!p/D-'G"i]C!xw`n~m +9y@v!i 6fl)'R_iu|݇a"C/9{q]fw;@@Y`wvrLYƼf1ӔraK>d+PpTd3ECppKtOs5:&1ʈjD= ,!pxLuCe:@}CpGaL!&G:柅|xRţ`Vm-G{Xc/GMn e[] /ҕ0ezczL5^\/W:,`+x(: hIHKX4YVQ`. U[[W3_e7FKUwGܼ Ψ]#N{q7 %sF WWA$ (#ȕDNC*X6{\pgQ^FlkMY'h'\%ʋ@'=[.ZO*ƜK؜1lMG1l +!Bt +4"n CG{v˫*d3xe+kB2@1C\hE+1dFVyF8q|XZPŽJ_<;A *"+:c bͮ1WmGUSpszPvJZ +5-9- JSMJJD +x4:%#+!* EO;A?xÌtn92N[DkEJ>Ig+Rfk+dfJϿ|l 9t-pc@6p7Lw6gk6&>`Q5'k\mP;ULE+AC}1nW-]vqg_]ʱ+{8kky볳.g?-7-+uⲏiA{.y9(Io243 q +ղ8sI[jR[mAS܎FSk8`a/sFKBm1c4Bla{f~{b |8](I2R@f:,<};2&m#9^9L49a2896Wp΁1lp NI5jlr8coN#4&la3?شAS9)ؼ +6XNYp-as N No-asOWlʾ!6eߘu*جC69l(u،&VlBI.[v=h.4wC=>}uw;ڦ}hדG<?Ej?W`7ZKazp]iu?o/ҧ_Kx?LJK]2uX.3\̖b`N^-,p5e%ۥ6JbQK sJ%r$EV-2l,2uІ٠:i`\ Ӷ(zK!AkSU]=<q5Z^k+X:4 ml*}eOz[\Is{j\n v.+ rY^GvM:j-Yj(o7W!EU~y+^_wFxx:yD^6#7vb ePu=LpU[}dM +I!bVv\\yUuˋkGW%>ɌjpSݵԿ}7eO0>;-f۷ )i&FrlC`<V䮴 kiucz8eAB@Zڢƣxõd]y&0gc6ƌ #@t45546X͡ %X+׿SJKJ7e[ W:ﶃ.tЬ`LEamcᵋ/>t4Vk{X(e],M63}¢uG+/K湟GO{F;{T]_~yg\۲?yCyÔݾ ld/[^pqw؅* !|Մ:-<ÜZf&+V#pE,z$we_"ryg\aǧ1v:"f$IkEڵ)9TVQHWxS7 +&Nl66)$˖VGShYԼ9IlM4ڿᎮ{"(mcVwNиʑ:K-J-v66vSn.E"dx~gZEד-+Mh?U~gQoz~E~s +-*73!mt:^gYͨ]VnFK߾%m +DwdB`5Ӊ9MEEtyō}mH "P24y!l6(ֈ[C=Dw1嵖yC$IA4AeM䒽X#]wmՉjo2K'90 &c'6 0G~lbfm,  h9]03?B):FbAs0dT J (Ƣ:AZ + AGVJ bvZHˆ~T/5mqeD;J~];;"m A}s @W 馽nZ;X}V]p+p,gWPő9SΊK楝r%9Ev+;]94alYo@ZLYݪӛV򖊹(-\+բ1ϥķ/QC>Xwb$R҃]IViլ6;JJzXZW'Vʾauj.5g$R}Ma58ׂNYs\˺^ԣ^PK/9FhwVW(Pjl5s޶ުnq*^*Y|Ƈ2*ZpUl-FV 5އUF\R2E\BHwРi3ÂY;]to$K37W]m@ZvѶk;EX(%Ԇc{zH +e0blND% 18KLb$zĿ2n + Ν%c8'|&Bca-I/JX$Bidа0UӺz7-meザuO7gB-g.+ +GZ:D^p ~G bj:v8#{ +$x;I6ᜯ=PCUSwjf6@b2F凕G' ytǝG#哫YͪIGosvNVe*a4κQv:ILuxZxk-2س7e{٬$Ր~!!Dp(#KJ'BK#t7b~eur 6c]y1iXc39_=e~U6+F. +|ln}vnS؃ٓv+m4l(M}6&y36Lf +GFߡ%HFCx/ y}B?oI䜏J&ywl97i{#aԕdg'z6!$I$k +iHLvK&E WҨ5|*5i>9&v3(/L86,zQɨeK3*6$lܝ`֗J* S𴃾h^THꜤoWMfwͩFh^i(5tWTw,f=Xl] W<3U\x]ijN L;}؃ {ψ+f--sN2UL"Uʚ[\,7{DXBԮV`Nq* N +Tj\9)U\J-JWo$9;gE3Ԙ.ɢluK[wf PSXSa׏׷pݟq-޽- hMG< 472tA..~jJ?!&'ǒlEiC)I{(Ӿ"!ə+05wk-]]F{5Ź7cC݋&U +.Nh^eAS bSM%|C0(q-Ұh9F$vJL3} \{&͠6tgZniwB8 j'ھmxS#ZlP|~Tp{gصit=a +zWZ.f_Eįwů?{ :̖uNmtW6W;{ofOD?p]R }'F%_ځIn(WB`2J[>C'-;G;.?~3fkᆭD: + >3 g7A:5-ەj~ɞ4`},&]76ffZh*b7 "TLyo@4JS``2K 1F۠x09ZX-K>&Eˁa8j)5…B a΅!+;VV*/+Ks4Mҡh,&;jM5eQ\/$%" kz)ۤKYZ; +EC{qA ;/N^JE8BA dH ۧ8K7DKYfu8gr^׃Y~ͪQ +:hi/{MڟW6:W_ޥO{1WK~zノ"r%S/wg_zkC곊:^뭺8w{'Ƣz|}f;յoivaj,Ux2-{FAmlNj8mؓI cn\x%z}-O;ڋZ"I-[[:HSV.[]E /0$h%u}amUoǓuś*dTX +IۢF 3O;-vW*GrR.柮=箿yRVN -@%sWʟ_\'j?ԾZ)TD}?_Pw?4?×ݗ=z=s?ZluSq&9KWȏ_=~G?w:n~yF)_zί'[NœRaѸzn;n^A_skQx|#Ј)fi.uq<0gT3NS4m{))cJ12֔kx|;$g,)P(Fa;͗؟B{c5$.0| +p~LN8JT~.3]V?չh=QW8@_F]r۟]M3N*t +>K.%5Ў)-iDoFy\MEmHX^ bañf*6B6-cGEAs8g73jMԘƄ{b1XnHxtoS±ܹ}F+IJ][fк$}1 N<(ԽGmx:@&V!{K۞v-Pltѵ1Ycl +Ѱs`竅y2HXѬ۹)l'`Ә UZ{'Mi䠬9 "r!^|xPl-ztU1bG @wE:'kLK{zK=: Ac!!]jW2@FXLQx9^sNXo.8 ]NGrNPr:P.N;]ᱬqH,Iotv9餋w:ƴvQx9w:~`.Ӣ|!ӽ r9]ᡬJb.qxCnr:tm!mAc/}xC,w.^N]GNXt+([NXI#EXkuѮ1\VGm8glՙ{(SVXHiLNzS,]VG]eu<Agu\/~!=yC"-V{Y.xcnpY45Zsꤻ:eu:7:y欎^3eu:>Vi8crZ5iu!gu꨷Vg~8"a~:5t:ڇs\eg&PȧQiP29m>4949ݝ<͎8~YK8VA86c8Buz\iDjC( o 4Vyd:=S>=.w,VON)grϒAkm1Vgr;erШ4wݙb11.ѝ1L5?׺chN.evZr9ꔚs9rt9ʺ'rzd uf*ss9f!c!qEF帒pwKqv<ϟOc&4wV.nrJ<䔜&Gj>M ]js&YJ;MN`ILNO6O jMNf5G&'irq3azWR[p^! \ +;p W R[p^1 \f+-j B5 \Ӹ+B\9pv +kϒ5F\Q>&Wɕ\c|\v'W]rE\;^ OJ+׮N1>O;}7:[F@nU:uyn8t5?Yp%U6n0&#x[3'@`jM7S1Ԛ t<<.k4!#_ti6"a6%r,l>"*5rI!"^p޷f3lt KwGk@0/3F#_Fl#_F~"2¬ғZ2l6e援ɗf#ZNQ#_Xgzv>fff,e@q<ِ%c\lC=] s89ˢ#fS3<0n"Q%4pbeoVf``UC#S)k- +~>᧏o?}},@K}?}_z˿緸?^W|۟߿?W?|N#W7Oo.?^޼qLiX,YxGsttZFw+R'}cą68ɎZ鸮c7l\g"ΥXdP'ㆷXpgB:Qi%Qy'ι[e͉0Ŭ׆xX. ̛<(' x΋؆h,N\ XwQc9^qU%4sg9NXa/0w,<rEtv XKjd9Tűk#Q˱4ܐG2Efr,Wc2Y\`ίiؑGq9Kl0n\4PlٜQ xguGr r\0ε|(~a'rNX㱬S4Nz" %/YNЫ@kDK _~NHVJ]Z'=,G%)%b[g| Q\Vd==ٚ魆\p[Ӈ2 +.Kr~qYz rYm^/.{r9z jGJҧғϰN#-걼Lч"b+z裨/E/d:51k,k>B,~JAG+KEٖgx2Z,C_t=X=rj2bނggzn.C#k`興 +muކ>p^/97,7@v!,_֟ԭ !:nLcuGQmP\f/*uKT"MvNZ +tZaдI|鴔,+uyO7{L-XKzRfmFZ6UX!R֢LZJ{rjtoLG?Tсgѵ^tTN LN+jԲR7sJӯMR!z+Sj^od 5#2_qkjY㙸B- ,dž +uE;Qe4ͨQZ̨ .4o;Ì=}F5kZ6^J Iy.PjotwΨ18QcrfԜnQ˚S6ZZJִۨmԸEשRKs)5B2$6Թ5p5:T!ӷQKa0yԳ5qF kPԼF v]bBD@F14uJ=j3JYS':Qh9ApGȇ(~k9,E ,Z臥 QY*uɳTֲθ,T~آiT;3bJ:0T]?0E(1: > S a0s-RmMSlXű]2bڼ/篸Q:l(e+Z h(L#)n$GR̨sHQ2^ Z@ZG)RY g1aKM_%1jwXEFs7f5Q~FrcK-F5FqE5F(6K3k؛#F(GQ4f1J8/ wEh\/kCV!v˞@Uc= =C|kބR&PZ7*~ᰖg[AD'Ƿ;uJxꢵb|&pMoB3I-w7cD7 oG6G7<`*7)ӌm[h: mS8C[H&u*Dԥ&k[6j@ҭ6/ɊN袛ǎyMDIȸ&ueInte(mP膥9эFM2ahtZ$bP4߰ero(on V=US7߸ o5avM6M:r6M:d&$YohoJv|csjrd_6\tC2ppF8fc pdPpDcd[:%حBO6ź=ؠs_ز zyp,UV=qdYLPo0=ߐC-g +;/ׁ!9ݖPή{o(ZrE9)zʱ>s1gk>t'{t'CdH15ޖ@7tt`nPИ{p8mss/Co9;=yox5PY=_7EkЛ̀б8 ƃs)wg<tV!}͸!+^;D,q'MgɤO:yt;ұt{jyG茖;:;m'7گkҙE캲C:XSlѻǯthVY?oH ؓstұlU|:cvU}״<'*?#>tVWpL:8\;c=]9GawZVU;S98qNq;{*C0S"i˔C}eS:} P˼;L~Coq9ԫΡa8^K9UsEؓ9bsα p(αsqkߞ}uWgSc*g ddc=ƮaMr>o? ws +>9suaܺIA/u<+c+>oԱnNTP˞ey\xhshԡsU߃܊1V~Q%Ճ:lO})gfnɇ0+VPwJ +.W'sirϨXSpzEkx̭dq'J]襙[QfZpV[EL,jCjdne] ̭€%3C=۬֡7Zָg0~T՞:~$9[[M3ʅ's+go;@U:92-;Ƴ6'2;|̭txbQб>xN{j53#E%:\ 玽_?͉fkV5a0qp#/D(m~ࡁMxOGyLul===6f[k|!|ygu_)ۜ}\vK,ۊ5Jy o9Gts̲gdwг'b,/~wQHR,F2d/y?J=>cI3IM1k5O>F7qZNyL\ʓO"{i+SfϜAzM<~f0>=[-xcY/Xg|OyXQ*<|#6.juJ7`6RWIRYe?"eK".p k#c!Etyl 4HԝsMArMhL&acT)bD-v@++ +!:o,T5^lp0";c(t"dMk1B4z-9B[pMKҢ8h-َݯ9 8G;QXӰnm5lGB_!QLڥ!uMІƱF3.: B:.cd38L$$t%iy웨U2'F95ex5g!CVO=+H\JpL:}#L)L|E(cu&qK&.f-u 4Zp'@a)N_uV+Ӑ1tFYUU8Mj1x!Uw4H{Ysj5YqVAYp;ҲkohC0%y6iīg>lWQJgSA)4uF) +l~P +;(LYJGai䝕K{0,h:P#oSʜn2)}Qy +]Fy, 3vo[/7Pk TЅԄ 4ru 4n鶀JSi Qi&*tun<.rїoR2W)Ikq*32F#]4B#iJCL)0e0[L0֗>14-aJm)$R 5rҧ](Փ[(b7T1^Z zhƾI]#)]H`?I[w R&]7JqHHަ2C> i\@P9JZz8JmO5FsyG(XSN9e˳9PE8VP8J8bz#8$8|!NqTqÞc\8M8.jN8Xـcx VpQ7uMe "]HwJn5vksSf_ S^(V(Ö݄cbp;7X,`Sٶ鈣"Cs6'm2^N X GdB5qqOkqB(V7(k(82/)qzǯq9㈐fN|ZGt1NӪ3+bӚHAgr:esA9eCN9U@2g/)ڦdsȉBi\_(nqӬ;CeE\%Ա"o[tHH:hܜ"bf頇)]C,qFt;BpA`FN:fZ//c'R˻ybcXwOXG>stream +HYsX$:,d:IOı/c0`&@lIƘ}_Ig*Ik+rWjjnN##=o| /_fsѢ1j%iDgbfc#Cڽ_c}|, 9|\Kp,fsGQP(J\-WjZh۽jWivJ)Q'jڮY$7 uJZK 1;H7D cdݫHsЏA]/kԭQ4}qJ b\CGfau K%&ysv~̄ن1s/b$Qyq05F&F9Y>x~r#z"!|e-2J|V 2cGv=U=i[%KƝ%-1% !njEsLD, \7H`@X1ͱ(qi>0odr~IB)&aUŐyR\f+y;3$QotťޮW6G?wQb96cyqiI+q^^ԗYOC}GtnM׫^fcO kas?@vZ ̣R Xb;`jj\ ]NbǰKE79}\wR ;ӈlRi/`V\W V:M ۫I5inlZk8}ĩ$ ezkuxr^MLjq@i!]lւMftbn ǂG$$r^^^C +׭=Bj0@׃))U1xbYElEjW~$?kV~`wa8;#i˥!-)ҡGs՜ nEA((Eb$O(J)DgϞAǏAћTFHZNUT{)P"uyC$WEQ:rudw=ZR1 +)HyK6ҚMjQhzUQUZjA6SdAz)G3lRJJHr"| +sz8MW[Hמ ) i/Lқ~†* +QpA/z H)Ҵ>ͺ$$lFkTV2:)vĹFgLm$ixnKut(yH9*RX>I٢M;oCE2,bG8&a2dIq )/)}8 &U _`rԦ@QԱ6ņS+eRP:0aYj!W!pV/}3H]-jbn U"b0QAETǪ@hi/?6:yİF$5JJ~Z@ipRLy^T_[idy[I2y9tz&=3bt"BPQ.ւXaYEP$j{N1ͷ0fw)[E~ZLc +ҘkǦ@LQpK?52D$.׃`-wiv̡c868s,N?DS"t=w/"ڶB^aap^ٞ7 4rP,4-7,#yZ;16Gʐn ,ӊ>Q**Fhm4EHrT*}HGcjLN٣3EK/EPQ_K(q4 O!fٯChuQy b=*˦mUR@*Z +HN,tV9=dGlpd9U7s3BnUɿsoVt)$7!җ?-څ=0+ܱԺY.,B1NsR)|*Xj ]3Ay}׭IԨe=BVC%xex _R$=dZtEaY.e\F.%^ mJ89/>{'YJbMZ `DPױ:9)H9)xo{R9k;C[k:Wec5lc78p&X%fқ)H )2$2lm/:N9ϰ24i"i-[ejA:ahX EpS@4膽PB bȥ=@ +!F"34KXQ;aX8 +!Trs0ap*K-TlcJ dxYbů'\ԡvݟ .~PWDž?0uz?P9n,hs?ꅓsiK2ܗա4> +?FX@N+DQ`Tac(lf%TP<{ɓ'hG"j[krXPZ@u:N[*.G9~7)7ќMY3I[}hUR->Z]+U"V!0nk0Vu?^@%TybgЕ믈؁+!ݹ9~πH i:ZzQn +HiªeiiEbQHo;{{Ugذ}ka)P`gTPYӚľ5 NKbV +^ԓ\srnMز$1DUuדXn.Q\4l KVde:9! P—UzRcGExw|MV }ڈX!K?C=zaAhxgiKNac,Mp6dy>@*QDR4,,u8Ȣ+2 >*~ojEM*!Ne:lTKK=~梜^$~nv۝n K Ѯ]V4ʊNi;%)H=8T7H*o6њ_f_?A(Z(XОeLR@cA[ېKW-ͨy*kGt)g'Yz BK^ [)XjX9o`2$$ Ej8.E#Ls];^}KTҊ4|>BLj0z9Tom9fALȢșA,rߝ4% +lfB@ռĤG+ BZ/,ƚ4Әe#uwT'b&E hQ͠tE"&w^& "OAfS=إ!Թ ++H}Xv& G|tXNJa.R͓ZfԸϟU+ uˣ +w Q9 %|Gg{zs80?yV t]"vvBG~Љ6m)uBU=A(_li,%71E34frTNҌ0Em5<]b@V$b|vnMܢ1,텀rM ;+pgecܛxWbh4-@}: +H߿봗B7n\vTeR%c+NZP?W,%qLΠlVORJ^?U+hRSoNV;q`گ1hh{H}B?3qqf^益x7<׻?^oEtNe+fC3TIˁT۫"Ġ f zayQA ǜME<|E-h0}5RA9 0m&]7{V_ Ũrn): ș9yHt]T& &h3U%nL  e:"jNu@h{QA%.%CѺh秉߻:\%MF9РݑoԛS9\JP!L:hN({̢b!X)zVݬ Yp()"،@D[H +75Nɺrq[ +5Vf4z9(=O]W@"C@ +Nwvvnݺ +RJn }j H5UpvE^iyCPf29袀JVIXV_jtlPVunݫNanTgT=KvӫEMÈ%,݈`DN[t;Jbz +p1a +> +i!D] %ÔTy@N~XH?>6 &Y6D`88^xR n߾ <)TH%gj +euNQS|D 2hA "^jRFkM2ţݚ)|kX4N[&k/v$uNStx4(tQ6BieŜ Ik'̴ +08mc@Z +%LDԸiX !3HQ9H;2.Ptqچ X9cxla;& +ys^d +1w#Ӽy'V(,hh>Yd$nYT-w^:>+~nSwoe%tQ9~:9X߂Iփ>K&)!X9Nl,u?V2z'3'[8]AQ(!*3xju;ӘtfYY!FEk?|-7ʎW.mFI<yQbVcx2lg$H "M[,dou9Hz.bY"HR6R"C!j)Aqܻw@(8}-8}ӧOQP@'t氈&axؐc3ul7꽨g-662[[;[[[i cjT͕Jinz_~crg)6d)V]|tmBw +ZZ *r`Jh,hUy!ډϣ6@zc5r|UPk59.$KG#4nJ ㈇T7}X ȴaQ'~G!oim1ь;A>DP<~z-bV<4qcWf@4m\x. N +"o\3[;8Prtr8( +_333BϟRIQĐ+,+E%yמtw#;'AZOyz.Y8"n.&p6[x'gY9h <)GA(\tEBQ Et: i(D/B!Jǟjy{F9ۨu:T$I&-> ͗|U=[w?DKxׁɆ.r2%%D1#0nf7A.S !#WkTmׅ#^&$l~;b̸o8zׅ">_.F(Z HZu-Q .xj 7^uRJ +ѡ +2HڟO. ~1N$4NYDzĠh5O/l6v3ϱ0 <]JRQQd`Lko/_ٳg#$Q&HoE`{^E3b{]q=MI? W(??T5DKգJVo6vT^x[G+S}[hy+gXI]_eEJ.%Tks4D)V/ЪA ]HHi(ջ)@%@AQt) iJk%xC4=>iTơCW(['i> Ez"#(CrtK =7T>1@ѱ P"eTom>N +~s7M߳ +,S7r;>zkkVo™si4 8dEjÑNPVΎh,<Ԣ:` C++?:j"]8pqW#v%{2U'dbr@!BB +anOŗ* r) MMM*aKKSWWݻw~zCbz(R©4%-e\A +y®`LRHә<,s?o #miZَQBsNԵB*T饖J +sTR9Rj)S,j#![5sv:J$)f饮J,RJ0 yAO1n:d$Z*Tԩ0p%QB[R ڸJAFob'Kbs~Z0ǝ/>ڛ(={O'Ɔ %/#qVnķkD_IEΙ30[x&3)d*) +G( ҶܼynQ@k 黽}Ѧ1X4u@1)ś7;P4̓ť҃;V?yџ|ac,Ԗw`Eg{mɺ3,.-y bN ES֑-G*E H)TfR&.$RSrQTBW\ԺHQ[*Wcn6N^V|j?|?[佚_vu ♻ęKig^.~abw6V~|r֣Ʒu9L,Al0V -zRj0QJ E8 QFP$ ҞihyjJNi?XC*JҁjulX u# B]H(i.+˸$G?8_ݚ9gϢt]ctZbi*TNjrT$"iRKbPFpJ QHk$@-?.U)6(uz&)di#^*|*HCKWxE|T1ͱ8< +7m.$4"J 3S鑝QwyZ97bʐEjZ?F+ 9P'"'z GN ? Q!?RJqRIE%RQ@8|5BCf&i b eH B&9~+ğo<CC +>t}*9V=xvҢGU`UlG"^)RRTHbyK) +XĩX TU)Y*^uETTu|T +/pz*)=aQKxϧ8iڵ[Y`k:=Hli#+4p+s <"=]森n;3j4a7;ZNo[mO Q@#މPE)bE}}} ~6GݿCN+>>#ӭwTiJ8Ef8@#(~[Pt.[ q'?* +UO|r5s'߾h1ƤuQ- +>λ]BrK%uЬՐT +B*tYRRŜRK7uFrKŐԻ5哧dFJ8NGwdEsZFw8!%hpVcEvɯ]ql> nMo ne +' ݋'g|/C(cu :!$h:=<DŹVgH QZWQ/Ő +R?|uH^oH{ .`k)TN rKv?59p1Pt(JFS =98@?:O;knYd+LgxtY>]`/bTŖ.մ@?Z j:jDO*E hiHhYYTSZRˆ֓vқ6攴>ΠIwyEnsSC8✼)\% vHGufn>[cIRo;RU:dG);?=?>%_y%aOQG.CObgOMQ(;$EBQC.t :Ni+QsiQUY&=y֭[w޽a)ziv*TNPx$Ptz&Fy6Xzo '>|\I:{Z44,o+6e$kZ6t +jEK 8U-%H RiKuBK *k*.;fC#1 !š*A*TNٝq!{CH5U)K+Zҟoe 3!̤u!\3Ndݥvc3;9Xv)"vRpN=JeJ-+PKUI2E/%T"PRZ`<{޽{R~_Cʘ叚݀Tҡ\8Etj-bwFÑhlb&B'0g2P·R/pŋbN?άzBs!mǚբ{rK)ElSU7 kVpfi9x`1js`z3v|IieKBK R{.PyjUVC蟯uI2cXhNtrS.teX'Kޯù|jٮPv:ݣW_XB@Y-jEdjmiAZ__Ԅ; B܌m͊*BQd2*T(f8LE`0F\./hhhx۷!$I:_)4MJLKJ2QEJlĽz~0I:::6HE'?|w$''WC)={)wr9@noD뜡1ehJM2Dd)Tf)qJJq +꺻~׈,脖RR*ۑR-_Qzش1oiNER_+$\ɩTM0KK X%NjKQ!-(X_ cmK1vk7(Էjuˏ=A 93l* +H[RefRwQ)jX}}}җ/_דϟ?>7Ҧv5 }CӪf <P4Ht O&SGޟ_\EQ.J/)ϟl\ZL[} R@JYP𑶔 eJUSKu,BHü!=Jވ[aN̲sS"Q:RVH4kr ~2xGT6->LP9l³4 jY7lq.MS皟JHqbSCުTQ,IskG B'%B6." +Bz=,dSHÇNTHZ:iB eiTѣ7ZNwp= +>o(6219hk뛨0'y-sNlߓTb;m6[,䔕fD7K ү2H,%H U_lBH2HwbO\ PSgoԼ;bČ=)A*ũ+-%H+Z*UP+ZZ BK_eΌgwv~bx1 |a$5냥PMnLFNaΤ]~\٥ _>>v¾U6Uysz)--jO"TjG̥!Rt:XZ)(AECCǏ$IyxH}Ĵpo'D1aZ)VUܪ)d=N9=Z吪I!l x Ln! a3`l [&3id, +|,!~B/_3IRGuQ. t'6ſ@dȝUEf;k͘"ӦiSc܄YDuCdK$-YBȼF +vѣYtiYK2DɡN$3G;iZJڊ5~RH1UUU޸qW^O__tŋ+ j[jXZ)r/jq*S5"Z6Yt[{GB!E~,x2RJꢘ~(針6u+4m3FGbL68q +HiJqgSu``\W~Z(VBѕ~r>`LS(jqTL4q|W6l}/]`G]Z)Hsi"`Cpr N=[ 8bzJ[49gcf d5ԣn|q^Ree_"qRNz b'1Oz13QktÃL;\b 6@ ~1権PR1M^ +?6o޼yڵ+W\|… ϟ?{3g`#*;v RCOwx;rДK)QjW*mQmPӍ$ׯ_`;R}ҋbOX*ENaw̛vC?u3zpj|%,q:k% @T\2.0?>:`Ʒނ9P]Q@JXvs)USS{A[!}m)E`?LԢG8V[=duԁRw}ܕ ;H {plReGHNgQMڈ+g)SXܳݳw?^:c}LNvYM \NH(O1b"Mx5Z=P" ܿƟ/o_W_銓?YVvӲ>-XfO>yt?'+ܻ\I5_VBNsas%<+V!B⧪><|,q,ku9ل]l2;?~b{Mv ?TMj IBNg-Ҝb&# +;Z#^-zct8OT .Eح\]JlR.y R5($%:[+!9XZ~)݃4WMQ#18 jl^|wcƨtuX9z_dC#l݊fѩG5ţG/EiG,M<Eo!!CQے#Rt7[xl`Ї*)|DžTNJ_[ #t}<.]ܯa"X'``Bg蛧i@ʟa cRy%#t77ebNSG\œR_gOie S]NMWk:5y>N҉Y5싨;7 qgdQ\'c7@`sP85U +pD)H*EBʺf\#U?p.|Pt5N؇ܸ7E!Mr5NpXÉr6ܛn?R0ttlr*S>..KI,M}%r]͋#H{|F( X-fr r:dɄ4Q2EZVW訖%1#W/Hlru>Z +EW&9Tih7G@L/Nj) ej3JtQ@:Kd^K" X$} +pjr@/ ʮ[ Cvvx&<<>/85L&s3qҫžA̼ǻ]ۏY8g$ MW|A0:nI%L6qKSB'}6ɧ iAaaRH +ie"1 }Z!yZTR"jh[u*~,E&SwGJqz$7T"vxHm:~@OsRp͟?܅3s9EɬtVQ eRHTY,%g)R_?缩ݸ+uuգBQX6.jmT`))@ A‡o)R Zʇoi֦ fg3 ;F&LkTwtgy^R52Zq#iu;<^@/UֺOBJEi kQM,͵Pv}t̄`yH·E2ui0_omxa 8GzgwOý!-SI79XI_=J +EU(*,Ci) ni)UҢըrfdKp^p#Vpd^@QL)D#BE/!T+Bh/8)P0{5ogcGlz~- +)NԓRR +iVK/)T@Y߇4{"Dghܼ:ٽwi:"c{2ɵ>i7U.)N5xe9,dPaY!rQHڸ&谦0I٩J-|7otn@+(U4ϐ怔N$ b.He +e[[[Wg]PeG,J/F|;ഋNtRRGyK,OR@Qj"*)"RQj=&/ȼ-ns p᪠f ALQ,NM 5s!p/+n$04stҵUs%N)۷^zW. JoDWH1p>xVHT𼒟̂*[@hLP敕ia_s$`(ƢH 1 =Ee9RU J#E鬢l|¥thx5T_턺ς +?M F 2i气A*R@o OƷ܂P,yʇT}\P\Y!fI4Grf̃vCpn8)cFw:Jvo@uˍ XGdHNȂ%VTNCj+B>(]wQ_2NθmIn87nMQ + uTxV*O7[+kZIdW5RX !W ZRU\f EMYm5n]ZYI;Er[Ӣ*,A%C> )\ +(ϫJjEuolb1tNvQ%l:O;3:C$?CQ + tQQE=CͿٯ4 I7fhjwۦnmU00TЊ_(VJfD@Dv{&ݪ80mILns'qf^^%lV@J6¶Mf)C-U.x $j4WK˲? !SR@JHӯ1W#RY5s[$Hz/A^f~i)L[yT'"O#%7 n>aVTai 6K3s[_FpuTp=JW{+Z*6P;əf/Y1F( +KFDi-,) +K)vK[d.r%%Jy0uqCp訄qtwUA8m?uA $ziMm&R|bޛS.j 7g|!E)eY]&K+=J7 iSn!y!Mw߈"_yLwG':7I~k!B:~#=iHh9D!1~vB@@d&@l8/5Sif8m`Ρt8=i( ťi`PQ3+ȫtto5\[FJ9=X !-Tыp//!g 4BPEvEDŽ<sJ~ endstream endobj 11 0 obj <>stream +Hߪ^ ş(g,ٖjP(ha:4w%dB'I^w-sB$s-K?Rtǻ_oZ_e uRkIm揯ӥT0ezn,-1do42&Mjp%H"-gnˤbJ0;V1m{*Q0|Hqx !͐T/QVfE[>:޵9->څn$51jcR{0,V:GL uu磘K$FwIC${R4ӱwǭE*Bwføj/>#R|c|&%+p^jAt]ʽh3Fm]c)M=RQ/.3LĆzjdB!IԦhؤ 6Mu7^%u{LBl +\-t*5J_>x8~kn'RGUf@ϭZ61&xeV;9d="LJ<[L]Sam={.}ّk?.[E@֘Os@{nFYZXܰ6 ps7稵9( s|m̅.\:朰bYsԣs9oqcu~p ~.Ed\Dݍs9a23szt=8'3f0bNEIrqa8"lڜu9>_ۜ"js:6q`6+_?0G9:ϗ>g]zV :j)vaiu3=@s7@ ٠K?@6( tԖqy:`$b?R"tA's"T1=&JQ]juLQpITBq.*ԋu߬ ;X٬.S6B!Y `l^sY&9֙i7^M(i0&3`*8ޅ;JkϸcaYH,QGځ;mI$`qqƝs߸5t_\751p Ց@0rj;'6 Ȥq7cngW7فΏ"f`Ϥ+{]dN0muwPͻͻ+h K߼;j:yG-8o ;Yy'X^6m;^;Zw;-nq7.I;ImaRv[Jq;Y!I;dRw-.aċ쐜 ^un0{;`njH`aÎz<`:) U.`oF;pجhFCz. +jPmޝ]agr]aרmXm|w~F +Uk0sglLzO\1ts/IU78̜A>=|(avm^~0o{j0n)XcLf!}XAxfTÖO~jV Eotm @ŌZk-Q]n1p(zjäJ% P$} yƒ1uY=(D?Drw{f@eLG:&~OcDqU^M2u6`+g%yGf"HAq3W'RYTU7 O6䴅 c|#@y $u-4H`]ӋDZPz=_f a踻nM +o>~[^o?W_K_חM;w?o~?x_azXm{v +t ?.SGiCR61$jFk.]>R#mDA.&| R0,b 448 AJ0!ai"qS>s2bĠwB@(qKHrA9bx-.s M\> DBG8+Z2D҄2  R MEgnriZb;71lc^poLX.^AmHlq;t`5uj,"@ӵM^~1Nix̴= X95[,ۇ +iVfD&vڋSh5@sGQI:ۧx@'#m2,׬ $P;9[ #"Ax^Zƣ*DCKhk-7 +T񅙈H?A`X+mhMk֚07_l()'Fac^n +[vb53S n +vp&5YJY`)Mo]L0&KГEYJz&&'L`SƬ SSDnr S'䕩0H4i?hj)7MF)yJa]钫 wtcTaco}I)rMJ=KkR:as$MII=ERa<)gER$_HQ?HwnꆩMM~ۏ7{[ԍXq^@ǯ31:;cFJǯ'-ґ)iVKn̽q*qojO1谵 i9H kr:fӔ1i:S12ږ*b+ß61CMN?2z7"UUŖ9#ce\UcġtpyҡFt{R:ܠ7r􍫞ju\U63jγ%t#˴-yVGKsVZ_!]5:=Ǔ|ҵ'2@'~W=y?CėrykW= GÄyx=6XF1?]t^kP:}Ց_tLHɛVR:썬FVܞU|W{+f EApNINNܙ*odȊC:rZn s,D9^Ů̪guĞ9'8!9 cηC $m9vaω>=<sgeIɜĢ ep#91rۜU+7S\S)aɢ +|{r[SNIE3Irm.y7)y|Q9ۢ+'s){/ydγYɜgs^9ϳyvfqkG@t}ij-<sC|9YbŠ!jps 88WaW~"&*aE9>+a=9c;yczUII~}7P1YW |;۰ʜٖ`=Csr׏9ɩ#D2sL;9r\8})9qIoyMz+y䊒޶[ijorY'׎crrşhɕW}+EOǴj:ciBg\h?GСfcorEޕ9/yW49%ZCm\?smRw|叺_3J]s45$G]7z}ڳ9VVaon9mXZ dV07OzuQIz<}j{yHC6kP:gaf{m/k -KXYB:%-V'qHL}ֺ.D;gv426G66|>Z|tyt\"_y|R{AeKG_f=lGzpaPBKH6_ϔtK{*Z-H͟Q +.ZhHR2%zgQ2-EImR-v]%վGFg{9,9ƪ Bݛe7b=c,w$;'Z9o!#XJъbdEyOϢyxoS"-)KZM ]z3UAVoo(-gt`\!A9mv&Ze}n`g%LipBgas G0+hd6(dMhd.t(d `1z99y[QL07LYJRB?,eh`4FҸROS|Yl)Vm0垕t` ;Lna0mɺ'LC )4mWCMԝQ +zO"4fRkz.:J[:[qB2$)B$န R.J &Rk"Գ8G){0P1g]՛[srL 1gf|bTzMQNx)]Yu669E LnFh2yaYPCQoF!@:!uBf(Ya( +֔X{ CZNnAE8lp5pD7F7J oŴ㭲8&7|MoИ:ިɖ'#78Gi㍲n\MUniƋmqumVY\h hh.% mNhy[mتܟtC(ZnЛ*Z\b z'"[;jGxCs6tN7r1tF1o1͋oA۞c󍺌rM6g%QWM=3|S9+1፫=Mkz/Milߘ!o$4VE|S|MiֱZ2X::/1kN8U@N8iCNԜp'qNJ ':,''RwG +Ԑ9png'!8s1c!G=L; +KҮOAcH9ik/rwNu)Gz(X +Krz:)itf]t zNŠ"b%6Cm/!{. L:\s^sZ ݜn{9z1s3+ ::te'3H teY >AX :{N::J=3@w36r)fktwtl HI ɵ^c&UÒHW6sy_SvIGi h/!VgI:eVj" t頓ypQJ4oN:НteyH*Rog]2l7ď+0'nsDsoNtpzy8'8WsùR]:<\մt0ǹnY8WΙL\mc\)k:j#7訛 :xwj{qn ta[K.fecIXQtm9Y#4q}r&c\gy:u7zjDtu\}.7D+B@q%U Qcs&qBaz: sԆkr^ccyq6@gcL˸ZJW.m\ej21CwA:fR/Ǹfcp/߾YnQ31g}+c3[M;sV&s&K ^sL:ژ3^Vho|b!b樳9HZ@$ [= G8Ї`u3G]\qL{er0zx^{8quqNcm{'cMx2NуqZUX=_CRqЛ_Dt;Ʌ8ve ]yQlA#˓qMU A3q2y +Gk8hk<PKi-'|<%'lA4 Xk '<i9jIc)̀^cC|AΞ]r@Ƹ1t䨛j@F  rv9"S9Ě8 ry(gsH۔̢sI_csF>sǸ0gN89CQjl$94%8gzy8_B]`8n:ݯ?R$*S.!.VTS=꠷' Ա(۱WoNM.qymcZPkQ 9PY=|+$l[Y<:j PD˅:pDF=@vVnҕ7漻ku|Dd[UE/ԱXʎ:jDxnz|+t˭K|+B[98J=3nֱVWa=Uh::J:ucu| Gvg\UVФǷ4n}VgH Q7xLVK1hyó =ߊfCJS tD m^c$穁XSȢTbeJ95 +qӫGo%`ntt-MYN )fY)v8ފ=t*2;DՙZf@q _y%U4q9_Q^sPYܽ'5aYS.߱MLqiw?nhr<y!wxYy=pq5z֔=,eO/ 뱲t:@Vߠ8Ylz9ЧڼЧ+=} ȳdݓN>9A }lؗ>ȧF:]ɇtc,-@56=g.c8 7^{>bXSVE x.;^t[tyJ^-~3>~k{Ce<#~0 1qfݽfF@;2+ ~/?|ח"o_珟ǟ_>|~x }_;뽀oWOG{y[Od߻1= 5tWl++T\ &@ uaZ^MqkO?Ĵь!&nj1FagV"{,! M +k-MjU쥼84;$@847u'Dr [Bf_qHxfĚzD =;&~Z9y(:[n"V^j'=IN6H9S62ګxVb7-)۾ Dв.Wkf uVu!o6( +rTxgR:zY+KK{ZzT@o2){F`T5x* Of*L@%TPk xsx,"xE/]o @P͝)xPg킊i8Z") #2>SsyMN GL>NzMQy<)wSFN^g'-2`F2rK%WS|f/~eR~7MJO z/K_&0rJE㓔QcBRcwɕCmJ>?JD+ܘ$E\WIQ oAgBcC&dhVG(s\5EX8GQOەcr;cXR93{"XG#c/qi'y,C +1J +\8t$qjE8ޟΞ8qz %MyTul%o>)}! ) yϳS85sPS%CNyruS8ԤCC^(ճR8]q?☷X:R8sp}+czOM$Sc͞1˖b_3Qq'5K*8݊+C,_>]C1; J8xqd|s!k.ǑC3D{]+׆}yD(Z<>S9vUN?uiQ(r3+<]OPkT0k=҄y|x:tȊF̡wv*#c;n襳`H윗&;a1QeJ<1K,Yء'&MMVjǿbjZ;C6=#cnV'WToNz+Xer|[&vr1ݺvƛ\iUv۰OtvXSrr|ڵk]]GΝWgWtۛ]װ$aiexë2{ڡ& 1kjo|Y#O֕#Ǟv=疧kW񕷧:>ߖӫsu ?ÏuHG:ݝuz9{Z|䍯ȭk_ǧu9o~#굾?<+1ͯۛ_w~SfZiúζQأ~a:Q,+u8>'A]!u<6 ,cV㲧?c YNyC^=p.'ڰ߫J:Gt%QY:~I7R1)ayvIťQo}SQJ5.}iwYn#G|xF̽nϞnX0uiu?pZڊ+f"N[C:٥XڈW[[3Khk?SXtّbd;Y?|ᖺJGgG78:ڐG-Ϩ:5QǍףXߟR5$_:.γُgs,YXstֱvM{Ď<$vȸ:Ų6oO1)߬Lr)r's<:oev;f$v#bl;~.RXj#XDSX\%{]Fb7x$W51vvZ]C͛и;F/ءg9]Bۑ&v-?5a{S,4CLXyoeޕ:Ǿ!1cbpꘛ!/-?wby!kX1%ǩC,b'QwҒ7w87 )c&v1uG Z3s\a=L1In;th`Naaqa?˥e[!غ.ƛENC<Ć1dj+@ L+#u?;pv;w(;=ŹnW Y KH\o%rzX p`۷K % zX^q9NHyΧ~ea3lwЖb-e ߸[qıu>aCS==,Oav<ΒFݴ5ؑGvHN.3`7y×N7e;p!,g_X'ɡJ 6v`Gc>CRUuS7~됞rju]iD.5z.e-PEKb[C ޙsg>P0(%e>KC Ӊ@ؗx#>?^֭e~AwlqrfA _*|{{hZj?}m>tsÇ9>yk?,hkt|Xjq,b]7*rvZoPMMw +O>HB?VLT6\~kR{YClM$Ltm_/?~}_?oz޾~ۻoӇ~@gI;ۿ_VǤ1==;  2db.uoԬjxjkՎGzP3ѩg& eό`8uaQw|ʥ}N'_%!')Z^y1 h)ԒZ|kL! IIԸCPXY޻oq/BJ=g&馁\h4¼x)H5[ i=Cc,!VЀI/O0#]:Yֳ>Le*Z~,cjJclY9` kXA4W dKΔVR(M4cĔu(W3]l+ }g9_)m(#jKYs3wU? >bM}qpiJG&sBwlҲiM]sTmLe=9|?n, VFq i0ڑlvkCTIi%]ju!yo&2`QnfIPhA(v#||΍ِ +rи&9%ȵ^% ]^CF86f^0ѬWvk brig^(ǘJkOG!GݽY} d9^R.1 +^^s rz̀x##I䁜bւrzJ[A9(mtuSI\{x)㢜*1 rj% ', ȩ9 +I[ CRNN#(GcPPSA90(X3(ݹ%S:T̶Q'8*uwZY3:TD9rZ[Q5r;cbl-(5ӢjiQQwZ1Qd@>C 딃}:Ԗx]r)lS.aց\BuS.oP.r}rlE.}261|QG9 Ǟqt Ǿd&U&z&rt~ri&[y-HtڍPbE-h-.=L">;Mf>3󱩯9m^ơqC㔳cPrcSzl*?݌.t\%1=FAK- )Rłqԫ +6]Du|j!>U19iANYTt|*b>n!a94Uiq jqе q #JqAkүQ!4oqoqeq=pp {!C8}!>px3M *&!V;3$k-q,hJalC/wtpS7F\X o![Y8hA`b5i7nd4/!6d\$<^c̼o^6㨫8B[孾GMXKP{1|a}\{YnjD8.)rԳZ1W]Lt .c7 *#!a8&\^7p\⠋h8$rFQA2A3 a=mBV/qZq{7X_]d0U[U =b@qeրKf˭2TvNȩq=ۭLۭjcV)[Z91 rb@?fۺ?\ĄuU}Ydq9X`(M`)}r*y*~d S]exbĪeG)QqL:J@VYDY]UߓcqUy!nUTQvkeo3i9qU1Թ9*wcV5#JW/)ek,pL+G URq<^Uڽk0N9'!ĉAwYұ}*~nU SZ[SGKA;p?D1pԹf8ʜ#9Ye]C󈀳pJlᘖz:[9N qL{ NPqDq@Jݫ8A(74M`uZSB6QJ M61q⼽ kA9hۛr^w[1՗WE96r`ڍ s,VOx1GO9:=9mr +sйsCρm + p{Us490 EۅaUQ Ḻ&ȥS1U y]bǵ;=h1"+7>2 +1Р~40pxU{;Kv{Uns&7Uv*u+,8gl\W5*GsvsW}1|abi|U+ǫӼ*w1UyFQܔC +^h6rL8y䐔(3 7yUC9\k+ATrԳ r,憜(HfBuJ9W MgCrf6.%^trLKs9:TCÊ|Pje9:CyE;V'E~xxf x_65@Ke]K(=Ч;[7Ȃ.5Fp$cu/vƲͻwxc煷s~˟$_G3¿?&=*gxGGS+x*ؑeVyN]yhK2f̭ғFNm5Բx#ScߩuPkdp)KxE3-*Ըe\C4e[p,deXd|?d+Fr,&LU1pAѡcPs; }Zu3xO%ًR7l+˝LIh8@ARWH>j54 l!Pk]iQؠF\Sؐ_$H3+=F}v$14ta]@>4ST_cZ.ʵ3싇tlԡ|-7P^ˌ d,Õ3F%U珴 ,Nk'8X]ͫieԝ$j4z5%/6~F/$&ʉbCKcfJ@CRUrEMt.y2d= `-y"Bd(9Mve9@ݒ%@ol@BOщ5hJ').7ӔQzՔo>M.)2MQ)51INhS\A:8=8.|N;8iMG5 )+9EV]o`W}=EaLYYb5IL51u<41ERD^,E qSʣ/^Ix9~?NCMR))c4D<[@g#!gnԿ/^=!LHQFk-*9rup.hz鸤_H*\"M[QOUGQk1ܤ2ú2aEU(s6m/Q0.5gKq.8dkaV^Cm͙118nwzy!1 +p98~cQ|&o}J~u7DL+q3ní7hKijׂYvv|{oq_ߌ#is:hx|3 +p"Jxtyi񍥽GYVz7Fk21p}1 py#3+{X +l1;p+Fg9{6v_BqR#R8skG +KO3GhF,-P5n8_K<iH<$XuI<nw 1N@mگq,ٍc18Fix4mI\*ZߙCncZ2ǼN)7eA9~fy3F1K[sZctU:ǸKx9Oo<鐇)'i:\X!^Ɯ:d0gw9uU{R,&ҡbSgJ쟼!#_JߥCnN5sRZْ:dY'uzX :ҡ/:,cғ:f*ܕͬLϭǍҭCiRc_:z!%Z( ~ {~uh !M 3+jbu +3~|qjݗ=XX.G݇6b݇Y=:aZV9k`l֩5[MȳQ1esc+UCM7*1k|Zopc\UW?wLa?SNXrjP7J97ӤRG:iZJVqtWJ OSڕq\:rmor=km%u'uQ{+jM,ҡtِIҪa[\Elp\f:8{ +oYQ 5`9װTt܏o90wo]Cv`ŁN=BСԹ.tLҡ]WJ>stream +H OV%uVԪj$$IH= C|`Nh.ff\)Rc| ow"a؜+yMt^LJ~%iipO,ɿ($idL/+ +ϓ7dydQ)"1vzeUL-0FʦI2m-tȧyU> uA2R8j)ҳJNE_t>=;;sً|%_w޽qFuMmM͚fɏ%ZLeUUT*_o߮l&45v5;z76-s\6AVu˝dsNޣ;:xㆠySԲ%jߦ:vN{W顀Oʧtc!?da(h$ilfMt #{#KzTǶdGIl&A$4"|+ܑlOqߥ3nÞKqh>ciLLiz#Ф܆[Mp/|~,a c,fAFAye\ZO.]s$%exr}YRv%d +ZDūtQb[z/Ȑ ~OVgK*fy Iv9ޖYR0:|;5.ZNҰ`%HI S/ODr78χu- uKXӎϺ2{ f!_ۋOu~3@ +EYH}]5~hP?2 "f\TxZe%N_SAT %ĥKU^չ-jXHD$#R<.84o׍ޚ)2ҤKOX'bހMެ]4oN׏#@KTeU b(K,, MĬlw~Ӳ pF-`eo)<1rJ,ŵJ))ͬfVf6cVYlȸZt]bG~5NR +Kq8x265ȦYzzgOB`畻)߿s ֟ii}cçNKr.7RRC=Wɻ<&ϫ{~ZTtkWHQ}S/(i@Q82//*+lbe&nWEӱ }1իMss{x%l\e9e~%Q L ϯe,5?s)B + +Ԧ/|i#aY_`c|XI}XOtXG}%[-j,-iY͑zk={FѨq$fǒThƱhւ?U5b1^4k{ *Q;%GРWVe=z$& BRAT@52x*pk2-j0sRv&e]dCs34y(2N g-bziDf"f^RrAEI\g{(]*^ +5Tl3mllߠMx4Zx6^xW' :zk2̋^u2ZM6h@ eɾt1Rm G#&qơfjJQ$37[PH˚M) XK}ƈEay7 +ʺpueOҹ&.Ox@54 ǖ3FGEunA rZZrπIQZWfE=&-9 y /`0gF! +F#@h}x}% u߯7՚;[dv$R4`G:Y02³SvtX)Civ@/e';w.JDR#@ +GGO4@zv;RRk;x;:j _8f{.%L8df 6C[t n۪I+iuٖydֹ+ 1g+A4|^j[y߂Fߋ w-Z4@hoM~ !/T1FMJJʱ {2)E9+U0j- +sO@*a.^K][oxzl4kE; \׽HWƪuYPr7DA +IY!*(r.>!+EheLj95#;eNRP4fIΧ_Nt ]Y]>JxWP$ԡ8UIfQV~KہM{9"r ,NG/ =L)4*&p(jK2~kvdqWJNe1?*#.3E <&fV :j{1^i+Vu"6RQKRWU777tϰPZ'Ra|.ߡ }rr緗([ ii#RhK/47o<\00 bm̮K8SRyT2Υ L<|,X:3Fbh[]6_bA*ubŐzHEcCm*Q6p; )H ']Еaxr~V 8G|EΛLSI]䝥0UC y"kaGiֈ7dTI[D}, ҽ,}/W?:H9ޓy FЩMՓTߦ, `OC], w[gi{e&\qz#E[b}sS.j`({Pl8Ok0&HEpK@oP4`)9f'F%**Fp D1< 6-aW@oɡ̲;)JƩneMښj{{dWi:']-QMZ ZsnɮIZX8; VC͹uYn<>^H¦;J c32Gэ֨dEƲKϧS;vaGk Ҷ%Q~ = t&BT(U%(=*@mnZ!*ռ^~.uM .oOMYӾ1`ƥNP@Z%]{gی})RF(8}DLacqP +rf\; &Hs O8SJTK)M EYP%+YcΊVla1h[+S&4e|0=>H3mirt %,(JCLF9\@>9KA_B.@" J~r,S:(] ҽ8mv{  lՈΒAh`i,MfՒE*?ug0ϝkMǏGw +]t5Ē9ы,{:tĉG|~Ǿ8G@)=O@z-P/b 'AQYPvJ8@ĪR>:cn Z)rRm2$/R|?JA Z7̸Y3P[ -Θ)HAQP@ ^I_VF\oW;%&l}@袃}RycÊSߔ䦭Re,h +sVA8T yDI@  @ + ffM@4 M] =)v?A?CFX( D & T%_#; 坔X퇔&E (.+ ʟ>̴g潁LvX*;DFc}PS $ =i"eSTTZ)fIڵJ4 Mڵ IǨPJӣWYL:qy K . +?R_]/vŎh,]h*&ۜj .פre{ B `;ǟd& cn|4} ha u39 !OHj612+]%'%nl+cu~y*^OpiՐ[QBQ` X+N,R|IBh7eƙ +Fu}/W"V6mjnHm۔6B(9 llg|$B8l|\iMVDyLtKv-p!i]=1LմD vU63iN0Y*51áu!ԒasFBQc>GW +Ҧ=,0R\EJQ w"i@Ս!S#%ivp:΅col=V)+늪DP@n['@J]ғB) '?pZL +G)oo9s=u'#Eq#I +ϯ|[ g]G/\g]ZqwJ~;*ĠV)ZU[;;[jNk'e) +2q.J)r0)訖c٥& ڶ +X[ګ2\lR6?|?iE HU3a>Е5<MCfYxJD- !])V M¦E1]pAԴPΤ +H.&nj "l-yd(<3tQi4$GOcCn5¨ga +NPP$ 6))Yjb;i4š N3&*MvBѸUSI& %K.U!RHivFR'.>3ȊSwiƌ׺͂Yn.t87@ {Qjtqs}֬۔q'MDYzHiΥ RRP6hPj{|^'ӀoQ(16'QmwD :o8RHi@ /,JvRݨAhc PL#c´VQu f3c/v-_P0L.\?o/^#8%ht䟬[o[hu䥭X f7 6!9]J;uYc3x6G.2.G|ŭ d&X 0ܟ*:i 0Xw4 +}_?ACv|Dd$3b'lQqVUª[SR>EJS2$i#TLʡ$ 0RDM9 ]ӳ#[k[ٳ~G.0 : YLg39 44̢#:$g HU[0?=!iۧj#BnHTV% Q P(x#=b862Wkj0Mm5pq7xI6Nl=u2Rن".gAMt}iwHkm:=ѹ]ꯘoa5a}g677*:M r't#~B -']s /n˯G5RCvdQfb(u~rJZw46%+nCcf4I*5y|eoN{~Kn,G}R񏞑N'Ny,2Ea3>DR?ܗSZwi2N3vf; _&i.Ӹ&Y+C[]/  rG;j$/y Gbi&gNs s~^AhL U0RtĤk +4֦a4 JcDoPJQ xn6H#"Y-ÚFBABϗy_[6'6 .u1M> rxK"4ljé ## ^KUK +(fuJ.FsO+ sΝ8qzĈ>9s*K+H\vW6~i }TJ؁|CY;ĽxJ<[eۯ62Z_>/78Ϳd3[YЈyV5mG,DЊCAʚO҈Q6"3YA]Xb^xi>ԂԚvDJEiljdT596F)' m-À2dFC&y V5P(DjlqEH߂R*5|2@L(uAsV=RO2!@ǣGBRL7vn,dg3(@R~eSk=.[G)? +eFM$?ɥH3_q),D+cux^1+6HB-ꊤn&#Feʒ&!Dw%m/wyvon)[ԯ9.Rmp3xMY N!2"tM{5PW-]}nW? xNq u)$6@H>$A|NŬSqM Xn@(]kH.yLa=cڴA>M$* !R"Tv{o^y_>Bs/r):pTTsɴP"uZ6S:f +ovciXjs7Ql;Y 3Ĝd.bUf3RIUi*HGcߨq#̻JDߜId}kVܨpەxF]},1GCXB:# + $:,4jrqk +o_uۥq|lu:]wtJJuQe-Ed)(dڎuzK{K'@?auhoBN{hR)\JEJHKK"GHc"OtTrGޥ<1)F/ul,h!"U̟88ܺc{$c3?i?Nb7NvĀL$tFS # t I}qJF45g}y3AhgP߷tA~oTDMlRi#A =(}s HUZ= +SC,ꮂ8wouKijp۳Ec + d%"e"~%s,?pH9sD"6v?Bl$vzT@ ?Tj9= _ +>T?x9ϟK"FS!Ϟ=E +4Tb{-hn3_;]$=wyq)J*BqJuy(]R`XGv4Y'[NLm%6 gu `oz)eB$PR!!SpFI&c6y$ƌ2c1~,#Qt>nӡۺuU5ȼհ4l5khhfoD WÐR2Wu7%㡼+o\Q5yNqtc!9qǫ)U %E=㜓rIUo ^_Uie(O;di͂ :P\g7ۥ ުyqtIRWzaqaXBڛCmǸY) ϼwdzkx*/-m9k.ŃrZh)UlQtt.:;nr,uugXJ".C0ː +Tt>) Ke)t]<Y2 X4 !!YD()ґ56hF95j39g.Si:bvXf,jRd썅u}=TSch)|`Ӎ1V[ELME֠F;td!RNed(Zi.w2BMaPPl+Ui\wGV*}s +Qq`J"I=}NnrEC7%Ge)N[[s?_n~~_B. +ϮRtt7z[ƕIJˆH!򸚯Ov +U8,pNRSW])XJWdCuQ PQ PO>KGۗG HbD³AAAҐV NyMXG``) ~:2%`) +@`Rv^aA-d-i,iLݻ\ָĕnyM@VstV05.80omtj'"MYIV.K1/0)#K&p핀8ySOG3$_~zFY7OW|.7rԔ6>Eq?:JZ2 -}4ϵ-]"gN.WW)2})CSJ,.(K@PaPG-!R q`2A,  N db L߰Naȹf 0m U -@"V鑠Uh.L(KAѰVщ}iX']%X +l X5rc R2P:Tj,1Wݙ曎*zuo^ռ ?Lo}Nl'LL2KFZ`x +1r[,yvɂwg? = •Qt*F,Hӻ<髍_v߿p/xv[mϰP8tY:ڊhqvQKwfqZW%ȢM.K)Nymf)NV7S,EX hB~~8T{5 B& @yl/I3Cd"a6h)BWZMuT!HV҉aĜ%m OGj`LX҆)̘;\T|Я *.䒖ʹ/3mLW@)哰өx2JIB7idv?r`tSFg +)WkApWO6|"Gx}G~ ((Y T2*1ocxۖͩ">t'I._0i-4]]sمũqqtDvߦYK +.fpJ)4 %ށ&p TRfq +^HJ4+z%gih>iQ5 B(+@bƂDx24!$@eƣX +AF )KR~B1˪|W Et-wH1b +Uq@Uۓw_.;&xNJQ'kl4OlXy$ h_n^L)_MߎfsLǎiܥ}^ӁLo~~T"#Ś GDh$Ξm{"qQIMRX/ إ6ޥEK!RKK\Q3:uɉQTFK)0-siwis)DJ] + +.]Vb@n 0B&@f͚EK\j@Ծˠר [HC u&<2b{wH'" )nu[Q UY5R:YW44\f.v)K֭1RU{%aIM;Nri TIǒ& [["Mqo|yF>?3Ģ>yT8Q%yrC{9%ѓ zh2uxfQUd/])ykmtCOE BG3Zj.vzv^¤*dˍ:ծS".] ;AHSp;X+x JPW'z'cdߊYXVMx m2[2y2Fz58q/`'jB! +;Ԇ" C^net#̨֦+ߌI +\i+QmBk# UN\-cW˖+ê qf]إE)t0*1_۷q8,9rq%>,DI؇H=,"%bɱ?tȾYBct=D.MD#i271t\ӭܙ|GE&*ͷ7\r +@uZȘi,r6]Bδ/7*s, T Ӝ_%ԥK!Eڥ7N_v\ҭ(ER#!"RU`ɾe¢ҋ$5TLbn>:8J H!R5>#>n".p:,:Y_h.uMPva~p؅j."uaHw\z3L0&ޙVpi<Nٴm2zmm-77`Q4+W'sШ9!f|Ef@Q6]oll@b9i_qc({dl.6W}:cȵ՞KMלJmڋ!Sǝ"Gs)dK.9-I<)Eԥ]*)nuXEAxLRK4f-~\T$#xo1lԅFTu1m_`QHXgC8HݑK=7-"C% +dŖs7߾C^QՐz- +}yɷ(Y +4ߴa//|%~=uDvֱ8~'4E2t.?~s#Xt!V%~H6D]kq?}ӗ2W}=]s.W}5U~CڤvN $S2>Sg +^4P-W҈^_HerFi5#S>S\uJ\C-N2!R.2=؂IE+@`-{c߈,-N z7g7Iw%e.F2f9"!;?Ej=!%Ӎ <"wP{y]إ"izD4c`[o;<3<'^tu ,%8U *GU[ 4djXvTʱD*b))ei]8KPflHѠj4eY7,UFg| 4~ߚtĔ%,u0I3>@R: +U!y#5d`3`l ;Rx^J@jÌ7ɴxz0X3iMCOU$ͳ |H{Ch,py|H'NV q8QHI޳+h7kxjZp%K.ګ<]yyU_sA+x/{ͯ" x>ngRb ua llA"VSUӘU_&$a)Ɉ"5D@= Z2 Lk։ϫgu-Z$na-s5 +" &Q ƮǏ2fnc +jV,*WV\< +ŋϟ?ShjEũ3g ҷ}:F -yt1eYwwwآ`c]쿟>y8MΫnގKpTWg%^j.i[*xWUF#+Po#vFVu䱇44 7 NͭTNY;,R!ybXI!DUTFcSɃ~Ԙ41 +[0,ͩIJNgВ#^p/ۍE$h!ē>m٭#hD4 1csiD#n MMS@'H#!,^GOP4L:9$sG~5icmmmuu… eeeΝ;}= =إz;H>RÄH+ͥwʾz<?l1w_GD%W|+Wfܲ +:/_(k:~EU@Y='ioț3 +B:~@Nzp2P2lXvS.wilH&ejLRrda)+:8>}`]qZ!z#J\ u1]rܘfO;CvSj”\8oSX p;-`; +(6C2FWw\zFXmD֓,zы"8jh+kL[2 +_}W]lo(}S?OKҶ? s endstream endobj 12 0 obj <>stream +H۪ l{$JjB..1d8~[e{UjTU_ZG/y{_CkX2M⓺imXUbQF4[_)4lrN`}qĴ;dr-MD-mndcnsv󥵔ۂ݄.^]z)=b5`6bv!|.!ml%6ߴKHgo'.m.3}.#ւJv)v6[TM;72 A{pc5M{vУkް㔱Y' ?X!kux*:xXN!us_c1!:KJ@ Rݼf lQ\::&J + +uoW/aF!(]*K!>8,mb]b[S ;Y3ZzHݺx9<|5U@B ynIscvTeQݵ{\g/V2juJg%Vmhve|0H:?:1><=(^Syzf9 F==͞W茅K9W[+tc0+hˬ,<eq󄟡Tsϐ46lO~  +~ԩ/AQg8H3NH؇cFm^XxEk}|8GN~ 6&|p\3:m;=x"w.Ymy?DgK%2ZD[" H=RSZY hb Q|, r`;f[_}w_~-^?}|Ww݇O˻׏pu){pyY?ǛkOä2OyCgcj"?_CԿ㦨+7yA! ˜$ZFI\&yv%\ܰO8F~+EHN՘Lb;A 258NtyI11^.)ReAT)[7=Wycۧ4HJJ,o]OŒ#p =hQJwT%ɉd%sQ6p)A)2lξA +]S E +$ŘIYlϓM rӔRO4Xꛦq~b̆o&ׅS+|%oel.Lgԍ7N8( 9O<cX8XBjXG}F)b + )Aʡ +HhHH9''_ +pzMH 咁Q_7G{G)@./2̺9 +}l哣˾1O1Jh˺1JF !;)JVE۵3E9㘅8fq#n9aTpu߀dC~J_sjtllI8 |zpkk$/ ptnU tOv 7gzitjnеz cjnA]gr0 @wy2YLWedJ\}'Pk} Al!ws7|C!{E:pg$XG?ߔqߐk+|c N:ppau&3/ {1p+Jˁ] 8m E[ i:I8nK3VB9])j 7zNGʏS71l5aƜr9]T͞9qJ?9vǘUc֬tȫksP:8Nn2[7x"I֡6rcF2ޗ;Q7]uͩC-ҡ4..2B:&mֺI|:F՜ƛ_XMԍ7!}1/MAj2woNl-QШku'Q{3w;u6|ԩ4[:.;m+KĿ賎[ϙVuYwN۳7uhu6NPSޏ:EE%tٺ::.k]6Ku:bfe>u+usܺz[\VYQuYYg?PՏu-=n2v똗nֱ6w g :|h՚Z;[qYSy"OY;BsYWx̬𽹲uZ03 +f밽muSY)upҖ}ƨI<;OͳbjEmՠ3:)'Vc+)zXJXװfPQϺ˃=wXUY:f ͈?of鰐ܪiJI:M<N3.sKܪ٫K|G ȥjtuex[:d!9IJVvoppyq~~q +Ʈp8\WGxsKf¹f!ysC>|tEh-AZ:tu!w/Cmq\:Utț'W:԰ݥOYҤofѤocz!k[ݕI9g1t5MIǬ1W9uNr rHq!˝tz=kX3tI}րq絛K!w :o=wi9;fC6>9t,/SnHDž7c~an+]:1~ѩC+s?éCngwR4WX_~̨Sy~Ec|eD1#c_W_N]U-^P[Z+šRu8u <:uqgP]#Yl5<:؀}Ե5:1"jyqꐟFn4Cm~!߱S[y~E 1WQfwꘇV1cmFOb~e>:&Omݡc޵'X[5׸A\V_uq:}NyU+s1 9z攬:n=b|mBةkyz;u6I:;Zݥ-'Wef]:NɖC Z:]ʌǡS.uř7Aǚs͡C6Ҝ9V"osm&PB;]96+jP+~\r]? ^NpDW߹m|S_3b։q&Zt@KK?ÚZeUռN OOCv3krYڙ"ⷞh۝}2ه[c.Ic^iJ:~xtzSoF?ͱgҏ`'A]?~I28Y >ݝ2>ɵNOCk<,tk`Y<" 3Hݜ@g& Hk=7j v Ͻ7o>/[^|_W?뇷ǿ>_z?{G|$ǫ׏wRi_PZ +釢Sj*y1ylnhfc9fxpPԨH)j'wC 2'`w6kR&/c_iKO>O\i◪Ƌ w/`v7}R&}9Ļ)_UE_=&E_.iY>f| B* L\E_fR*e\L=yϴ Us!:ϛ,7{}{%^@/ @/tђ-jcQm9/A;b/wB QdOQ' ̲acbK vbB2A:h]:xLq GC5XGˉ:~_~N6C7-A\f1ts.'ǔu9RS7=-Q 9uFʆ: uahܨC v^.u>)'uu 1&3 u>Bۨc B4:>YGɳ=aǘө;d`G˧ v٥;/)V+6W6i}NU21K:y鄆5/eq,)R`}2\#kS=pRp~N wp']턣. [BNDž;jg8ph/1&{pGo!R"R.1e!xоUxMz/:[Y"iOZg#OG}[ȣ5]ck]CuJy![Iyڵx@B/sQYC K,L9{&hz}ؠ^jئ6@C R7=QpArCszCj`C pJ'ziI=j~I=2uQz9z%Qo/acP&4DǨ'-㲩XN {zL {|a[:t-1Kȡ{L,F Ğ/ {J&(QyX), 3=/8tl)t {R {Ү.Q'yc/"Mbͧj {cc=ȒՐ]]-b97Q]-u,϶]-ZjaVc &{\3['ư]v-^ W;:7" 0VϸSrc͞lb'_`!'S90׷|ZB1zV_d{PԣIDmZ}-ts!L4]Cl{#I=c,ogǤlu>mluAIRsly(=e_R4 =ʞv>Ζ_e w[[|[ԓֆDzZok+nmDn!.wAϳ̃j!;јj-oA'}]=`tқ Ay2f/7ny2(y,Rn"cǺ]m y3`yL+q#O@gw US<Ǫ|En V¤@Cg]y2&xtꄞAɕ zz]zfۚ;(Ӝ>1 )ǭAilm\> 2Ɛ Jarq^ԟe[9O3^-if=u=νj7Aܫ꒷]'|jS| {(;SCy MYScVم{]…r.]m9ka^'M=VhqKRgqMH1.9'^-JR~$oq/֓GX3RvI%oK.v]g ,y% ||[v-qKӗM* 5vyk>Ⓑݵ]*-yc'pcri[:*R:t%o*v]ʠ(&d7saT':yQOTrC~NK}[ f3@zh6^GUP:qbi qN_M>:"$k }tVd&ԫ~RDGsқ#;9LƚDž1g2EP, + +NqT .R{;p ܥteu$|b9 wN0ǴO6]%R+@ "xmw E gVXKraHjP1L ]eb?'q̽~vv1Wl| +؄`<ͅ(IA=RmW AqJ 91(N՚7 I]tLv?O*?#rXC8ȡe f BN҇f[$伣D(ī ) šBن+ YEirX]0t jw?<ܽ'4Y羭Oo÷'/^=>:l7[/o?ۯw?~xCMy}7;28uBJ]퀢N턟^uO/| ϖ_ߨRJa.Buc0VC:*Tk:oM07i7h~@p8 I3{z;;kYRbp!n~ǫY.LY+RPG䶥F8;rkhˬj45t4BKc \ 0HbtH5KDJW3`jgEDjXȃU*# ]cjZF:T5y*z|FobuL"WaNe+;-:ؼ) ` '"_ +K`dU}<u)(wgV*c QJD2j4N*LD` Mnn)혒2a8kC &>'iak#lc +7GoqLdWW@s"u`` _un@ ɃmDP$]H)gDu!]Fh MWtŚۣ42*E-`:^pG{\N$W'/ zxrKSw TYy0JGxunAٜEEOaȞe㩙1࠻&q-wx67mhW}>ó6̀z|NZOX8qZgHpX25|%k%NYWQ{|¹ '&GG8ʕ053[_]rj ;X Pw0ye4p\r{45{B3EkRI[=` ܈Uadr) ЉVj)c|'Uޏʓ} ]BR؞,=oasd~Sʸ1Dݷ }YPGJc`C]c[&P'R+IH>O0wϕ}hވ!T~`!MFwp@ }f43+=Eb')NYlhvp]PJð۠{'}H;>oPP$unOruegs2^d-eFVol8|fϮmFx|BdOr6deOFƹgs6;88Rrmwt3t %G^_u֎pQk"]ƫFY@jj=ѱze[OCRj?F>kgZkecYɗU'?⤹XF/3P~Qޢ)TIN)$7Hl7-'PDQ;TXk%@e1)6ǮA~BK-f,gŕ gޣ*3zPxmj?'.7U`v:7NVoGW^$``">j +B$嵠֩8 Tg IXP*(~ާP*P4b8gFiAƒa$Czoo/6@q;+;ٙs (s}#EXa2 +4YXl!Jo_Fm@'WTò3 J*8 N Z"qviI׫b01ZKtt*ߵ;]\hOz\Tw&cߚoyՈJg3".`i6ua?a7ܴf* !.l7+w E%h!C[>_2hO3ë ̾{so?ۯ}>%Z:( /)GY! ec$̓cYK9} a{wWZśw?݀_?_܂w}a{/+Hˡz¼󖿻{{^zћWb x\q M2q[ a)V| :>ǜ:%E[Ӛut RBfY9i5g1$["} }831\fp`;u%YӘvZ/$|f RvEY0'O%e^v۴=yr@eW!qF|`t _Z">Ϯ{o?Y"k(H<ǫ^9gMjVDvO0)iVYۃJ8އD-iTkʠPJi!pc`=XR<Ә}㱻76MF:g[[mZ$Ū+w:'kPh# _Wt)yyu:X:v?4/ϖN?jPIU vQS]$4({*KRJSU+V5}Z*/zmHUt{WܛҐ{wHo dS t7EϱB)O m6P rikjg%@ai쁄8Hc:t6TZPcOZz̒&rBXc* Yk).^BYJQة:(R-Ē$Ps1NtHv5zI MșVs-E1K3Uw6lkMʮʶQO_LRr?tS憰Y%37b,N [AHRV:1d`NtTAmBs2ǂ\=K&D}(y=@ɧ: sn2Y +-Gg/tW~x|pEPo&/+EL/Q%U*6Ij' c(j=}BDr֭7XF*I.Yr +֚,-jPsHSKKGj^+CUzGC U#ZR.G52l"J]~ʴiF>}KJ8)TvZQ:g?q)^G (UuF+;$M5 ='-*TzҭY(j)-*^amĀ .vPO-La h4搻/,ݬA[d(.~ńևa:$Zb]o}4AwҐ.bDEWLbzkU( +fnT~^Lo7S9?ٿb[_;Bv`1͵_Wjk xHZW46^}nwfg}uu}bׇ:qfobTM\ްSeSvPj9)G mV xG+90/ӫ7~>d73św?݀W,Sw}a{/+txWSE1C3Dul]O? ~@FےQ)&کBTb'G`J|iIj' Se@v~*\GNdWb +S\k1d&oT;]a@^r)$#*FD0A^ kGTmHe. kWD` hPub."KWD5{s0e˸ڎxs*Aw3PI EKjZ㐧z\q|mhUR +JW %NCW;2# dp}: ôߗ5u91.U9WJcF +[|DNla]`+pbڕ*BO@XOK׺F1$ZNA; +0.*E NN`B3}ΡgxsȰU+x% d)rg8/>zpnOj(pBq3{f +^Y aX`pƘuccG֨Jƌw9]pWNxj{N䡭\zFr30L_u,fR !:X-ZSS78KN$Z &:q11L5Qb +3,E5qES@ezRum][&rB M^ P]OF3vvP  !J$%$Ei U`KS8YIm|G[$B^HCiAqɱUZ5@1XY|YTyԯN8*̶ Js ĝ}+%~sm\kXva +mcVP3.hr fm`b0D|+*'fL GJhJ8kjk+y]L\H׽po-0Ҍz]ל +$T_`/L/ ? +Mуn0K_pR鱖7k'S]?b섘WÒ-GX!*+kԒ _Z7zn2+~~f!P0Dj4 6WYaeW唷>l4+(̐هG>J43=-^RxsQL5i wYS\9W{`dkO0Ts'xqɈvAyeҦ>W2[F}D ߡR{$Ԯpk##'i9L yzh6 b>tWqRZgz +=!Mm%op 1bÙyһ6 F3sLh0:'Ff>kEA7p'j߻Zazk;,:. 6[{8c|=c3w^7C#+aAyWyI+Z0{L,~P=t٨R8)[Ý!^cB̠ 񱿧xZZs9c &[Cki+2xQF[|BZC)h쵩 QQ6wf Ko8ۗ|z1sHH>!okjPWg!`HR4[ +{ ٻdu'.sh~F( `QF^_s]CօR0z[ODj^#+>D9\EȮ1s{B#餧_U*〟W!~c-LU4Q;ŨvS19S35֮^1zՖk>aXk͓h-X/ޥ6>?G6R 091P3}鰵BhEM}JiͿc#֟bD ]cj$WpS^bkr:˟ʹ51Q+]29Zpq/PP}ل9|- +k]x,v~xuq 6qz)Q8e[ `} fpXk nTD(#jT1a +`߽}, ~$]sZllyjy1>@T,nfcȧ&_#Yk6@G +|S dɯ g2G9M7¥N> +*Ks1<,LHx&%$ޅ6 W:`80NhZs}/8Ck:L +)+Ǖr,q;[6P6쑃C{TŢi4Urgm*gǡ~) :1$U )KBE?J>3A+ 8w6W6T`mWbbiv^8)嫫bVFПTnYsHP) +x3,R=x0@z8w[ABݟg ia˚`ˉ9uԹ晣76l1]:2O?2(e9Yjme׊>0)pTӜMe'Eț;U'B6CbAa]|Y|XYn䝻s9ى:FI95>stream +HSSYժҒ)KCt4.GmD a [Ȏ4k" =! 5`ry=pAz'v[Os{ysĉ?8p/rQDwwBNɓCЫ1 '(vmM BT0ܳ>t^1R}R^'/@B;My[ =BOGDkӡzɽ|+" +d~s\Tl|ArԆ.5@PW3Rw7{"=m~e_h]aMlDK4Kq+v5u]wڣ#PAAQ5AMdH;?lbcؘUGM#}¨ FMjj[j)guEӗ:JfU%jmXġC8|(:00 jcTNJ#k12:|F)psxyJcbRWV_>}[;u_ߪ+O~uVSQwr<^# ͳ/f +},dӠZ/ ,H)K}X@&tL/tq3 +}JЀ + AaL#'!"I  % u&v\Ճ>,`~ܩ-RͨenCZ չEa[D~7Z'0D +@ Ϥ>+MF0YpO 26LF8[[[ˇ89@C@*l1,Rn7pnM'iJL l\gU9ק\to'U_o& ҽ13p 9_yUg(dӊ, :S,8n w,UB)xEqJY`))2p +:6I=D}o.pPK5?FQ;胶utXMѕV5VM;tGSI!k݌jkl98j+KB2+ SJWOqe(Dx*T9iܜd(\(%`) vN4cr={9"'m#$@& ϒ\LZQj|>Y} +ifz3]SГ//O@)p7f$+!lx^} ũ1U`dMu`)Kԝ6Em}~ 8i(NbGlDz[{(JOl*$vs2P;} +UhI @=rtwT^SI؆ecmrukt:TV&o&?l}"LAVR#}B + %T} +PWAWwmrdcX+.=Fœ̥8/_%<'=ZbJ/̿_%AZ685YCf `unMq$GZV2".mllP)5mҽ8||b?k͍J%*Lj-24,~K3Ǐ1WϬ-(H$0Y6u?rY $w4R3sYg(JEVTAk5KuxE}RH`)${[i{IK U@iI~UQx 9ݰNdlW +f5秴%6%@f20:H8%{7-V8A O):BCv"=YyQ%A/5/'%%&lc0`}i[%`4%,%1B!' ydIHwXӘGYe)aMs8f.8B\\4hrr Kk*﫸 +p;:to#T̲EAXFQWCKwO)|-!&d&KAX? ?Ppt&׾AZ]cs0~V}-˱%ש]6̢S}Ouk'UYJMʣn`)lcSũGspINɹpbn XZMs\{bnujj{}zX諠<ϺuyU_).2;"!Ipץ&˖TAin^)־' +jjN'4S\j"nH"V)J[d;0g),m.W:& 71X +!JN?8a^@ +a%tuIرBHAeĜxq516݋#f9NSNJ9zKq4, cK3C1 w{ \gQ*@s_T5DX{/0IBfaKaf/:V#TAuMҳ3'?Vp-nqbGM4PG5kYS+RE,/0%XA퐱 6q,DtBʳԥ`y.WAUSnT\*WOs>V}EFAZ! $ఱ#Tyn&"bB\b27[!n O5f848==Å|5<nwvB1OԻto޼!5sg`NRך6Euw S{CE1K{&OHgSHP\.v^Ѷ-n6 "Ȥ,[3uYA"4uMH$V}vMBi'NmbHR95!rH=4Zy43z9C|g&TXګ4uwWMbbBvRb\q&!- ({I4f[|'so*7|]2E`)4xLo)JOƖ`Q } +EKT+ZӶRfqdY%Ԥ}O'^Չ!ߍD|#,e/E) ¥]#~B2`r +Azc+TP(1PhAE֦(a~BwVgآy(' A4$,ߦw9!]-_i|'Wh O`Yri"MIlj(GL^;mTG㋥Fyl4R]- b|qZX-bkL.U3\ؚ)*:0z~Lf-Kє:~׉DQ(9⩁iڙaN"Bu6ܽYONJS>:_+ԪPcf|i>S}ndlZx0qv͚FU ^92<Ď2ա_C" ]LZaCKߗM&+5>nTg +ťb}~daZdZo͹yŮ2y!؆)&H,s0;N/W`QTvwm/mzkuz1[4&ί]ؘXҿ'[VبU]_/fǶjwWuH£a^ώ +Hƶ + :E#u(,HB*c P_\Dn%C~f}η+'F]\/ 1=R`MW.ܞ{PSGRc$Qw 0=5Qhid(R*))u]lzpt"]3DJm$+Ԟ'&Q}v}ڝwo7nn΋w;Z/|.W8Mh!葄/ȥx:ԡ0$(L?Bȁ~:ƖWUƛC_+%x: qLwPIExV{=;DB4Cmڹ]| qB~d<%Xe"0 +U2.XUFZv&<oM[@A.OjS3O"}LDY/O ,)aG +~ixmQD a RtG9Ij)DJb7/MT +NasaQ!)eY7Ňܥ ǭQIS0 eMN* IaazKk„Lu][mжHQ xL%" ڮa&CM[TAІHqHePE t_tڨaع2Yr;mlC~)tRM{a&iu]R["Pmq!RF,Lar)Y(CHQ֖ "/UDeBj)0}H0*tg꣜Im4:$5 1cB=T1alb< IBz;NΝ;A8MѰGX 8 $A{P4R>H215F0LiFѴlOdZV9t-.l Q 0L h + +!<ϓRsNS"%LdQ\b>Dڍ0 t;j;iΖdQ-N>*0xh"%GqR9$Rvra3qz Rmގ 0L +RzHdWt +a>p)EfDj:٢y?A endstream endobj 13 0 obj <>stream +HtWI <p=b۾y ooUEI$b {ٯ~q:: +ԟJ 2 sryS`6E4 4 錬1׀&Vyw: kW)i_N+4Pq\8 .{UJ z㕱^>@  On[CܝX# F7xE Po:Mr \$&05$9"`"' ~>ŎO$}X@ͯ 2-w7*A%\>!T.˂^HpLѽoޠѧ`S9 d'(0z})' -w (uIuУ9E :^^'SDq0}A7CbRԁy}o]RN8[zj8ϽkO:❖)6rw99zNOWWIAS^ s@7 3.J{vSN-Z2yuLy+Pv^sO!0eG4[K]_>2&(AD>KhnhёseTٍ &ѷYk:^Rx ܒyW>MRj[lq0Ff ÈB[Kmk @!S|Ft)/(lX_UM>bdJ< +:|4GpJ_PK d +XpV6X)x`Yϖ0hd&@j`[_b9gvSQ/#K&%Og*{hKʏc5`|T|;0RC nYCES=wщxv}̧AwH|]Ov]wO?;`zE2c@Le+Biߠ9j\a&R0zLl+/a# C"SՂ5{ے66ak%iS[%e:Yy.Kݜ"a`kL]0ΌW `b;a7@^t8_scPQm4.|s6n:H2i|VzQ +1&{ 41^c`XUul{Oi5`8+Iu6l>ys$y91_3 \0 +|R{`6^N z5ӹCx_Q/ψl< ;Z1δmM6gȻ~`eBrt]X^%CH۠Ė^{k )[׀neRUxrWKG>GKykݙBLҁY {ϯKwխXz'w87$F?-"aCBa!`^86&ojuwά1gjZRwuU8(l,Gsm}1YK(N֎ 5];Q>1k1%{3#\;Z&P4f'( ZH(.i Mҥo9Օ<'#9o?+{ba"wW=`}Ű.j.wj+N 9ם'JPޏu2'g.~p<  dj~j(yQjR +]{V{u˘t ,=AdtgOJcZGꔝfV `ja_j-KUe -=}u A\$hkVgV5=ښEEBIcvQp'u:ǺX[ւ +f$U vCe7-TvLI]S22&yV;鹴_l-3|FzP?ZXJndw$m H|)h>29k^ xEiAa +$N;?Μ]+nw|X]㛞 _)Ci}+ }n( ݉lei%pBQ@0#;k&rs6épۮ Ε/D0reiƆ% #` )\4.8KA0e\>%2fx0_3uX6nNPߨbb$la n0dO0ÏA_Ϳӷ_}o~?w_w6z|_ۗ᧗z+/Mno] !%&ZT +UFOO)usK4KJisYƅ t!M pOH܌ybH,vo6T.`šk<ٶ4u38O]_`IJ^4Ja[ri-)[ƚ7-kdX3;v^"O!1p`upxZAx"{V؁OXeg?#]y?1eФL{bRy M{obZA+ȭ!h7ljvUs@iӾMMq+i6HM%6$- XuАA^_!ae? 3j + 2CLb7uƖ9( ƺ>Z`oha' =.LhF 5M x\Wh}t@o,U%W+"wOwk#F&E/<\SR]@ n8bx\T=uQTOUdS(' D[,i{᫞p/X )Z{T `X)H?꽙4p@P;#K.puYVˉb-y~WvB+AjR7`Bze&Ɖj61 +3: Vg5ɥ{ԐiN!Sc`3 Lu>2:onlCx) c_H@XG+klZ?r)XObУ/w`tʱQ8oh}Ɓ3:^܏7@sݒ|G O eP nR"& hh +%y>zO@GU[+fQhjq^ؼX!FelY(}#Sj12!=?y:ݴ\A[Á371`b5Ӵ="YLՐF'@?ÀrV$_q/޿ŗ_}? ~?1u~ˏO|_~?Gy񗿆Ƿg{(e`LE}c.$wO{n/xV8ym :"P0i{Z|a.R 5~"5k1f"8Tb,:,;@T=t{}bD[LhG"&#VVU00q5m(Xmv!PrU{/0|FELu-q戏3@dj:Țe8bYuln͔x@,⍙Q9a+3@FcPH. N*GZ +';|`0Z 6on*@\6y48 ˚-%q:,=^c1HԱ)<`fLv聖:ѭ4˵.0lTcelwҩ=4m4M`jG?Ƹ ~ˮ/pE0Gh/bQ bk7Hm}8Xı۶H.8:֛2&Yu?N1Jc4 T4Aܱx48ty iLf#Bld,Sv]qVTpI/pp%M+`iqv_uRFKMsP%1Pȡ$H튨j&xW$pN&ؐ@+jY vxk\ @\W X* Wd Yz:b_U[ݙ''g"|z^-Y8O,/np偮1|b#l'>r33]QUf+f2@0_c\RA&jewHy}5TIDe`O{'UaQOVZ;ubcf^IK@ڶ%Tw0f +͗<̬mx+VZ" M  G4 PY}Z՚RW)761ʹu]l;u&\oI 3ǵ؆.++Mb[U禀ώ.غ#P0Mc h8M|j`%_e&vAcrcCBZ0!S)DB0VRtv]gb~D48L1,B[8sO\z  C:](O)0^l,wF(*c2 4!~T_m䈐ivta(@AOkW!p6_&/2V#d륩wiUH-+Ŀ N__- KO?|L<]wj#F;๯ݮm|WA[1gX][u|]P|GwÃE \7XӖ^ SMmD +X<_NPtG.F·U®ewb4s0!V\o2W2J&JFsŦ45ZҤ(my ҼuVLȱiA^&jBxUkgtWj5ȳ1`Uh.4&Tmp7 >[37/Xh>vNJʷ$n +< +Olu [f|많'j0d a @~I:%؁7 vTo,G(e; $֤IDQP%@|}RgJTy)f&Nny9+>©3rO,J%&S#佃ߦFVWܒ?j9|lkݱF G&!uPbr.1~b$Az3;3OeVVͥ2#-ws&͡$,ѽ~ QFcۯ1b/\-/8\PRm@k6S85z80ϰFXnק~Q~h5CWĖ5KWqR<{FXT6-VjB U6/ucA]5q} *[`mS$R6'>/۱Xyܣm&@sj!_ w5KO D凢)O1XOW'8^"^Eq]UTk d}cF.د޶q% E%Q(2k+^=Ҥ~")QJ{QKz ,!9#gL&Oz E{`jX< j~M>X5>v\b DN9B P"WH# ߆| #7Ա0| t`pUk3{ 6Mi0ܰY_+F: 6@5 - JoKwmǶ PҰ Z-@6Sy-UD=W6R#&ϧP;4MH]@ôy Q/;?SWEwBɫ8O@8+zj +n U׈J!IР p+Ѵ6aYBB9^iyAbuU$gp;`SA$BPOVn@B Y6^gg߅ f@zS]4P`L"* 쎚Ũ]cr BoAxjaqPTL8Stb f>V&Cʃ- ԫEIX;#f㻢`y$݈+\ u/-RQfB]& ~t3-Qff;Y,-c~ 8'0,z]!邍t`-P] h=t$Ĵkp˾tˮ-(Bb>!(7Mr2 +{ XӯÄo ++3 ԛ 0uKM|-yU>FeLT7y1O2%gI ?a쮻>J+"Y@Bh]G1D}S*[٦hY'B%ΚS^`mèy/2"#-;;CQpU +a9ʥHr;?|xo >?37?b L-gE6U7yY%1 |-ayTͧ]0XzË8@m~-'F>i4퍗i/Ӵs#=[i۰#=OӸw"xNi7e,z6cva2i=ihFiHtqަՖVxxz)O"qs`MTEeSC,]k1D7]k`t6PPJeS<_Wr$CtKp{gXlXRN\@F ܕgEvIR4*_F1.uYtHɹmo@d#OZB)'+V МWy.*"{_d6 v-#ayT-.Lf|t"h_t≸&%w&2a'_,xGUKLcl%gFyR֬g_;},m/+i%IG w,c&*ǘw>%˷~-'.y]H\qNsƾ1\l\콏ۿX\Ny-lSe$3 e.ΚS=/܂Aa"ff80BL&rfhܬXr{]i\cKۖp"Z.*:! M`223CEF%eO&G(kG#f&fhB'1;ؔ,bq_)c0rt"f T˂T;`w_RhFcoF{+[wK/2gxo.;ˤWX~E)Iw Yw]8XJMlͲ]9fdMɓ?IOl>IYOƮi=ص~Vg<;MPn5GWhFczQ+vD@I#c>k/h/P*zy^|f#N]}%#z endstream endobj 26 0 obj <>stream +H7rHtdE TeJ5$% H簎82DC sS)>>es{߽ߟ_; ++[o_ + +3z{ ++5H}daVXaY0H:!UXaf7|OdWozeO7x믿^rŔ];[jq>c3y!CDgO/^9a +5,f}T4Dkd&??cz,6=fO?>/21E˘Fꏹn;^V{z6eʕ:uzF}e3gߥK #{2b +#QFԌ9nݺ-Y$߹sO>m޽>wܸq4?wi/[W^ ӧO= +֙%Ȁ!H|rx^t)ͭd47qc"(Ͼ}fybb%-WYYٵkD{͚5iJ<鱣xFxK iҤɉ'bgYTODmΟ??v֊1#cqФA|4t!k?e,gz.]yfZhQax({w3^Сp{ر +xy,?7 +֥MHW^ϟ?{"ƍ7lڵKQݻwڴiAsn߾}'|{YRӃyn۶mJnG1`رD˞={_^{-T? (=:j(dXnݴiS˖--݁>`?~<'O0f̘AGSu[_ϹM_u1bzD>|pbE̱h 艙aYpU  .\~>s7oF 0"E d-c;>wuHyi˖-eeewi@$ׯooۍƍn8$0WGf͚>|8+VV.-]cCf(4`qvTkKUUUPQFlժRݻ-Y^tdIrIIBKCmςL,/b24TkNaBtܹӇ捠I07@;V"n1](!V,vNpM&LxG,Z"ٳgS.t;Hb|饗WbZ)U(Kk}`xqZW_ڵWGjaKL +ÍTK, JƥKҭ[ da+.|o`jG1v5:Μ93dDll1B=˙&.`.pfVmhN~'hY#JbbHijAA4E?7PDɹ_S6;dȐkΚ ß9"G<8/`۶m>T +֙E ǝQf֭[r磏>Z]]]ZZ#G;{WFaXYY +C?0h]^0RvɓUwJeC*eƃ3lذ! i_jXx޻ };vwPS %%%.PH3=VԦF)e/<^:ы|8g;u0YU1EaD( lTҥKͩ:?QDn8E'mРR>.+JF +]SNգH^~պԵ,?Wfzƍ;d"Drӫn]vڔ:ӝ'v!{vH`lr(21RkeȔ ĹzTwRrΠT]6:iJ=jm?KOI9;<|9_ rdF^ظlG.p'}Lt59=-َ229ҞE@Ws[cQHQ@ +(Y=2';`4!K!N%&0 'ڬ'AF(ɚ۩4C +js볆_b,gnGw-6w*Sf^S(W'騟l;]oHz[JJ򕲭:MJA1Í[[%MQB{mI3Oc%9s|u@L4uڗ 5r.T4¤3PZ8hbتN%Kg풄UQ/*"yGwIBϪ?gT endstream endobj 14 0 obj <>stream +Hr;wVUC*.HBޥQ-Hɉy#8,Q+Hr'V7$VL:/o +.엯WR?;^ :/\}ӅA/#i&QK`HMS3N"w"9TX(c&uh B5YyT(fUi:#`nQ d'Lq\-cFxvn&'R8٪]p= +J Φ$Q4[x&G4Y8GS5~=t5h|aLLU1"*3oae{=ł0i0${{ý}0hReW=Jz{=@yG`޿z'X)~ +Na).3MXZpv~XqΗط/$IFmi(ip`BʮRSrGi۶=Û'D{S,lN> +sbp/XțBmXUrABrQz֟iONDk}A쯺yLr7xw7+?yr]&JkDv bD Q'# +jxj7G>=T!*\;@3-C6~1N4\:$^ۇQhxE(3Ã[4*"eOŻbid hLۄxj*U9lyPVYE;(AW?-uAE=A0zv0h=;A_T#bȍ:~β4Ձ i>6s۠mshgNWg:'=,ES/wíhr 2=FP{ġôtOs0n_f::xx jBkD(4Qn:ocgŭ?;t[g_ԧG +Y qٹoLH<2SNGZ)dx1wXJ,YIrSUaS"exA8P'qydQZK9׻ow 4lS=> = xAk#<ț Щ̇}۷/(ho{3}TnwF9^&wHg\{3 ^t'_ꌄǫgNWqֺ ]ϓ^}Y=ihr 2=FP{ġôtіTs}-Syh::Q7ulxwïcM&˴5qTgp^ +Tw&<8 R)`ϾO仓3D[ƌ1>8mBp2!㜭e) 'ڣpl +JN2<LmBp4&(L0W)ڢY#QʈPB*cd""XA~o \4*S^ɣm;^p/Q'T/iaA*MG`du 4nR$aLLU1"MEY:@Ycxb'h50*vob4&cE= KiG[l_gK XL^}9Syut|c~Mhi(GL+0`, +@*"fYr&<8´v.j$䝬~MN&@Le0hµR)([h +\XUA3鐝 Ʉ#e)kD%G)lwCv gJіy VFU֒8Gc5c,hg_{@~96qf9Lwh-@㠁Z:&O뚹Q0Y֦gx"sW|ǥ1GYdý:<[ѮuŴMOg(ejGw|!xc']7x7@(sSfƊs=əLxr3(h|35>@|~52:ѷ0;t=}[/RA`"u|Dz8CнM 4fhH9gs.a5Kx5C{jV'a wC1a&fT4DoDs`9n1s+lڪWLo@#X0:k7)SUaS}ﱵEc/6B ?A!nkRNv#[9498J6KĂB~޾ٵ!U`>#ჃI1B:@׻,꧒P7DHgVkt +t{ןB|!ﷁD;=8`q9uB]/?і74ؽMW{6T'1ã`׾!nRh EY5T`'+:h:QxsiD'r%vnD',$)r ۬?S!^ %+t J(cOU5$(0΂=z1 +\#{^!!wr&(򼳆#Kk=cStŵR)a='DGcЂYàHtVF&T8,}S^蕍)\h4|`<p+':n q +۬u+سeg,|Ye{oe +geƷGJrdK{_F}+߸w@oۙ+*aɍg=h endstream endobj 27 0 obj <>stream +H +jw endstream endobj 15 0 obj <>stream +HWnH~ 116fcgf ,-Q7%$ާꃒV˂% Rb=ϛ_E6,GUSeŗŏi^#HMJk{0z=8>φMVIu ,̛'Utb8Q9(W73{|^=$(8st籰@ft~PpHw^=>@ Þd^YR=%jmF?+bvFv0Ɋ=RuHT$MZ:ODfڨBc,GG2/7y2&rr 57Bywx6熦 .L#K' #;L=A=IF'eJuijTםYYgM#{N (sQsѹLr<4WU::g`K/hv'Q#w˧C4nyZ 6 cCCIJ;<G7b>0loVUvYQ^5Y3Wӟ|>Oћo'`bt4"n$ߗş`+GGN|~Ɋ3o>ޔ)xfE'{}0_A9~X*D5P8 +c#2B#E14N@3s} _E7F֏#w6!i|$VJI' {R11BS* + M샘hoWL v" 6&OXƘ (y,e(Bx uB$^/WA$WZM0YEgڙFŦ?2$gI4X6m{]iIl.2mXpPp?'4T9 QNcD$uB΅ϔu2ŭG +!̙_l ĉME e"KW'N>إeDFPƌB[} _gyLMT.Ql,c>s5AV 8p]ʍ'\ [j"c1Ɉd|lRd+8];,V5̄h'2H,T_z;ݜ#'d^osB`yLp<$B $o:} +MXE +G?w^Dz31%Ę"l^A+m)o/>`-saf@BxC \ +\ChM< EO nb zE/9J`~ +h0Ȁ+B;!XCӂ&Zzx@ ,:/$fqȋͩRژ]_L&$,"4 fnAtBc4ZSLP&95"7nULRE}A*Lxe/Tq#˘  Ĉ n.zrXd`(JHEdHp VH){{ps +z'W2I"ih~e řtQ`'Re=j3V66 +g` +~_x]ӬTսj]l 5lͶ +0[ekl 5L/^-k#G[`!= bL^gڡ6z܀nAbJIB5V0,,sDZ^ɵ7@veg />XP 챍vRFD\ +%@[1U 0 bQܦ,vz]~_p s İ/m= 7=2m;YOxu/p& B\UNFε3:`CP$'D( UU1:,ݻj=W+x4c낱*4[`9|d+ֹ7u蜿 "i(V!ဇ FˢMxF!V c7ʵM8y!ol@/&yM)aٌyi/zaMA Wuή3g|ː)ZAJh, *z4$b5JW|I&\ԤNU.=qa>Opk"$${Qaz3\ɖtMO/˙*ല#|/.\iyTqJ֠|3lXU;ugfʺ.BS;U`H{k+; xZe8WGj˄SgŦ&uUgI_uͬXVcHn xǧM]k`` VDŏi\xa[G*(ZKhngtmZ]qpi`ZVV@ڒt_"qA %eUcܠK,x DҌa)IAm6W\2 vl+euT$ѝ1q!OQ_c]]v8!6*aU߯ @x]RO#D;PwbX]DrpS ha/{v0G`,YTǘVp,q̣OWk]ҫZegBzon글^?5%%8IpίTkK}A253;Gϥk2/B®Fim+vOf"AQA.EiI:KCC$R̴yאi+9.@"?oujH /aH8C.J pNbpPFy?>cs\kuRķ'f, n{jƸݢPwJF簭 +N ^TdJLdfdz9IzOzSv{ey\[$fF"l&+6cyXp[X i;ዽ1lz.púO8]=ǻ#@VQse} + 젇_#-(]arc0 0+MlPHP['@j,ڷ]a]6)jHn2lfY7Vֹ ZF.%=D˗ܒ<4ػCzaGfEңz4J󑧈I8pm hw`$@fkqj4L;+']\k_+!=_V":vH5`;5[+,8jΫDϤ\Ym ;ʵ^jl撉δ`ZamH8y@53 sI70o2|05)%!O>?xԢQ((Aȟ)6<Jbt)u4[O*ˁ"f3wqC)ikcۙr'vu0,pdݠЬiv |5\7#r8 Yk%מ%KS4pX-F_0C{usx-AhÝZ{v73..eme1.gPNu u#Q +f +,H$;Yo1kyTkL8ME[ 7e]f<a$J? +__}G=~j&*6~n~T%pK STJnYCzݳ3!fb fBRFj _ᜌ nt5'\KSYyWB|5b3aM tiBTxb k9.\,,~9ɂmh 6TbO)&F~:1񫏋OU&{:'qv`sCzh@'6_8fϿ\S#O$[`ƩӮ+4UuA[51yg\~2kc0ޢ5͖Ȣo5.#҉$-2] kl\p:=xNgg(,TO3S8=qLغNoͲ#7oZL2i&մR  n_z,v }LTc"iȮR6v7Z3bK>& lö_eZ$[fSS+s"0C 0NJ{R)f&d1'rfa΋r2nVj㠂fsZSTV,^q&]q;BJ .[ko"'gyhT]0,0Ձ[vJͳ=?,.4t̥f5>f/TCY#ȭUV΋Ŭ`݈"m jG~җLxK"MnnZum 8 z@݄EvVPVfV{۫Pť1"E܌HaJv9@ lK\un`_w&dP fpv2j=Y(ٿ0 +I8X20x`ۀ$!<,g[Lٮ +iMQCfdZNDF6cdA N$1%Ʀ06C+p?` t 4!z V#a ‘P ,2<"$5{vlv3[<[WJs2Br$Wxh/ v\IaNܶpDE^XNo&[@8`4@)5~_CDjcsyN#Sjj=Vkkvd`1jZIo.DRSj1'.mi*W>L8!v{_j&҆}̑p5&&g%=y!)XxáYpMͦ-&T9h6eebmmIGKA(7(1Zlb%G-'*A$?\yPZ= :FZZ`~6NgY|7ȢXP^gnzQ'|_p\ʧx?ͷ-+}IghU4\ROm;z1;t3<6PI +|lB%ڝݞ=,1=.̵ҳ&ҎbWRQ1wxMڢ qĵ̽ջWq#Asq |vRi ^UI䓇v.D&Iic2):M[~^tM.#»dڅ#*V4TxIet +\ۇ۝3y`rp<+b=1Y[MVJ͚~uJ^-g(,\m)0tD>z00 ve#طrj2PC32ni/UԣMD O!-(U"BQh + " J{}nZEg3gu~u BLY}4.3*.|]'8RF<$ng8 YhV<3Kx[ ++zl$eIܶv TrYrz-"0k9SӋBH!\.&[~ٶNĒ IC-bjҁlkm,:mjϬ[{WjXQ: ٵ7xvc鹴A:Ⱥ:o&4+\%RPЌ%W3MӧkN]r]cQ\WgJ~YXqR@ Y -K x{2oêɞEhl[a-^ݚ6ONFW"u4OªU.5R+70|:WTv'Ƶk-C6J.fOOc@@-BXK>}UV$Ak5޺PF{0b3>{w OsgL^c4eTN",evݏ¯)Z'D?xLing`XvM,@y-K4j*X6X’`aML-[\&Vyp0 )YN$k*ɪ{ ټ$U'% l&{tPFbe[>e" t|H3r)F4`qan,R *zFHwM"0hJ(Y{bX!qF(Vi~4A86rlOo5$>}hŞvÈ !<_)( +(J{Ϯr-eÖ6c;qZdpH\<34y}Ԫ;YY*J=)A%(.VGt.Q0N(PI4YwCPr!2mn_^bjvp)bH]8/275p{l㜾Zb_2~M jo5H ɝ3VPwY|wA4F[Ia YК.ٕKN6q@ѴKB+(b[uIKȹ05HY^"^z6%e'oׅ[iyĿ?H%;^cǗ!n[O7_ތ'>x>y٫ϟ՛w~sx#6O>y𶐂9_O|ԐßIOuiJ7~>y_={ @ǿ{ūg0OW_?:,~%<1ffN=M&sEc3'<9wGu%? ZNGo \I\f x>S:JqgD~Z" G_oNp &'4W3,n_4^!RZmz>bp}Z~7~0ۧo1?mlO%>,t<'߭ZmZ{7@z|Z~7w#vj#DU +4 7Ƨ5Ɇo;Y#COw_`OeC[pNU[`riv6v+3v 5o>53>:IP::^nFר^T%Cć9 7h]6*nuXnr.qS2:g ؍0 O 8Gd T*FqϟZYs#} +(;.uSw[@[F)G\h̨Nx{`Ӌu {j[(!9U{[CGmm\罾uD;eem`jeU.za?1Cn%n(+[DESwSwp3bX:x{'oen[nkI4O`WL.$gQKAl(sar(ێbPU([l60P cЄNgEw*9 T7MvuTNX>LO _Q7~7V\C[X=ϝRYed2&^4v1!`5u\0NB=dG[Q`_0fBGD[QU˨+[e=.r܍@,q +H xkfq邓{8XB 3T'<qF lMFj3BnUCxB¹6wα?K6H}|Yw./ڜZȥcla݁]ӓ<[̴.$ц|JR +GOS%Tg5 i<)jۭ븡_8/bUHp.铫$I +(ÍEe !9{}l3!Zv (zay +eҷΓTT>|{dkFcf%c֑J;)>ӯR6yܩ0''mO'PQ0geͳ]*)dc ca DDAfx hJMFm[mMNB|d'6b;fƄ$$4V9$Z#^Þ}S6/<58n[*Jz$qwPJWx[$'qJNgm I)yA)u.FtcSu1F L9|wjB @猗:{0әyڤ.c#[z*T52S_hdG_oG +m>,{壹J:w W%''rc̷ޝnо(WWݟ~O˷'|goW~>zDy ?ʧ}4@M'nc1\= գU͋W/L|˿^<+o?x_~^wajp[#;:Č݉4+}cUDkKZY <.,>}_\o+(@55TC|ҁ5yGM9@q`IDn +=@Pi/x47#Q أMh&yfXmUf5jVϜm}ԲhMvFsqv~b GANU`%JTNՀ[SKjrm6cjtKX x^iZ-4FNip G>\zrjZ3: JMG4tڶ[[?}0K /˟s_fl?g,/I)exlUHa7 Z|煇RxFS,(p,2V*ZV&7:>YpRL߽7A- )L W!}+/f\) +G='^X8cQBDPhI p" $8# +xm?#Z4I O(y _YE:XHw_Xz>Cv3$LW`䘃$RlL +E` c/-LqURj#ʸ(lȜy8j^cӑ FA+O`*e1GϺuQ|脱dWOFҲ]yAT*Y 94JPĵA´ ݍ9;T} $煱a#S̑2Dp9K۩.3s +I +vCP{l6U{jrnL1H"LņXNmdLaR塵.ܾ0. hO.n1Ro:&gX]aiY-w\m#:ܳڨ"nR!\X/~!KD#ɧgVqcÐ~䙾h MʘNk7֜'ķG['j=STjBsK&:xF5O']Å}WECqWkeW0q}b-%-$RMdi@UɈFRեXگqNNjN? x IЄzr@Cv$X )J +YZ8rm2pZ!Ɣn(k?h9wjv/Pl/vA"q遀靪9$B'xine 3:AFf~FRt=l;#9$R6~"SF,qP- ґnA[E4ŁlR4Oe(j|bVњՑsI^d||E 3B (IucbkbL[oU3Ս\.edu"'$ÍɫatApCxEiNpA04 a)m7Yh$:]mײ 0 A9tL"ԃ`;O +?b )i$1E')@^mpX?Jx"5/ӽFJ#ĞLI' ]`vUo,='4M!X `7^.?+gAI`&[8p>.NRcjwbTˋm ߶EΆ%'ۑ,C e +`ԙ=/V/ Ȫpny-ѹ PO`k< 0f# ] r#x.7cPf]Vt3xXbqc-\Ltk\ֶ-w bFn%@OP5aivZSS[$ӊ0[6rXŋ" H\g('Qy\1[D p|7ԙ"Bpž{hfn OadǬ&Y߅ew giHH{xi_=Ͼ 1J!SXoePF: u~I,SR6W`BBۻTnJKdO%fZzVptƎ8Ǔ U[ hv <u 'f {i|^lNxΓ50DKEzNZ MCnhc%f$й2X%uZk@O Lqn9)~B"# bbR@ ilFUm'Ds4Tm)qz[UsЧ;ɰ?aw&۟MMsB|tLY\Y;`jMST[A|4N<4OYj +zCZ +3Ilk) !KE fбuEx? 9]mS39|~ow'a3Y~7q`MSb@>  H(RڟăPzR5M5Ք# Wyr=c`.0 endstream endobj 16 0 obj <>stream +HW__7|R֞?¶9߇O_=雷߼ǟ{r#,ϱ$!ӓ¥;J1%}1X>I >~/|/߾y}cb='ǯwyt/e{YZkm2~GNJi.''F=N#S:'yLUF%щۨMvZ-ݘ)% G=pi1[]6rtCTÆ4VS +8])ԍzij,liBpCp$/VE9kzVQÚOcE j)'b3q6>kky z*:[Y32bb Ϲڪ5_F(F|f0.CH%tX t#Z[a1TPZ x3okYpjʳUU1sTV/Mt4cc6"+SQ3@9LS͎d}DLc~~ Sm{|fMn]̏?xv"t%VFU@ZQ<ؠad ( X$y&IwLWeuca l8DJ +&F^S bm`JĢwbaUx"-vGjuкd1`ɉUJVk@PݚF|Q8*k|SDQoGa lR c]r)q4:Ѝ5*V>FxmК.jԅgwh[ +hja>XVdʩio溚|ilQ) Znm*\j(Q-mrSc㮧g99-P[>f[ F` sQ=Zbu Rx r<(J34Uuҏ]C87-Zɍ JnJms84iā|CUY+vbBx% ha4C/$ 4+(>Z +qiη|@1 )\W-1GR}jO%BZO4K5QTYlUhji>y'2+&|1x$r\8%㎒F ?H}I;}y#[ƉnDgz77ŐŃ0}"XgL,xrIŐPtd+ǖ=C FР@6K K(ݶMsG_t>p0l0*J M: T63X&ƴRT[!)*ͫ~} !T9ݘ$2OadWoȑܟWͥ'NtxdȓE-̦J=9=sjNJOuR[Xx驤p4ql b[2} (hG ^(:fa W;Q{R.).M#̹&B(9t oH̙-HD_7; UZ Y#D[oX)uLR#e %Ӡ%$`Q" rP1J2o&7⪤0dWDL4M@C;/ 6Stu;¾^"׌ [p@-7OC]cc=hMo.6zٕ4fp,<x0ѡH<]ۃwVc@ok1K%y)jbyӸSZ} qTqgz: ż4πPyps˾Z9!.c$] 9{r M9XRRxbٲ G&׀;E.u 7-pgR1x+C{%y]$*)?e j*0Y1- ޷ BY&بUxَ>7pi2(Rz.+C/Q>j ԧ +ŏT +Gֆ"5FU#4 w4S*JQwaѼos= Oѧ ՀL,0m_w]I{#ウ0v骎CDμOi9ڬ_,>ҫjw}+r;l}~olg?^n;{yo|86pWX`":T4p`ߺ㏟=<</~\N&Ϝۻ˛W0m_^^̈́ތ4]9l_b}p .AYUHt|+(6嘔v嚂[hx_o7, >۾v@[' APx]ΧU)c JM挙ӀmC#!^m> <;> O[']o|™˿pNa6Z$1T„8UVqt؂965pYR\T8V=nP8mOI~)̰O#i ^6C(Մ2G F>nPRz]3vl,JfVuYzAw `uߠnԌ4.'1jfO9FcVMlYuF|\eYbaBF/@c~' Y'w5`Ld_LVuRI\Zi" іH\ `IGt}-Ә}ǨۡSqLMcmFn%i]bH aNW&6jCK*zѩfbB('GChYȭ腌:fxQ3U-!_WY-HsICȧ ҧ _54¢]SkupR+{ 4| H*'NYޙDMxn|[c:7 GB}U7mؒ[*c(/H=E],(^u +CuG.fa =o8Ð5XDȴKk0CWDU2B;5!ZㆆƉj qEu2-`q,N +ccA{{kt"6ޝ,p70NmI͕훖4*i0F゙7bd&DsK0遹f'(iKsbESNf6c@eV6Q٠C@!8q_] Sw 9h(o46GVutGӬԠ) rֱxadӑ ̥?GYQ׉SRp+,;|{YF֖8\m8R(+)E05\'lZEKVgSiy1>vvv8|NZFO'RAXWfs=Tnq,z cdf28շb7O'ˁt3%A)hSVUbԖ<%qd,Z Z15bG|iZWLGj=szMK))DhYp u`'jNv |zPə'ĖDؼx$QlC0l_K TcKlfdz۳;v0-d>R,b1٭Qĥhdѐ8N>XKՇl:2FN >_}Pfg6/E4DZ/X3Y> Z#-CM&Hҟ=E*pfr8'`=x?IfuiЉ4CX}\ yB V9ĻQVev:nKhlskKb8u0 YRb!K]Ξ-IH}7b66Rd PuVlG8U6Su^-֯Xwkno{A_fdFm-> "w˛7^/ʸ sb{SPg\Mc ijbkj ԯ$i{Nvn-/:¬pԣ.O ny|u(FqvaC7G!8v5b1c![wZPf[ vűp5EJݱ w'UBL(B+,FP~sN Cx/~I,sQQW+cS(ޫy]CiQ43 ñF")/~F^=uq]wI{ 6% ~̳{qnN/.qGJ]+nM<ОrA$pE䫉+y ɠ {~Df:`M?0E +bCK)p)kݘ…7\ Gr],X2@KWhDIl`X\}>FP90?#1UBg?l 8ds 6߅ 4}gՂ!3d# +*1v@*x9?}b|?V ֛mT#J^Ԕ(3ƾK +6%=np +;i00潌@ ;Qf_oL}/d)r/~܆nhA_N7kۃW'_>,>=\B % #d_5 K|HgO>./o@!6? +{XKM}6*1_ʹ߻DZP0;>YG[ !124.܎V2"0H7ʓsqm9#u. :w?@_.sޟ͑o{~qݧO/Ogןv7gh95~i@!0\L0 |@(^W6I-|?7,-or޾:@B2P8ZGHuɀZIN ٔQBP^Z7σ+2E>\{ɓÓWc}vj#I4v&HaaGIeܨ̋+Ov}ƻ2@\x_vrt.S*H`߂Tv̘"waJTgC!>w#GmTzVtb=ߧAV.'_R'I0!t:U \;<( &hP34(&cMpP R-gK]"n"E].Q1(oJq?\&%&=|FLuB*kQ +HJ +H_ kMk]ATsUօ\'zr+Xb]$ؚSt~jY1VR!8>bB54Xrj +BF:ͨ'kS*:ZpNUtnX*R}+ +A0V"z`hWciuTuT,cξy Uɫ[ X,k=),`ZFFEBF&F-ց7c̴: +h9uD e]aXjs+ÉڜR-.T 5_Cj`=7=$yz~ģ7WK*tr;=ݧ/vW %P 7΄(\< ]> ޠλ}Vi- {Qr tk%EȺ% ښ%hՉP +p5=LӅ/T [)bD=3) GogdEѿi/+ +?ACO"~B$H "0N Ϻ:#ԙXvT{oAE_@FוPIZP}F͟:?pA`\J[WU0O8= Vi`,v$Q_)] Zija*h)E7w7uc1 ZjWM.N2 ;D`0sq/:Y;.GďP)9T8 zoc~aznqVLO{{EG(XOZ'{5yX^5HG-X:S 7pwݒ1sCma -@Λ5-'oPV9Ooz%F+>l0Q^_pͿ %)FN +NY2L,*`WPB=;q$oM18+dCcUqTYGw, + *.3禷X´.J"Ɔ,v L} \U' \>[e@8f&$haoJKv~l}ҚepՁȵATikʵw(oXdjO74rna?: fG/Mi}u`r݉')NA\3tG^w ʠ5^H!%(q 605{,ŎcEV{v(gi$Y *~/n"6ܔ-"6qGԧ$.۾RbU22>н@*@w7jޫ +NX + q>pHWa`->[U(CB=aL|Nxvmf8E4N^-Vn BgeVp|^7#,(DxC JnCtUU;#Sܜ @NDd7;_fL `%%vo/6k $['O!HrDۨ5W*2_FH};xvMS?vՅl5L"q8qmrE.H+\H" +é\"f9Jj5+9sW֢BU*+gE`Z;!QբY. 9%` |[r^ +9C 1ևk A~-MXDNK;[H55cW^8"c[ +F}8^=Dg~sȥuIݯ0z\"t2,ES_׹tlpߘq\dfzhcrB-b[d\$݅m<#ׯq姛=O}$JBuS &AV(=@S>/)3f*bhhl :}%j)f;Nq!e؜UKaRm(8QX6g٭wmq,7ҊʏhyCIln˚{C@A%k1)UWy^I U+Ar 7OBlkbmC5_TVo{~H(+`ZXv2k6u +)σ"O) 9&Nrd5p +Dy;(; IJVI#~;1+8lj +Ϟf·vy^ +o~ȼi  :]Ntn:bCpޏgOkeH Y;*l8 &냵"%1N ʕR #9>QWࠨӵS5›cu9/c(Nj XKJ9gP~LMSa }A'~t@|/8ɮWzuKcVb:-C=ఁ} }E?۠r6[.@qyCH)c:8֬WL׉ I}-U!E@oY ivZw6G9h=/JGJH#Hk5I!':=9lR1~6ԑ9h׈/&-G%'V)]҆}5-@"~sLP;( +xE A)5Y MyU8@1}DajRI: +&4p9ˢL1\Q8cDⒻ"CX<`Ϛ˸cx9E Њ,^\pWjY=#YR(78m"]@1bn/5޺IdN$ ڱ94YU 5HL"iPWR器iXmY X65iw5n"i2[x%d2*mi~SW,ms*:#_sЁ{FP8g IpKyXx$"z-^ J0@*reO  t\cBF{XyM@@BBLf_L0}tbgFmMj7{)qļ0;v8 @D3 U ݋ʉڬ=qt=ë*o JQe)jm!+0э *)43iRoX +m9[,J('" 'd7kp@ S\ePC 4F,8πUTV !=npI&'K9m>݁7GKM}jpr&Z&"TTi-7T "Dy4א 3YJ\Pb,X4b4+=[ZIS[GSt 9yl\R9Or/NWZ2/c~,z 3H(6J"D }tc/e~-j *re/}Ҍ[{[KLEAif2 f B-HE `AdQMvjX#Eg\udO ֱf((m81;DlB:Ɬ2X0*Bi[{Էw>~yr'"{A,`y!>wKg\NX~v5\A`-}2"\*0r\55?XqhAqXJ/dEmXH'"`2wک9:@:m/4 #b<ȞfKI0k4ALQ_W?Ku7Vbx\^7ZZly$-+PK 'hbI|T{P_‰wB +VL2oo>jvCQb9#KKFpN=8qvYyIA Θ@ qSC%ktLk@e;$8I=ϩ?QoY$Yg,_0_> .A_a[ Z͊'ғ2vKI{8a,9x658Op{V},Dt$  dtgu` +!F.gC{|/g>ן>|?ٯ?~?ݷo/~_mO0o ҧ!1q2 ;dd!YVY=RlC!1ݻj\~?~?/x߽Kϗ_#._$_=Rr?P'wrV +Auht( {BӀ _P\*ɇ^x]ʟP4vۮpVǀnKXYA: +JQԒ`2kME@Xn] E~/c+zZLE zM4VVAF\nHpy7p x=U= jHjl,>;K}6}Y$#2.V (,D&j!U_\ +D$xB zZ\t ^IUKeVkXy2Q'By$af5`Wj/;!Cu_׭»"TPv#صi0N +eGAβawd'6عy:.=O5e8̅w(c5T mR*T4RqCtՐjGЗ_Z.M1Ϲ V52> O♻TUBƬ ,2M|7হ6J3+OP@GVE NV] PX +E<\,] +:d<> +xı8)QǿOnIpFF3rQ>r H S|HF zyt!sl/c!BWwl* hPq9FB^*L-# +8+7[@i]i<|XQ 1PvR&R\$fG_k*3LQ~H8CX{hp޸u^9QC꓾Hx!ӹ `>rxT6s\HLi.э +!]M^ fc) uR6NB@@K@y=v?{WP0-T[S'쳨7ȝjRKsk(d,j^<_/Py 2;7da~Is5 MKs +3PC kygXx'LbdN24%KBŖ}+]@Ћ/* w^ f mLt>'E%6na_0Cjm@ohjCI8o +#_KjP21pl &Y1Гģ#WHF|PJ1O5$p”`PbE_rcT0\+Un8UqRcmG!-<Dz&p'!zz>]Hj4£4}4Y1/c: A:im[ TUߓnVzHX&V0֕kyr GjY)kO?̂ekn-Vg`OH\Yo߯wS|[pTdRA~v9W>8zXtN#i :Ca4 +=o : A4ƟCs{NCCswY9 :@i9 84ܜEi9 5O7/n`-DZ@‘ӅFZPQyxg: +~M]WwN%/½}>9rJTBY6.U;:B2hv]DvU/df4%^x+(ة5E`ֺ +$V "`jėe9v=j_͎^h-w5 +|-4ۆKXjD+mt /+zh8TMq=p;ay50pX& z.o|af Z +?ǚᛈ O":/ +q%p!DN%6쬔򽖌;k + ;pm ATsnqtC9N-0|k*/]U^̜ݤ Yfǧ@Z & !Jd,Yl,|M!5wM}++>jƓcsGC{16ƞ&jT )es WuuGg7UWFaf=8AټmnڷV2Qo0f!ͱA^d%+ ,P'2rݠ>, +rR)r@7 xb#͈AhB4w@RS ZheAmq0QAU(U|4 YyDl9??p$({VR/%,tᲂQڸ1 +X| hIu5H`b7iKmZjh62"(d~88#%QBU˭&pY㋑RVJ߯1s#Jޔr[#D&\MW>Uq#-w#wNmw :[Pc2Q0@E[KGhioУWۨ 3V w8cIE; 7pft06>]s]b$&RxwmZc2]eǕ:0I +98x^/O(zuqKfM\_cܝ:X ɬ(9ӕc3ܴA#9ش>Wn7AW 4w[zD-0zyݦRnvu%(kk=& n, 8O G4n g58-WiZ\6VNMaoxym-L&HH&ަԜ͌{¨?pq[`ÿO'0[P或HǺNd#[ޖgc͢,igw_IA̚D;u9 bpG@"sy\r`.ܾ(U۵oo/E-5) +_,+RcP# +O}gt%zq͍WϞݽEn.;<(lICoGÿ9'jBaQS5]kBb{I\)9Q+zo%Kn2( /ԏ]&i.z}B6^>4͗f˾;VOoM(+Ga+'7Gv籫AEmudtlסH<׋oh2Lx35tYsT0^H}%l5>Yd( HQdߛ_$|1./hSzcHrpX_&RHox v~$`Dm/=N{Mʜ0B)_OWfiS,y Dz(鲋xbzY'9WqC+7B梟Y)}cTRp\skbM({ݎ%(|Ŷ(eEky* ;?g::9xwmIkHt9aa;aP_F<4&dhL{.UR';}}Pln>OYKLp褜\Ќ޶$@wڵFv}6}xӖsȶ *&vjjN>Jtxz ׯlW}#'s5Gz 0#ZYUh1`>;& +J+ײsQ%E2 Eڢӑ_f8Ol <Գ  6y6!e©>aV+?]9MүXMϏܣ⣱UMQ~&miw5F;գ'?%a.hlX/Qim-(+@妔<v7`3}0tvQF&V#0>uLg TV4:apmL5ym+iGc=4wgf 볯.1"fg̼glp?R~ޠ͒$f?c*['E!gjʧy.ò<j0QsGܲcň'CK4 `|wH~11E ړ`rCd;rOeĤx߆yBf 1v2(ە`Y.f{m.J7"UbsQ02 +rSA!N@uHcdeHV> ?ncثlVΔXӄ]6Jzn1>m8m꺎-7gh c8J@Gj3QYO {}I(F{R%JgT">A@D0J:l;s 0' c +3 5Xo @t+ H՛IJr@%}uP}{Şznkϊ=ՀejE1:?EĶΨg ;nA׀\ᖡ{؞$}q'm=[MyOnG@?,r_Ctmy}k@نuفe&eź}f+۰<Eԅt=%\en ǷKXॶnN+ v_d v$[r `mMsuqbPw> +h6.fCVЩt6s/cuN*-:E[qկȖp=~knN@J0~l?MaG-xd v3`,⸹`\B/mk + ٬, ^ЍxuB=RU@kD%5-USwW:Fwo0Iᓡ6l}2彾S(UqK7*s]M,) Z^~rÙt Exo vF#rb$Wwjh_;%6K#h 'ii=Fmh&?B9!=N]uq睥=gLIVִ39邐Y+rc Ec~R{LZ,+9Fy<=76O[΋<^ 2 "=8g-eRE.Id ojLA^.[g|Hح@O{ނ[?h9\s%}Zi+Eʃm @]COް$_؟E O#EK?^s7(nLےDp%efQ{9ܭdP,&e&' >F}+G%TE+r~[6=`11.G3s WvR0"_|h~I`/A޹~F[|;k}=6NmxYu:Bb='`M} ӗ.J삢Q3)pݿ"A.O˙yG] O]C*ZP.o4 8eO9& +]#0fN3ݐ%fL$vƀ!] f0xŒieow~,2,@Y Zkb08fUؐ 蟦mQyepD6k= +T.~Np]6s8-atfֽ1;̨} /ʸG 6+/x05|sTFY^E{V`}5ck+觙VnePf'% u;H:oIC \1\ז큵e V%RfS6BD~I6m=gY69$p +F> +Fڻ4O%YdS{)M.ӭX)=pgלQ8)p6e0ƽG/<$ ﳉjTVUB iX9YҼ ,>)^xclxMFLo'FcY5s82_ih(۸iz6 P0n~.'$ޘXUtdTOF#]tJ`+ψ%kC -D8å?%A`_s'Ů3r'A / —@8Ѕ#2Z4%/ypZFCW3e5Rh;'*Gt[Y)UNݺ?5llYvc ce%>./z +Aֳcf`_a2.[81,\_B5KKwSX&J}⯅ ؘԨjԐi(Ll+x N3r[D93(]AE ^~Й +_U ]Hrx O0i4׊b9$0XIMA{P[s-ћxPw +ҁf\=;O@WTN3S)=K58wVKۇw:^x{\)7W'/OGۙ!BfK2H|{hTm6'\_t'&B!vd%&"ɬgt P]pr$l/8O ɖyX2u\)+C!,: l.,G\W+=JE^.VSEGTz<+_hn"%蘭(ЪV]Nɮ"@'_=Ss@ 5lE%q# ܗN`VABʹ\dbA; 2yOI‰Ao;]Q ɳ?G!AO_h&WWC{: 7J춧R23ul3UBoP^LNlX㶔:ͮHwٴQ_tY<4ЃQ!'T gbRx2%TP*K"rm?rIP>4db`Kd.?iI]-|vK,uz`:Th%4IO~ +|5Jhp 0 endstream endobj 17 0 obj <>stream +HtW^ |}' ǒ(RRq"Ez{sQco w p8Z1{ig6WW_x4sҎ)zh,*a%LJ8"PO-~Q類R?a긳ֳVm<-}.󔡴zՕuvxZ%ra\׺¿,z4)k4az#}d(F6T>pڣjmQ6{x EYie֋Q4V.67sF_/:\` +.h"R+1Ù ou65Yw{OPpT1ZmzJ}C9 +U'.Ow4?5Y\a {Doa,S'y=YaHV5b]2B +gG9PJz2:]/i!Eid0E}3i̓0C?Gira?J p0[ q5ek:7yZ#EU?vr+;?/?yw7ݾ|%Lx[__wo?<<~SxLJݻ?:O<߽}?Z8^^|uOn{ow=DNOW?r᪀9*s0f9W<"yQ~f!EK|]yE?~яg9^gW[@z p&kNy}xIU9m &h9ȫu7]ǢinM03lùr|f1]ɠY P X +?_ș]F]\$R$9~jE$ Qf4v"; Ԧ%g15)v$i/ t&4`xJKߺnz@݃+R^w-qE\hYPVHgp:fa`{aOG:gHEkwVVɔ]YaAcvi X<+ ?m.ج@F#*=/(ZYȰ7Kd MP@S_ +9jp3j +VQ M|z5޸E ._k-i 1P {aÌ6 +C6pxf^ m +9# 1&~ڇ8.+_"+:̶! #3,kX)^HA +տܛ-[Ӽ ,n.hZ/ `iGMsBk֦Q_ϠY +ECt##L#ePsa ”XW3AIQ< qm|Vk+K"ی$ hxIV;Pjia,v0ʅrEnMEN&+%ίZ8zAG;+uFtp 8;IΕfإdQF-]sDGX_K$,.#D#Y(Ps:r qL'!^Ehq-sv?vK\|90VG]iϱ CYx +ep r cf˧\H޴-@%fr7LPM@lH!0:QUx%/Rʺͷ8 \Zxz.ˬM4iu 4Zv3T(k!{hn== 2tbzrqGwףGYߩA]MTWK-(<<Ǟ:[X![wᵁ(ǹ_ӑ+  x|k#ԶytW$ dg_g*R:ŋ7 qS<8V4#MHWRKf3@# Z24H +B%r;j^{Oj!,uO*8i:)k % HQSi[ǢWaxvVa7_nZ9)Ïp],%EG+-PC|c`B֦G:䠵axBuu4W˪]g HF2lxāZH.\Z)VNZul\KlX49.jD"ɀ0` lZIjj)if0&'[[Nxr̡t6 5Y؀a5 +E풕Xŭ&Iz AfW#6@4UAF^!03ox==Mq{]Z;lL)g;K;vst\;s֮}"HR/V9AaCkrt@h=[&EeY.]Fw]+&2rS{X̢!@ a`Dv1Jh-o@1 Q6~UvbϿwJiZM F<<ʂdvR H +_;UKiF$UpVD#4^͇\Vc}*ؿz]aR7Sľ}{48_5lO;l)}0f&ۂb:ΌٳtqU^%CsX1nGYRj0``e\o${ZՃ(ޛ5!Zʆ+<1EQ.ebƎ"3K*[X#idi_JwhF"8 C_o]8v;X]'gNӚ/zl[Pl==knlG^oŴM̼ꘂZwxgPZ>jbIJyll9Kvխ[3y3./6Ew_:ۚZuAe \U +eTn CGTK1%yԟ;k-RfL4 +EÎ_5*gur>T+* Z|]t'~,~`on󳇡©܌nX)}w)A񡃠z42FӮ;:n0gwQ;x#Ω-C$HXp|V_kh|si:2bVSp#=sGwWGy.T|-w4apwߡbr Tk)w}X[ߔk]A 68ue}:3gl_=uY BB6Brgg2P:cl#jJ0MfW% UDžMz.s(qG%1aJ,f//+>.ϧ,hU~Th=)#^'UgV%Fw>TI5 +?{hy8. dPv?d!1 np/EPaV8:Eݔ՟v%/Rh*U~[S-kʐֆӞZ Ʉi@:֥nzlEVKmA/_ỳѿ.7e)7yɋaY'sUCsq}Ud 6J`B"^vU`$h8 (fmYҀyg/^ +_17zowwWw?H>/Q @SÇ̞îS&b?B觗x_^>K `ZR$>Y_:HށME;(mS[QAeK"ֳ$$dZqf!v( }h7[e `N$u.Yu%{NnR@"']wsӝVԵۙ+:eX=%n~J-0HKvf !]ɉWv yWb&T}EKK]ERXb螪P;KcڠB=k:k< Q3e73H;cr+۱1dd#rLN=t{|J^]HER= +sʻm$0w6J[ 0E@ 7bh] }e/D(}iӼ&.{!(0J1~z5o5Ɩ9;pG{uտǼ_Oٔ?'>$%ݻb(LLa5LЬ1*Fr~̒s0{6r-fD$ې|\Gz-'$v=gβq3sꡛz8 dpVD +A @5Խh NWMܘԬ +Y)v4{v^m@~*AL={pQ#jBf%(_mQ@OdJ_dTf5" a3u2&G,@o[*홐39Q|L r JJ!X5#F 㟨tZ/@>t[<)(\c)W&\l>-F*LtZGeO6e]R0Yl\.zX\9 .,% $sgrvdIaІ"Li[9o S4&BAW mFM4@mmCKл/kB Z؀j.DGe1Eh%RhouY d _P~lb |fU)cU( Aw]űvě!X ٚ&9۶7Kw""F{ިT‘4Ǟ_rd J]f7w'ؽu!0O[.6Zi8:W3K]Z8UNQfc2Ȩׯ߅(Ĕ '$3zzlW,sAu~qIk*ddQ{=o)S%B𥯥IZuFI0Hy"m?#L +:WőřjΤ:.gCYHEO%r>s߅۠0GP(agsY?][!%^0R' #/)AjSIV1U(fV4Xn4%h[V ,N, 74 *tm֧a/$Z|][aNN(÷2A:3np'q#|$oU`&^GJu!A]K^ oey(Ҽ-(h~M6G@:KUa|(Q~Y`ul\;ں>$'3Rʽ/nr5Z7@H=*iƯ_x 蜣BFT# +B.2YoZOKIoڈ(ƃjA +P?BZxZ7yO,hB tEcsKlC#L$Ku XA:Ѭso=2gdvJ?ۯ;.=Yܠ~J&+&uC(Ƣ ;,("uXgA/sc"~2v@m ֜?ӦA`R \gb/7Wv3@Zb^hפ +G4O&;!.İ:$+JXuG '*WΣ៞OwOgr)L[#-CL,(}zOFXJÇCGA)^@xGsݵ3& ҫ[W2$P% KYFgciDfLȼӄGN.GsҐͳۺU;HS|HPinw ~}ϕ7ecj3zm+g5ЗY@$= '4KZl8H"AD cIgȪy;,B$9IK ƓYF#A=`Ƶdi# +Yf!n‹䰈-ӼV5:$ =2:Yt(l`bLxmjkOl9+sɦ&s.y5Ky)XDSSLwF6ԭѨCchtNds۪w_]FKU aȟ&_+17Kh|a@1qDm(</Θ0Z nmw=fƤ4a^{E"-\t&O#pl*9W-MsYN\)H<p-T"ÞQ\ɦX Bcܬĝ'7L"q|4W+<iIsj8 v0)6>V")z-\}ew`?ቆg(cMp3#5r rۻdŀR}Q[1=VJ}@kcBm8]0_}GǬ/f^;$b2!ݯ ebo\XEĐi ib=68̊q HSoiE 늩"(ldc$q7q" pFz^Gثk9Zo~hO>b$!/Wvs z-[oW=EᰋXP\&/@$MoQNkGsy%X[ 4;.EgazEDL=^%VME򴾅Lr/_->Ӌ uDBk@4('Asd=[n r '2Gs$ywJ֌e%9Yh6i3bpmV&5kC9-`R 8}Ahup<>蹫 ۵-K`',?hRO\3NCWnb ! Uj3LPv:F:C18&pd֡- +@dp:֛Dm M"3nWN55F,~W;#/vPRƫLXʧ7gt*}#a=&q J\T]J0"Qu9!vPmx`܎Eieu, -"TK٪6Q.AЌ`=՜f:j9?6f¼1Hm^%=gڲT~/:Ƒ[ 63L{^Nu`.(š#hlb갽D=<_Z(BCE[q:kbCZO{c eb ?U69P:Vg ߥhpjLgx+a]u甪jr[ VHȢ@kߟ!ųɍHXVؽ eYܥ礚dv +-] O/MAT}9IF7! 0_Vsr)dnqe] m}+Num$5{"9X- Su,\Yw242MGz(wgK X6;w2Z_7ڃF4>:V[fz$pPv$Ir@*:,'ϣu;`dV,d&cE3Ip^w]tY߂C7+tޗ +`i+LɟIegEB ᳱtlc ?ncNKeF鋍1LݯwFW;wN`ohA+pO&z5vDDt?tdNjQg X#ΦߚiB NF?7o@IܧE/{8#Ag0d +bbg= ;w2w]fq)X~N "gxWFpEqcQx. X%p BҜ0JW8D'7:0qg Pwo)5 +EUf>h)+45Bxo[fyݏS45Jg^vȃNuymR4(@H> a1hѐVc.FGh_z`ӌ5>1/b%~\|΋"% T_{9αl3=SOڧ<܍"\#)6}'.oW!.:8I=P'suFcK=l(R"i> ^,26W>Hb5RUw+(>ꡋpvkϛlpl+7f؝ `B4 }}JZp"QZkwkb3{ǒߍ7q8,3zc4if T_Lzr-X(KyިNVGnQiYӳÉZO[Uӱ\4xIǫyr87^KSc4h )l~x׼ p;$/V}E=,N aF2J\/IX^Cּ~5,X,&$;j1+H1@=$$R +DPR$+rQVmRgIzՋcfz]keVm#ՀR3yՓ -_YCFYc#2D +nrE1}yvXq$֣ CHnA䈣|7wY\LՒ)lZU7ʈ&JXj%yg2c5hvFkCVr_v`s>GV$^LuSq5BluS + Q"-v $cٱr5!~v.-WFJ +?pG3nȧ[|(K}\LY>W(gtW4*GM̐%xj͈SMzhhQ`/sG<]6Q~_bn}L>g@f Gqh攜Rj xhw^tATJՒGcjLbRס3Z\> WCK m|=ڲ;[S,"`0ošCHo̔ȫ!q$g 8P=t櫼DWtS)o\q5ưL9w~;LeKffjr5]-IU[A~8 +cz|5h>+ nq6G٢zU0# 69AY9B[*L Od ,jpHz;s5 C`bbt&l%f-S(sG]zB(Y-F%=MSS!3`ZRE^K~R|\C@T=R,H4id)ƁkU[ =xHK0rFĠڷ(BSNkha@ HNFb|*6v1 xS^ %ex{FM)9Ɲ$b"t) +׭b|bܚiDGw4ӂ5#*X[+$|!X+A>$eW#wb(t τoO0A7ZHedCF[MPC8~3vMoBIS=?[aK(FjCwE ~aŀ1Q%e_V$.j" lr) Qk-ePaʪMrQҧRx!Q՚-3w ڳA6 Z5pTfJ@ ֱmk %/&Kֵ Brgцr+"AUNvSxd2"Czsz?TBĔ8w)hĸ;=>ͳwhw,Hd$ !FBE ʌy3((6OeWmjZ-jo&9$)mC5.#Y /RK\GV5mc1op+&L1$~,IuTB+J٠@TWI(A;WUy7:,k0*~$j (Fdjb4DnPYy,Nn{?V,\/0d+UڇE%oN 4l +r +Z=А +*3i5' s,aWO^:ZE@p[h: B]`7G3-%R4fݥ]] qyLEָyd6@^&ԸfJ'nѺˏ0<܇Wrp }a 䉙.^_~'ϯg/{q~|ˋOo7˳W7'b~|}{O~w8\.qy{by?dy+/yѤ⫫wû߽[W|;wjy|r?ꊇfws~Mçvbqxqb]-gdºt7>r} ^/` ߺ|_z6m}g'|TUw>~e}GѠ%l_%O&cvCc vYsO<'V/ 1cCܔHAKO'}%zKNSytIV|ؙ?ǬPLm{X7 3xL a=NA4Mn  +񗫋{^<~?P֓kD|)闇뷜ݯ._umJ YvAы8=id{ڢ( +Rl5dHr{?3$84i"H3| f%7ȷ;]7CfK 'B՞Ć-VqqgKlIսpdM/a%S7Uy*o +?J3E/!G @o]G5T~>8JwYC]" r;Y3/ؕޫAh TBI*"`/";`z78ޟ?/;r`:[uh}Ĭ l)w &Ϭ\=,*k`\rv=;kouJu"/<\c%Ľ*e%R/2VU\L%k=@Bb@:"Ye^rQt9/Õ:}--$+ZmzA^~J 1V<-֮8 7>}tBĂ8=6 Ch" B,xHC“.=܃!8!7$8R M)6l4}#|o?Q=` (.8'Ӥz,oqG^đ}R/-.;rU^ylQ?bB&U'ǃ^x?A8vQ0Ql"oR% :^IcR~ZJL#,G?@s^`lGX] {I9MzNP(ΖIglH{'kOg$NoN/R32 v|KƜBgu5ȧ-%L3:7LbS |E&;y=blp<ֳ;=v2|yKTnߟI72HxsrR5U5\HQG%5ϾV%JK,zGyR7[mJO5( mQ@k^I¥C@ ӥ;JWuקkK/NNY1X喩]޿~Ieʦ>$nܖwJq8 +8_ +pG89zǸ@V7rQ#[ڽb.=o^$ <^7mHA"CnЫbaQ͊UW ~_юw(n |0#,KAwGOkX_nx&yZ"O#;1;DZD'_ w!:ȣƆ +{ ⵀ |^pvPKx'\ژRjթPW4_U;228&hY]ͤu[0[չylGؙ$((mF0wGK>\',. + +oU|2tquk])2ůHѵӾum pc巽WEW5p|uYL* qiӤF)j*/b( \[<0X{ #8^7>`?&h -&k׮H=te1tEDcjhNj.p_Q!Ǣ%&Gv@G?y$&O3x>`' [ͼҴ +xi!o=l*fFd7Їb}V}O CpbmkR DZb\MhbeŖb] dx"JҮ0s1Y#Kr09hh_c`+BS!S% 13@ݾ_h*^uMqLM{Z5X`a%6Ue2oDGN:Ar ((%t.ב'C7C +Jڑ%- :LYU"V2NjMIdOr4ח~ŐjF9(RKDI(zP\x]-I{ݲH[C@##Z^z>~Az,޾tTݝ=Ӛ +$8x{v嘰dF3'tc =2F^DB݂Q J0mK>\|xpqA0MokteKҟNS1YlCNciRrT!Q JMLIWrmB%Nn!M.7 ʵMZk=HFyrIB:=31tXdhaӊ"HּNJ̓NEQq~M8ݙpĩ!zKk3toޖ, +¡X8k( _{:c\µOot#'M0=r%QGFЁK}} +5PsQ\aHBmLf%Ps.|wDM#ϥ@*=t< ȥ@'l;lL\ tXÿ"+qcazAǃ +[4h|{7\Eg;~4;|KkkpX;a퓵F&e~[es%Cd /P;pj2dUXzLŽ&҅\3pٜd'JPr'͘%U[O9 +Kڔ"dWR9QF.Spi'H."x9:^Q! NWĨxEZd +85)*2č?SȾ׺`E!^ܝ0 \KoR֒\|o]OT@O X+ 4&d$m'b}C~n2ov-Fx{ϦSyImWR{KԕNN'c'#7CkIS_\D=|QRo[(<- endstream endobj 28 0 obj <>stream +Hnߡo`ݩU皹bD!$H(HQ<@v"O?ս $6 +wG&j׮êu_B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B)Փ?L?-/l;;z~[޿~G&mKg?N}l>~ۗ-ys>~jfGo0;71{3 2'{xiV{x mK/}A[W!_|?7?A'SW~׿0;}J(K}2R+;g\_N%kR@X]Z(p>hcd,?O6Kĝ-"|[@VΉc^ +HH%1%2bkcYeA8-ϱt}.~\8bZ_6nK1 +F {HY,5?o%J%$MCxYpwʽckeAֻ5WS*mգmݔ!md$6mM1*(UY.~VĘ4+0bP8ݴW޾0[BAu;ÒP*ҠDc} +ʹ0꼣ƏSt/i2 .qvӂ3N 7r/ݏMn-R ǗS'Zv@K u,+lu ǏIWgd=f$+u`p3ѭ-yG~T:ߢGi`RWY[eG$,UCtW.S +=&@RTOQpZ;agk%8TrL(uW%5wAc#fCKaHtXGDpp XKN `RJW!WC^c +fݰ)Gw_NR;d#AhZ=V9T4AAR#PS{&dj) aJ3n:M{9CFXz@ܲN,A0@gDFCw=4#ւ#chP2FiԽ[DnbX꾔C E o ;)oqp ԔlGv6c1ꚗs Dh^$JImyEd@1Q \F `F>VF:z*>ৠY3)ܸE*2=@7I$7pl. X/:c; Wx(W*Ӫ:tk۝ BεՓL6;r{ +Xgׁ_3T#fjOxÄ^ Ȅw7_p0/,AxG@x1){t3QG6y;Z<+yBdy9 & e~x`Cg1[iJ)!C1|R퍵}(ýqəV@v§MŽݙEZK RBCie1 q~ m}~LG$24QjUjeCVZLC .=6f}d>|nod-#&ײds'#[V:T4Ȁ?~gX˶iXgp}@jǡýKYrjsz`C,(!Q>< +0CzqEQ z"H1tCBij l9AϩjJVMι{m۞W*K RHD)é#J&a,|3MEJ0TSϝ2-7T0;M(I0fQـJk$[]]tIkQ~Yw - K(H5,6 8Qͥ9BD,8'$[s..O4J〦F),Z ZOn|e{Y!|wqM|)e=Dg +L܁㛧Zִ(ƈaJڕڢZW0z~KkKy[-#4sfݟ?+JP{"8"iteIyga)&DU AOTIpVTdF2\BT~WEe$;IȤ)@%os %z=V[|`r;=K $_'d +!{UVWZH]TAm59QiخxZQ`AnL]|}DtDh fPtn(.L?ttJiRJIN*.hTHeR:A +&3.zSuq +~MvC-zƫ-\/ u8XE* ĿD +2}/4VG'-h^e2ʨdq?cߞ YASp,s)o-j$1|l#*{EseppG-+RIey(f~@ +DCTʒGt"Uk[ڛDY[T-'XHievr::U[E!iGlt6QFFɓ|.)͜,1q +C6#7U,\=,f!Y:n +C fA9xs5ɠRt CM\HmIԋZӸIvފzq5Ar48K9VBn9㓶 @ͩ3ҬSt ҕyZz^MZ/Q?l'}qؤI(T7u Mah؝ٱf14CiCV{VTWj.AA6Sgͺ?w8FXF?q#1a!:<d]dQhI.fņcWPbOQџeL 8H(}R/Z#WUя(I|%ѺӮ[$ xl o7?iIk/k{Ў)Bi8f,cH9AvYcإ lqe4rB5ZjwEW;hp `Y'WnۉWysqƕI6d +]H1QE`P[!WÛڶpnZt#E0~#BZ1/63 ~W_o_y\WW7˷W?\fO/On3G'7 endstream endobj 51 0 obj <> endobj xref 0 56 0000000003 65535 f +0000000016 00000 n +0000038673 00000 n +0000000004 00001 f +0000000029 00000 f +0000038724 00000 n +0000161526 00000 n +0000161598 00000 n +0000162214 00000 n +0000216674 00000 n +0000247363 00000 n +0000289555 00000 n +0000331582 00000 n +0000360909 00000 n +0000378792 00000 n +0000382702 00000 n +0000397746 00000 n +0000421524 00000 n +0000163124 00000 n +0000178251 00000 n +0000186979 00000 n +0000197140 00000 n +0000223103 00000 n +0000267362 00000 n +0000311259 00000 n +0000353936 00000 n +0000374513 00000 n +0000382545 00000 n +0000442471 00000 n +0000000000 00001 f +0000159917 00000 n +0000044422 00000 n +0000044193 00000 n +0000044080 00000 n +0000159202 00000 n +0000160755 00000 n +0000160850 00000 n +0000159345 00000 n +0000160551 00000 n +0000160646 00000 n +0000159488 00000 n +0000160347 00000 n +0000160442 00000 n +0000159631 00000 n +0000160143 00000 n +0000160238 00000 n +0000159774 00000 n +0000159944 00000 n +0000160039 00000 n +0000044309 00000 n +0000039921 00000 n +0000447079 00000 n +0000160965 00000 n +0000161013 00000 n +0000043225 00000 n +0000000077 00000 n +trailer <<8B08712331A543208E3B6950530BAF8B>]>> startxref 447248 %%EOF \ No newline at end of file diff --git a/data/flarq.xpm b/data/flarq.xpm index 08d16c79..50935eb1 100644 --- a/data/flarq.xpm +++ b/data/flarq.xpm @@ -1,975 +1,210 @@ /* XPM */ static char * flarq_xpm[] = { -"48 48 924 2", -" c None", -". c #5B1E0E", -"+ c #7F381B", -"@ c #A7624B", -"# c #A8624E", -"$ c #652012", -"% c #90555F", -"& c #AA7A86", -"* c #D4B5BE", -"= c #5E231C", -"- c #540900", -"; c #AC5D55", -"> c #B4644F", -", c #CF7F58", -"' c #FCAD85", -") c #FBB18F", -"! c #BA7057", -"~ c #965140", -"{ c #4F1509", -"] c #3B1314", -"^ c #45151B", -"/ c #895156", -"( c #AB8687", -"_ c #D7C6C1", -": c #FFFFFD", -"< c #FFFFFE", -"[ c #A58088", -"} c #945D68", -"| c #642D34", -"1 c #AC6352", -"2 c #A45C49", -"3 c #A35B46", -"4 c #CC8C74", -"5 c #F4B8A0", -"6 c #FAC5A8", -"7 c #FFD4B3", -"8 c #FFD8B8", -"9 c #FFDCBD", -"0 c #FFCFAC", -"a c #E7A380", -"b c #A2563C", -"c c #984D37", -"d c #A2787A", -"e c #997474", -"f c #AA8B91", -"g c #D1C0C6", -"h c #CAB3BD", -"i c #FBE6F1", -"j c #F9FFFF", -"k c #F8FAFA", -"l c #FEFFFF", -"m c #F3F2EF", -"n c #E9D7D9", -"o c #AC9092", -"p c #AC8C8D", -"q c #926A6E", -"r c #9A737B", -"s c #9B747C", -"t c #9E573C", -"u c #98543D", -"v c #9A5F47", -"w c #BF8469", -"x c #E9AE90", -"y c #FFCAA8", -"z c #FFD9B6", -"A c #FFDFBA", -"B c #FDE1BA", -"C c #FDDEB8", -"D c #FEDBBB", -"E c #FBDBC3", -"F c #F8DBC5", -"G c #FFDCC3", -"H c #FFD1AF", -"I c #FBB891", -"J c #E79B74", -"K c #9A4E30", -"L c #9B5644", -"M c #7D4F54", -"N c #D0BCBE", -"O c #F5EDE7", -"P c #FCF4EE", -"Q c #FFFAFC", -"R c #FFFFFF", -"S c #C7BDC6", -"T c #C4B0BD", -"U c #F4F3F8", -"V c #FDFCFF", -"W c #FFFDFF", -"X c #F7FFFF", -"Y c #DEDCDC", -"Z c #E6E1E1", -"` c #FFFAF9", -" . c #FFF3F5", -".. c #FFF4F7", -"+. c #E2D9DA", -"@. c #C1AEB5", -"#. c #C5A3AF", -"$. c #7B5057", -"%. c #7D2F24", -"&. c #C87559", -"*. c #EA9464", -"=. c #FFA873", -"-. c #FFB886", -";. c #FFC193", -">. c #FBBD92", -",. c #FBBE92", -"'. c #F9B98A", -"). c #FAB784", -"!. c #F8AE77", -"~. c #F9AC76", -"{. c #F3A97B", -"]. c #F3BB97", -"^. c #FDD7BD", -"/. c #FEDCC3", -"(. c #FFDBB4", -"_. c #FED2A6", -":. c #FEBF94", -"<. c #E89574", -"[. c #D07355", -"}. c #C06F4F", -"|. c #C09581", -"1. c #F0F1E9", -"2. c #E8FBF4", -"3. c #EEF9F3", -"4. c #FDFDFE", -"5. c #FDF8FE", -"6. c #EFE7ED", -"7. c #A6969F", -"8. c #F2E9EF", -"9. c #F7F9F9", -"0. c #FEFDFF", -"a. c #B2A3AC", -"b. c #CBBFC7", -"c. c #FCFBFE", -"d. c #F9F6F8", -"e. c #F5F8F7", -"f. c #F6FFFF", -"g. c #69302D", -"h. c #5D0100", -"i. c #A0402C", -"j. c #CC7D59", -"k. c #BF6F4E", -"l. c #C16645", -"m. c #F6996A", -"n. c #FCA264", -"o. c #F8995F", -"p. c #F3925E", -"q. c #F29968", -"r. c #F29F71", -"s. c #E79469", -"t. c #C26640", -"u. c #CF6A43", -"v. c #FD9366", -"w. c #FF9B68", -"x. c #F99B63", -"y. c #F19F6E", -"z. c #EEAB80", -"A. c #F8C59B", -"B. c #FBD3AB", -"C. c #FCD2AA", -"D. c #FCD9B1", -"E. c #F8D1AA", -"F. c #F9C596", -"G. c #FFB371", -"H. c #FEAC6B", -"I. c #D69B78", -"J. c #EAD5D1", -"K. c #ECF6FA", -"L. c #F1FAFB", -"M. c #FFFBFF", -"N. c #FDF4FB", -"O. c #FDFAFB", -"P. c #D3CACE", -"Q. c #D8C7CE", -"R. c #F6FAF8", -"S. c #FEFCFF", -"T. c #C4B4C0", -"U. c #D3C8D3", -"V. c #FAFBFF", -"W. c #FBFBFF", -"X. c #FBFDFF", -"Y. c #F7FEFF", -"Z. c #F8DEDA", -"`. c #B76C57", -" + c #D76E4E", -".+ c #F89463", -"++ c #F9A36A", -"@+ c #FFB783", -"#+ c #F5A27A", -"$+ c #D0744E", -"%+ c #EB9060", -"&+ c #E68655", -"*+ c #EA8855", -"=+ c #F1935B", -"-+ c #F0975D", -";+ c #D27B43", -">+ c #E18450", -",+ c #E98B5A", -"'+ c #DD7C50", -")+ c #D07242", -"!+ c #F9A06A", -"~+ c #FFA771", -"{+ c #F6A26B", -"]+ c #EE9D67", -"^+ c #EEA26D", -"/+ c #F2AA77", -"(+ c #ECA776", -"_+ c #EDAC7B", -":+ c #EEB17D", -"<+ c #F1A55D", -"[+ c #FFA45C", -"}+ c #DC855E", -"|+ c #D9A3A2", -"1+ c #F5F0FC", -"2+ c #E9F7FA", -"3+ c #F6FDFE", -"4+ c #FDFBFE", -"5+ c #F8F9F9", -"6+ c #D1CFD0", -"7+ c #CCB9C0", -"8+ c #F9FAF9", -"9+ c #FBFAFC", -"0+ c #F7F0F5", -"a+ c #D7C6D1", -"b+ c #E7E0EB", -"c+ c #EAF4FB", -"d+ c #F1F9FD", -"e+ c #F9FEFF", -"f+ c #F2FCFB", -"g+ c #F6F5F5", -"h+ c #CA9E8E", -"i+ c #F4A27A", -"j+ c #FAA77A", -"k+ c #F6B280", -"l+ c #F5C896", -"m+ c #FED8AD", -"n+ c #FFCFAB", -"o+ c #FFCCA8", -"p+ c #F8C39B", -"q+ c #F5BC9C", -"r+ c #F2B48F", -"s+ c #ECA878", -"t+ c #F3A86C", -"u+ c #FCAA68", -"v+ c #FAA664", -"w+ c #F9A76A", -"x+ c #EC9B65", -"y+ c #D38048", -"z+ c #E69056", -"A+ c #E0874E", -"B+ c #FAA26B", -"C+ c #FAA470", -"D+ c #F5A06F", -"E+ c #F59E6A", -"F+ c #FA9C62", -"G+ c #F99A5D", -"H+ c #F49E6C", -"I+ c #F89E63", -"J+ c #FF9D5E", -"K+ c #ED8F64", -"L+ c #B67466", -"M+ c #F5EBF0", -"N+ c #E4F6F9", -"O+ c #EAFCFA", -"P+ c #FDFFFF", -"Q+ c #F5F8F8", -"R+ c #E6E6E7", -"S+ c #BEAAB2", -"T+ c #E9E2E6", -"U+ c #FCF9FB", -"V+ c #DFCFD2", -"W+ c #C4AEB7", -"X+ c #FAF0F9", -"Y+ c #EAF0F6", -"Z+ c #F3F8FC", -"`+ c #FBFEFF", -" @ c #F8F9F8", -".@ c #EADFDD", -"+@ c #B47A60", -"@@ c #E99560", -"#@ c #F3BB8E", -"$@ c #FDD8B6", -"%@ c #FFDDC1", -"&@ c #FDCFB2", -"*@ c #FECEAD", -"=@ c #FBD0A7", -"-@ c #F7D3A7", -";@ c #FAD1AA", -">@ c #F9CAA1", -",@ c #F8C392", -"'@ c #FAB179", -")@ c #F9A468", -"!@ c #F9A166", -"~@ c #F69F67", -"{@ c #F9A470", -"]@ c #FDA56E", -"^@ c #F69A5A", -"/@ c #D37536", -"(@ c #D1753D", -"_@ c #EF9868", -":@ c #F8A67A", -"<@ c #F39F71", -"[@ c #FB9E68", -"}@ c #FF9D60", -"|@ c #FA9C65", -"1@ c #FAA06B", -"2@ c #FA9C63", -"3@ c #FDA26C", -"4@ c #D5926E", -"5@ c #F2DFDA", -"6@ c #F0F3FD", -"7@ c #EDF3F8", -"8@ c #FEFCFC", -"9@ c #F9FAFA", -"0@ c #F3F4F6", -"a@ c #A2929B", -"b@ c #C0B1BA", -"c@ c #C4B0B0", -"d@ c #AC9398", -"e@ c #FEF1F8", -"f@ c #EEF2F7", -"g@ c #F2F3F8", -"h@ c #FEF9FB", -"i@ c #FBF2F0", -"j@ c #EFD9D8", -"k@ c #E09D81", -"l@ c #F0A268", -"m@ c #F9CCA1", -"n@ c #FDD3B7", -"o@ c #F2B094", -"p@ c #F3A377", -"q@ c #F5A66E", -"r@ c #F4A873", -"s@ c #F3A476", -"t@ c #F4A66D", -"u@ c #F6A367", -"v@ c #F9A269", -"w@ c #FBA169", -"x@ c #FD9F69", -"y@ c #FC9F69", -"z@ c #FC9F68", -"A@ c #F99F65", -"B@ c #F4A471", -"C@ c #F9B385", -"D@ c #F6A36E", -"E@ c #F19359", -"F@ c #D1743D", -"G@ c #E3905E", -"H@ c #F5A370", -"I@ c #F59F69", -"J@ c #FAA062", -"K@ c #FBA05E", -"L@ c #F8A26B", -"M@ c #F9A46F", -"N@ c #FAA160", -"O@ c #EA9C62", -"P@ c #C3998A", -"Q@ c #F7EBFA", -"R@ c #EEEAF8", -"S@ c #F6F4F6", -"T@ c #FCFEFF", -"U@ c #F4F4F7", -"V@ c #E4DCE3", -"W@ c #D4C1CD", -"X@ c #F2F5FA", -"Y@ c #AEA19F", -"Z@ c #C2B0B5", -"`@ c #F9F8FC", -" # c #E5F2F8", -".# c #EAF5FB", -"+# c #F0F5F5", -"@# c #F9F7F7", -"## c #D3B3A9", -"$# c #DF916B", -"%# c #FAA76E", -"&# c #F3B787", -"*# c #F0AE84", -"=# c #EE9D6B", -"-# c #F6A15D", -";# c #F7A559", -"># c #F9A160", -",# c #FE9B68", -"'# c #FD9D67", -")# c #FC9F67", -"!# c #FA9F69", -"~# c #F9A06C", -"{# c #F69F6A", -"]# c #F5A067", -"^# c #F9A464", -"/# c #F5A35C", -"(# c #E9A779", -"_# c #F8D5C1", -":# c #FFCEAA", -"<# c #FAB079", -"[# c #E1884B", -"}# c #CD713A", -"|# c #F39961", -"1# c #FAA56C", -"2# c #F8A668", -"3# c #FFA864", -"4# c #EF9965", -"5# c #E59462", -"6# c #FBA360", -"7# c #F49958", -"8# c #BE8469", -"9# c #E7DAE0", -"0# c #EFF2FB", -"a# c #EBF0F3", -"b# c #FBFEFE", -"c# c #F6F6FA", -"d# c #FAF3FA", -"e# c #B7A0AF", -"f# c #C4C0C8", -"g# c #D4CECD", -"h# c #DED5DD", -"i# c #EEF5FC", -"j# c #E4F0FD", -"k# c #E6F2FC", -"l# c #EBF5FB", -"m# c #EAE0E9", -"n# c #B67A69", -"o# c #ED8F5B", -"p# c #FCA368", -"q# c #F59E66", -"r# c #F9A067", -"s# c #F9A165", -"t# c #F99F66", -"u# c #FAA069", -"v# c #FAA169", -"w# c #FAA166", -"x# c #F8A264", -"y# c #F7A262", -"z# c #F9A162", -"A# c #F59E5E", -"B# c #FCA464", -"C# c #F0A172", -"D# c #F8C7AA", -"E# c #FFDFBE", -"F# c #F7D7AF", -"G# c #F7C497", -"H# c #F19C6B", -"I# c #DC7947", -"J# c #E48552", -"K# c #DD8553", -"L# c #BF6033", -"M# c #E28B60", -"N# c #E99B6D", -"O# c #F2A367", -"P# c #FA9F60", -"Q# c #E89874", -"R# c #E2CBBF", -"S# c #E9F6F7", -"T# c #EAF1FA", -"U# c #F6F6FB", -"V# c #FAF9FC", -"W# c #F9F1FA", -"X# c #BBABB5", -"Y# c #BDAEB7", -"Z# c #DDCBCC", -"`# c #FBF1F9", -" $ c #EFEAF7", -".$ c #E9EFFC", -"+$ c #EAF0FC", -"@$ c #F1F6FE", -"#$ c #E2CDCB", -"$$ c #D28869", -"%$ c #FFA26B", -"&$ c #F99F64", -"*$ c #FAA065", -"=$ c #FAA167", -"-$ c #FAA168", -";$ c #F9A066", -">$ c #F7A168", -",$ c #F7A167", -"'$ c #F7A165", -")$ c #F9A163", -"!$ c #FB9F63", -"~$ c #FA9E65", -"{$ c #F89D64", -"]$ c #FEA667", -"^$ c #F4B072", -"/$ c #FBD2AB", -"($ c #FBDFCB", -"_$ c #F9DECA", -":$ c #FBCBAA", -"<$ c #EFA579", -"[$ c #D3764B", -"}$ c #AE4621", -"|$ c #EA865A", -"1$ c #F8A674", -"2$ c #F8A16F", -"3$ c #FAA66A", -"4$ c #E38A65", -"5$ c #D5AFA0", -"6$ c #F1FDFF", -"7$ c #E9EFFF", -"8$ c #EEEDFC", -"9$ c #F5F4FD", -"0$ c #F0EDF6", -"a$ c #F5E9EF", -"b$ c #C6AFB4", -"c$ c #A28385", -"d$ c #FFF7FE", -"e$ c #F1E8F9", -"f$ c #EBEFF9", -"g$ c #EBEFFA", -"h$ c #F0EFF8", -"i$ c #D5B09E", -"j$ c #ED9B6E", -"k$ c #FDA168", -"l$ c #F89F66", -"m$ c #F89F65", -"n$ c #F6A066", -"o$ c #F5A166", -"p$ c #F6A065", -"q$ c #F8A065", -"r$ c #F9A167", -"s$ c #FCA06A", -"t$ c #F99B68", -"u$ c #DA7F51", -"v$ c #E88B52", -"w$ c #F9A15D", -"x$ c #F1AF7D", -"y$ c #F8D0B1", -"z$ c #FBDCC7", -"A$ c #FDDEC9", -"B$ c #FED4B9", -"C$ c #FBBC9A", -"D$ c #E58C65", -"E$ c #DB794C", -"F$ c #F69F61", -"G$ c #FF9F61", -"H$ c #FD9D60", -"I$ c #FAA163", -"J$ c #F79C6E", -"K$ c #DCA289", -"L$ c #EAE3E3", -"M$ c #ECF2FF", -"N$ c #E7F0FB", -"O$ c #E7F3FA", -"P$ c #E7EFF2", -"Q$ c #FEF7F9", -"R$ c #B49DA0", -"S$ c #C0A5A8", -"T$ c #F7F6FB", -"U$ c #E9EAFB", -"V$ c #E9F0F8", -"W$ c #E9F0FA", -"X$ c #F5F1FA", -"Y$ c #DBAD8E", -"Z$ c #EF975E", -"`$ c #FBA16A", -" % c #F7A065", -".% c #F6A165", -"+% c #F6A067", -"@% c #F6A570", -"#% c #F4A673", -"$% c #EC9A6C", -"%% c #D1794A", -"&% c #E68752", -"*% c #FDA26F", -"=% c #F2A374", -"-% c #F9C29B", -";% c #FFE0C1", -">% c #FDDDBC", -",% c #F4C29D", -"'% c #E09266", -")% c #D67F46", -"!% c #FB9E5C", -"~% c #FF9D63", -"{% c #FBA972", -"]% c #CE805C", -"^% c #C8A39D", -"/% c #F2F5FD", -"(% c #EAF1F4", -"_% c #E6F2F3", -":% c #E6F5F4", -"<% c #E7F1F1", -"[% c #EAEDED", -"}% c #E6E0E3", -"|% c #E7F3F7", -"1% c #DEF1FD", -"2% c #E7F2FB", -"3% c #EBF3FB", -"4% c #E7D7DC", -"5% c #D5916A", -"6% c #FCA265", -"7% c #F89E68", -"8% c #F8A066", -"9% c #F29F67", -"0% c #EFA56E", -"a% c #FBC490", -"b% c #F6BC8A", -"c% c #E9A26E", -"d% c #D8834F", -"e% c #E58456", -"f% c #FF9B6E", -"g% c #FAA16D", -"h% c #EDB075", -"i% c #F3C790", -"j% c #FCD7AD", -"k% c #FED4B6", -"l% c #F6BB94", -"m% c #CE8350", -"n% c #D6854A", -"o% c #FBA16F", -"p% c #F39F6D", -"q% c #F1A86D", -"r% c #E89568", -"s% c #D79F8D", -"t% c #F4EDEE", -"u% c #F0EEF8", -"v% c #ECEEF6", -"w% c #ECEFF9", -"x% c #ECEDF7", -"y% c #F1F0FC", -"z% c #F0F4FA", -"A% c #E6F2F5", -"B% c #DCF5FD", -"C% c #E3EBF7", -"D% c #F9FBFF", -"E% c #C19A96", -"F% c #D57E55", -"G% c #FDA366", -"H% c #F99F67", -"I% c #F99F63", -"J% c #FA9F63", -"K% c #F99E64", -"L% c #F8A86F", -"M% c #F1A66F", -"N% c #F8B985", -"O% c #FDD4A2", -"P% c #F2BD89", -"Q% c #F5A971", -"R% c #E28955", -"S% c #D97847", -"T% c #F69962", -"U% c #F4A66A", -"V% c #E9A46A", -"W% c #F2AA79", -"X% c #F9AE84", -"Y% c #F6AB7C", -"Z% c #EA9B63", -"`% c #E49159", -" & c #FFA572", -".& c #FBA36B", -"+& c #F8A363", -"@& c #FFA66F", -"#& c #CE7F5A", -"$& c #E9CAC3", -"%& c #F2F3FF", -"&& c #EBEDFD", -"*& c #F1EFFF", -"=& c #F8F1FF", -"-& c #FAEFFE", -";& c #FDF8FF", -">& c #FCF4F9", -",& c #F4F9FA", -"'& c #F9F7FF", -")& c #FDE9EB", -"!& c #D99781", -"~& c #F59668", -"{& c #F8A165", -"]& c #F8A164", -"^& c #F7A063", -"/& c #F9A164", -"(& c #FBA069", -"_& c #D98350", -":& c #DA8954", -"<& c #E79A68", -"[& c #FAB887", -"}& c #F6B181", -"|& c #F5A46D", -"1& c #F4A15F", -"2& c #E6914E", -"3& c #D37D41", -"4& c #EA9569", -"5& c #F8A078", -"6& c #FC9E6C", -"7& c #FE9D5C", -"8& c #FF9F5B", -"9& c #FFA46B", -"0& c #E58B5F", -"a& c #F09769", -"b& c #F39562", -"c& c #F09762", -"d& c #EF9A6A", -"e& c #D67F58", -"f& c #BB8678", -"g& c #F6F6FF", -"h& c #F7F4FF", -"i& c #EADFE9", -"j& c #D8C4CE", -"k& c #DABEC8", -"l& c #E3C8DB", -"m& c #E9CAD1", -"n& c #ECD7D4", -"o& c #EEDFE4", -"p& c #B98787", -"q& c #D9805B", -"r& c #F9A266", -"s& c #F6A360", -"t& c #F79E64", -"u& c #F6A466", -"v& c #F6A465", -"w& c #F9A065", -"x& c #FD9E67", -"y& c #DC7E4D", -"z& c #C7693C", -"A& c #ED9167", -"B& c #F4976B", -"C& c #FBA160", -"D& c #FFAC67", -"E& c #F49B60", -"F& c #D6784A", -"G& c #E5895F", -"H& c #F09662", -"I& c #FFA866", -"J& c #FFAD6E", -"K& c #E07F5D", -"L& c #7B2B1B", -"M& c #853D24", -"N& c #963E27", -"O& c #8D472B", -"P& c #824730", -"Q& c #843A2A", -"R& c #712A23", -"S& c #BA9092", -"T& c #DABABA", -"U& c #8B6E6B", -"V& c #4D3232", -"W& c #5D2D3D", -"X& c #68353A", -"Y& c #734744", -"Z& c #6A4A4C", -"`& c #663235", -" * c #934833", -".* c #DF8766", -"+* c #F99766", -"@* c #FB9E61", -"#* c #FFA66E", -"$* c #FCA16D", -"%* c #F99E69", -"&* c #F7A169", -"** c #F3A266", -"=* c #F4A365", -"-* c #FB9F68", -";* c #F6A16A", -">* c #F6A16B", -",* c #FCA06C", -"'* c #FC9D69", -")* c #FF9D6B", -"!* c #FF9E6C", -"~* c #F69563", -"{* c #D67949", -"]* c #D47348", -"^* c #F79567", -"/* c #FA9F68", -"(* c #F9A265", -"_* c #FFA166", -":* c #FC9B65", -"<* c #E98D5B", -"[* c #C4683A", -"}* c #BE6339", -"|* c #B06D4E", -"1* c #732F25", -"2* c #64201E", -"3* c #8B463B", -"4* c #B6573A", -"5* c #D06B39", -"6* c #D37A42", -"7* c #F4986B", -"8* c #FC9C73", -"9* c #F99F6C", -"0* c #F4A766", -"a* c #F1A561", -"b* c #F49E63", -"c* c #FB9E6B", -"d* c #F7A069", -"e* c #F9A16A", -"f* c #FCA16C", -"g* c #FE9F6C", -"h* c #FFA06C", -"i* c #FBA468", -"j* c #F49D5F", -"k* c #ED925B", -"l* c #C86A3A", -"m* c #DF8653", -"n* c #FBA26F", -"o* c #F9A369", -"p* c #FFA673", -"q* c #F6936D", -"r* c #7C1705", -"s* c #7C3625", -"t* c #C76E51", -"u* c #DE7B53", -"v* c #CA693D", -"w* c #BF633B", -"x* c #E88C57", -"y* c #E98E54", -"z* c #F9A267", -"A* c #FEA86F", -"B* c #F4A167", -"C* c #F6A362", -"D* c #F19C5B", -"E* c #DD8848", -"F* c #E89255", -"G* c #E68F53", -"H* c #F49D63", -"I* c #FEA76D", -"J* c #FCA36A", -"K* c #FAA466", -"L* c #F29B5B", -"M* c #EC8E5C", -"N* c #DB8154", -"O* c #D6874F", -"P* c #E79659", -"Q* c #FFA778", -"R* c #D07B64", -"S* c #6E1913", -"T* c #6C1F18", -"U* c #963729", -"V* c #EC9366", -"W* c #FFB374", -"X* c #E98F56", -"Y* c #B24C23", -"Z* c #ED8661", -"`* c #E78B58", -" = c #FAA561", -".= c #F8A262", -"+= c #F6A164", -"@= c #F7A466", -"#= c #E49459", -"$= c #C16E36", -"%= c #E08C58", -"&= c #E1895C", -"*= c #EF9265", -"== c #FFA372", -"-= c #FEA36A", -";= c #F5A268", -">= c #F6AA6A", -",= c #DC8545", -"'= c #D47440", -")= c #C87153", -"!= c #69241A", -"~= c #AB5E46", -"{= c #E88666", -"]= c #E37B53", -"^= c #D26E43", -"/= c #F4996C", -"(= c #CC6C39", -"_= c #E5834A", -":= c #F39462", -"<= c #FA9F6F", -"[= c #F6A16D", -"}= c #F49F6B", -"|= c #F69E6D", -"1= c #DD7F55", -"2= c #C7653C", -"3= c #E7825E", -"4= c #E4895D", -"5= c #F1A364", -"6= c #FFAC66", -"7= c #FEA067", -"8= c #CD7151", -"9= c #6E2215", -"0= c #7F2427", -"a= c #902F20", -"b= c #E5895A", -"c= c #FFB175", -"d= c #F2915D", -"e= c #B7522B", -"f= c #C05D34", -"g= c #D67649", -"h= c #F69E68", -"i= c #FDA46B", -"j= c #FCA069", -"k= c #FFA46E", -"l= c #F49460", -"m= c #EB8E5D", -"n= c #D06F41", -"o= c #C9683C", -"p= c #D67D55", -"q= c #A55135", -"r= c #682616", -"s= c #8F4C2E", -"t= c #DE8C68", -"u= c #CA6E51", -"v= c #C4654C", -"w= c #FFA579", -"x= c #F09360", -"y= c #CC7345", -"z= c #DA844C", -"A= c #EE9556", -"B= c #F59D5E", -"C= c #FFB174", -"D= c #FFB075", -"E= c #FFB073", -"F= c #FFA472", -"G= c #B85D49", -"H= c #6C1515", -"I= c #8B5446", -"J= c #73251B", -"K= c #95402C", -"L= c #E48F68", -"M= c #FFAA79", -"N= c #F59D70", -"O= c #EB9061", -"P= c #E48A59", -"Q= c #C57046", -"R= c #B26340", -"S= c #B16947", -"T= c #B36943", -"U= c #A65D40", -"V= c #7B3629", -"W= c #6A230D", -"X= c #BA6848", -"Y= c #D57C5E", -"Z= c #D1745E", -"`= c #CE7260", -" - c #923C2D", -".- c #84382F", -"+- c #813F39", -"@- c #7B423B", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" . + @ # $ % & * ", -" = - ; > , ' ) ! ~ { ] ^ / ( _ : < ", -"[ } | 1 2 3 4 5 6 7 8 9 0 a b c d e f g h i j k l ", -"m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W ", -"X Y Z ` ...+.@.#.$. %.&.*.=.-.;.>.,.'.).!.~.{.].^./.9 (._.:.<.[.}.|.1.2.3.4.5.6.7.8.9.0.", -"R a.b.c.d.e.f.R W g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.A.B.C.D.E.F.G.H.I.J.K.L.M.N.O.P.Q.R.S.", -"R T.U.V.W.X.Y.V Z.`. +.+++@+#+$+%+&+*+=+-+;+>+,+'+)+!+~+{+]+^+/+(+_+:+<+[+}+|+1+2+3+4+5+6+7+8+9+", -"0+a+b+c+d+e+f+g+h+i+j+k+l+m+n+o+p+q+r+s+t+u+v+w+x+y+z+A+B+C+D+E+F+G+H+I+J+K+L+M+N+O+P+Q+R+S+T+U+", -"V+W+X+Y+Z+`+ @.@+@@@#@$@%@&@*@=@-@;@>@,@'@)@!@~@{@]@^@/@(@_@:@<@[@}@|@1@2@3@4@5@6@7@8@9@0@a@b@R ", -"c@d@e@f@g@h@i@j@k@l@m@n@o@p@q@r@s@t@u@v@w@x@y@z@A@B@C@D@E@F@G@H@I@J@K@L@M@N@O@P@Q@R@S@T@U@V@W@X@", -"Y@Z@`@ #.#+#@###$#%#&#*#=#-#;#>#,#'#)#!#~#{#]#^#/#(#_#:#<#[#}#|#1#2#3#4#5#6#7#8#9#0#a#b#c#d#e#f#", -"g#h#i#j#k#l#m#n#o#p#~@q#r#s#s#s#t#u#v#w#x#y#z#A#B#C#D#E#F#G#H#I#J#K#L#M#N#O#P#Q#R#S#T#U#V#W#X#Y#", -"Z#`# $.$+$@$#$$$%$&$&$*$=$-$r#r#;$>$,$'$)$)$!$~${$]$^$/$($_$:$<$[$}$|$1$2$~@3$4$5$6$7$8$9$0$a$b$", -"c$d$e$f$g$h$i$j$k$A@;$=$;$;$l$m$m$n$o$p$q$r$s$t$u$v$w$x$y$z$A$B$C$D$E$F$G$H$I$J$K$L$M$N$O$P$Q$R$", -"S$T$U$V$W$X$Y$Z$`$;$=$;$=$=$;$;$;$ % %.% %+%@%#%$%%%&%*%=%-%D ;%>%,%'%)%!%~%t#{%]%^%/%(%_%:%<%[%", -"}%|%1%2%3%4%5%6%7%r#=$m$;$;$=$;$8%&$&$q$+%9%0%a%b%c%d%e%f%g%h%i%j%k%l%m%n%o%p%q%r%s%t%u%v%w%x%y%", -"z%A%B%C%D%E%F%G%H%=$=$;$;$;$=$;$m$I%J%K%v@L%M%N%O%P%Q%R%S%T%U%V%W%X%Y%Z%`% &.&+&@&#&$&%&&&*&=&-&", -";&>&,&'&)&!&~&{&]&;$;$;$;$;$;$;$;$^&/&K%(&_&:&<&[&}&|&1&2&3&4&5&6&7&8&9&0&a&b&c&d&e&f&g&h&i&j&k&", -"l&m&n&o&p&q&=.r&s&t&t&r$;$;$m$;$r$u&v&w&x&t$y&z&A&B&x@C&D&E&F&G&H&I&J&K&L&M&N&O&P&Q&R&S&T&U&V& ", -"W&X&Y&Z&`& *.*+*@*#*$*%*&***=*A@-*;*>*,*'*)*!*~*{*]*^*/*(*_*:*<*[*}*|*1* 2* ", -" 3*4*5*6*7*8*9*0*a*b*c*d*e*f*g*h*z@i*j*k*l*m*n*8%o*p*q*r* ", -" s*t*u*v*w*x*y*z*A*B*C*D*E*F*G*H*I*J*K*L*M*N*O*P*Q*R*S* ", -" T*U*V*W*X*Y*Z*`* =.=+=@=#=$=%=&=*===-=;=>=,='=)=!= ", -" ~={=]=^=/=(=_=:=<=n*[=}=|=1=2=3=4=5=6=7=8=9= ", -" 0=a=b=c=d=e=f=g=o%h=i=j=k=l=m=n=o=p=q=r= ", -" s=t=u=v=w=x=y=z=A=B=C=D=E=F=G=H= ", -" I=J=K=L=M=N=O=P=Q=R=S=T=U=V= ", -" W=X=Y=Z=`= -.-+-@- ", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" "}; +"48 48 157 2 ", +" c #010101", +". c #0B0B0B", +"X c #0F1010", +"o c #131414", +"O c #1B1C1C", +"+ c #242525", +"@ c #2B2B2C", +"# c #2F3030", +"$ c #333334", +"% c #3B3C3D", +"& c #00005B", +"* c #000163", +"= c #0D0D62", +"- c #00026C", +"; c #131365", +": c #1B1B69", +"> c #010373", +", c #00047C", +"< c #292A71", +"1 c #232376", +"2 c #3C3C7D", +"3 c #444445", +"4 c #474849", +"5 c #4A4B4C", +"6 c #535455", +"7 c #575859", +"8 c #5B5C5D", +"9 c #5E5F60", +"0 c #5F6061", +"q c #626364", +"w c #666768", +"e c #6B6C6D", +"r c #6E6F70", +"t c #6F7071", +"y c #727475", +"u c #767779", +"i c #777879", +"p c #7B7C7D", +"a c #CC9272", +"s c #CF9778", +"d c #CF997B", +"f c #D09A7D", +"g c #000483", +"h c #000589", +"j c #000693", +"k c #00079A", +"l c #00089E", +"z c #030BA4", +"x c #0009AA", +"c c #000AB4", +"v c #000BBA", +"b c #3539A3", +"n c #575787", +"m c #52528B", +"M c #686991", +"N c #6B6C9C", +"B c #000BC3", +"V c #000DCA", +"C c #000ED3", +"Z c #000EDB", +"A c #000FE0", +"S c #0010E5", +"D c #0011ED", +"F c #0E1EEC", +"G c #0011F2", +"H c #0013FE", +"J c #4B54DA", +"K c #7F8082", +"L c #828285", +"P c #858688", +"I c #87898A", +"U c #8A8C8D", +"Y c #8D8F90", +"T c #8F9192", +"R c #939495", +"E c #969799", +"W c #97999A", +"Q c #9B9C9E", +"! c #A59F9D", +"~ c #BAA498", +"^ c #8687A2", +"/ c #9E9FA2", +"( c #9D9EAA", +") c #8788BB", +"_ c #9A9BB4", +"` c #9EA0A1", +"' c #A2A3A4", +"] c #A5A6A9", +"[ c #A6A8AA", +"{ c #A9ABAD", +"} c #BBABA3", +"| c #BAB2AF", +" . c #ACAEB1", +".. c #B1AFB5", +"X. c #AFB1B3", +"o. c #B2B4B6", +"O. c #BEB6B2", +"+. c #B4B6B8", +"@. c #B7B8BA", +"#. c #BABBBC", +"$. c #D29E81", +"%. c #D3A185", +"&. c #D5A58A", +"*. c #D7A98E", +"=. c #C9A896", +"-. c #CAAC9B", +";. c #D6AB92", +":. c #D9AD94", +">. c #DAB097", +",. c #DCB39C", +"<. c #D7B7A3", +"1. c #DDB7A0", +"2. c #DEBAA3", +"3. c #DCBFAD", +"4. c #CEBEB4", +"5. c #E0BDA7", +"6. c #E1BEA9", +"7. c #D9C6BA", +"8. c #DDC2B1", +"9. c #E2C1AD", +"0. c #E4C6B2", +"q. c #E5C9B6", +"w. c #E7CCBA", +"e. c #E8CFBD", +"r. c #E9D0BF", +"t. c #B4B4C6", +"y. c #A3A6DF", +"u. c #B6BBFC", +"i. c #BFC1C3", +"p. c #C2C2C4", +"a. c #C8C9CB", +"s. c #D7CAC1", +"d. c #DBCEC5", +"f. c #CBCCD9", +"g. c #D2D2D3", +"h. c #DFD6D0", +"j. c #D7D8D9", +"k. c #DBDCDD", +"l. c #EAD4C3", +"z. c #E0D5CE", +"x. c #ECD7C8", +"c. c #EDDBCC", +"v. c #EFDED0", +"b. c #E4DFDB", +"n. c #E9E1DA", +"m. c #F0E1D4", +"M. c #F2E3D9", +"N. c #EBE8E5", +"B. c #E2E2E7", +"V. c #F0EFED", +"C. c #F2EBE5", +"Z. c #F2F0EF", +"A. c #F9F5F1", +"S. c #FBFAF7", +"D. c #FDFCFC", +"F. c #F3F4FB", +"G. c None", +/* pixels */ +"G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.", +"G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.", +"G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.", +"G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.", +"G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.", +"G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.", +"G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.", +"H G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.", +"H H H G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.", +"D G H H H G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.", +"V Z S G H H H G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.p.p.", +"c v V C A G H H H G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.v.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.i.i.#.+.", +"k z x v B C A D H H G.G.G.G.G.G.G.G.G.G.G.G.G.x.c.v.v.c.v.v.G.G.G.G.G.G.G.G.G.G.G.i.#.+.o.X.{ ' ", +", h j l x c B V Z F u.D.G.G.G.G.G.G.G.G.e.r.x.x.c.c.c.c.v.v.v.v.v.G.G.G.G.G.G.a.+.X.X.' ! ! W W ", +"- > h h j l z c B J F.A.M.G.G.G.G.v.v.r.0.q.w.q.q.x.x.x.x.c.c.v.v.v.v.v.G.G.D.g.{ ` ` W W T U I ", +"* * - > , h j l z y.S.M.c.v.v.v.v.v.c.0.9.9.9.9.3.0.e.e.r.x.x.c.c.v.c.v.m.m.V.j.W T Y I P P M p ", +"& & * * - - > h b B.C.x.x.x.x.c.c.c.x.w.9.2.5.5.2.9.q.q.q.w.r.r.x.x.x.x.c.v.N.k.R L K p i y t r ", +"& & & & & * - > ) Z.c.r.r.r.x.x.c.w.2.1.>.,.,.9.w.c.c.x.q.9.q.q.e.e.e.x.x.x.n.k.R u t r w w q 9 ", +"& & & & & & & 1 f.n.r.q.r.r.r.x.r.,.%.*.&.*.,.x.m.c.m.v.c.q.9.9.0.0.q.w.w.x.z.g./ w w 0 8 8 7 6 ", +"& & & & & & & N B.w.9.q.9.q.q.r.e.,.*.%.*.,.e.c.c.c.c.v.v.c.x.9.6.6.9.0.0.w.s.g.{ 9 7 6 6 5 4 4 ", +"& & & & & & ; t.z.9.9.9.9.9.q.q.q.q.0.0.q.r.x.r.x.x.x.x.c.v.v.x.0.5.2.6.6.6.7.a.o.8 5 4 3 3 % % ", +"& & & & & & m g.8.2.3.2.5.9.9.9.9.q.q.q.w.w.e.r.r.r.x.x.x.x.x.v.c.w.2.,.2.2.3.p.#.0 % % % $ $ $ ", +"& & & & & = _ s.,.,.,.5.5.5.5.5.9.9.9.9.0.q.q.w.w.e.r.r.r.x.x.x.x.c.l.,.,.,.1.#.@.r $ $ @ @ + + ", +"& & & & & 2 p.2.>.,.,.,.1.,.5.5.5.6.9.9.9.9.0.0.q.q.q.w.w.e.r.r.e.x.x.x.1.;.:.| o.K @ + + + O O ", +"& & & & & ^ 4.;.*.>.>.>.,.>.,.1.1.1.5.5.5.9.9.9.9.9.9.q.w.w.w.r.e.l.l.x.w.,.&.} { R @ O O o o o ", +"& & & & < o.=.*.*.*.*.*.:.>.>.>.,.,.,.1.1.1.1.9.9.9.9.9.9.9.9.q.w.w.w.w.l.w.:.~ ] Q $ o o o X . ", +"& & & & M 4.$.%.%.%.%.*.*.*.*.:.:.:.>.,.,.,.1.1.,.9.9.9.9.9.9.9.0.6.0.q.w.e.0.=.` / 4 . . . . ", +"& & & : ( o.G.f f %.%.%.%.&.*.*.*.:.:.:.:.,.,.,.,.,.,.2.,.9.9.9.6.2.6.0.0.0.e.3.! Q 9 . ", +"& & & n .G.G.G.G.f f %.f *.f *.*.:.*.*.*.:.:.:.>.>.,.,.,.,.9.2.5.5.1.5.9.0.0.0.~ R i . ", +"& & ; ^ G.G.G.G.G.G.*.f f f f f f f f *.&.*.*.*.:.:.:.>.,.,.,.,.1.1.5.,.1.6.6.9.-.R P o ", +"& & = G.G.G.G.G.G.G.1.*.f s s s f f :.*.&.&.&.*.&.*.:.:.:.>.,.>.1.>.1.1.,.,.5.6.G.G.G. ", +"& & G.G.G.G.G.G.G.G.5.:.f s s s *.5.9.5.*.f f f &.&.&.&.*.&.:.:.=.,.,.,.,.:.,.3.G.G.G.G. ", +"& & G.G.G.G.G.G.G.G.9.,.f a G.f *.e.0.6.:.$.>.5.:.%.%.%.*.*.*.*.%.=.:.:.:.:.G.G.G.G.G.G. ", +"& G.G.G.G.G.G.G.G.G.G.,.f a G.f *.6.5.,.&.:.e.e.9.*.%.f $.%.$.%.*.$.*.*.:.:.G.G.G.G.G.G.G. ", +"& G.G.G.G.G.G.G.G.G.G.G.G.G.G.a f %.%.%.%.:.r.e.5.6.q.,.$.s $.$.$.%.$.%.*.G.G.G.G.G.G.G.G.G. ", +"G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.a a a a s a f ,.:.*.9.e.9.;.a s d f $.$.G.G.G.G.G.G.G.G.G.G.G. ", +"G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.a a a a a a a a $.:.:.:.*.a a a d f G.G.G.G.G.G.G.G.G.G.G.G.G. ", +"G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.a a a a a a a f %.f a a a G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.", +"G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.a a a a a a a a a a a G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.", +"G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.a a a G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.", +"G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.", +"G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.", +"G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.", +"G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.", +"G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.", +"G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.", +"G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.", +"G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G." +}; diff --git a/data/mac/flarq.icns b/data/mac/flarq.icns index 996d622f..968dba89 100644 Binary files a/data/mac/flarq.icns and b/data/mac/flarq.icns differ diff --git a/data/win32/flarq.ico b/data/win32/flarq.ico index a5f2c034..0bc5a836 100644 Binary files a/data/win32/flarq.ico and b/data/win32/flarq.ico differ diff --git a/doc/Makefile.am b/doc/Makefile.am index 0ebc37d8..0593a362 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -36,7 +36,7 @@ endif %.1: $$@.txt $(ASCIIDOC_CONF) if HAVE_ASCIIDOC - $(call silent,ADOC ,$@)$(A2X) $(A2X_ARGS) $< + $(call silent,ADOC ,$@)TZ=0 $(A2X) $(A2X_ARGS) $< else $(call silent,ADOC ,$@)echo '.TH "NOT-BUILT" "1" "" "" ""' > $@ endif @@ -62,7 +62,7 @@ ASCIIDOC_ARGS = --unsafe -a toc -a data-uri -a badges -a icons -a iconsdir=$(ASC echo " *** make ASCIIDOC_ICONS_DIR=/path/to/icons" >&2; \ false; \ fi - $(call silent,ADOC ,$@)$(ASCIIDOC) $(ASCIIDOC_ARGS) --out-file $@ $< + $(call silent,ADOC ,$@)TZ=0 $(ASCIIDOC) $(ASCIIDOC_ARGS) --out-file $@ $< all-local: $(ASCIIDOC_MAN_DIST) $(ASCIIDOC_HTML) diff --git a/doc/dl-fldigi.1.txt b/doc/dl-fldigi.1.txt index feeac6f6..44c08e73 100644 --- a/doc/dl-fldigi.1.txt +++ b/doc/dl-fldigi.1.txt @@ -443,7 +443,7 @@ getaddrinfo(3), getopt(3), regex(7), X(7) == RESOURCES == Main web site: http://www.w1hkj.com/Fldigi.html -BerliOS project page: http://developer.berlios.de/projects/fldigi/ +Sourceforge project page: http://sourceforge.net/projects/fldigi/ Wiki and bug tracker: https://fedorahosted.org/fldigi/ diff --git a/doc/flarq.1.txt b/doc/flarq.1.txt index f098faa0..496974b5 100644 --- a/doc/flarq.1.txt +++ b/doc/flarq.1.txt @@ -126,7 +126,7 @@ Flarq web site: http://www.w1hkj.com/flarq_main.html Fldigi web site: http://www.w1hkj.com/Fldigi.html -BerliOS project page: http://developer.berlios.de/projects/fldigi/ +Sourceforge project page: http://sourceforge.net/projects/fldigi/ ARQ specification by Paul Schmidt, K9PS: http://www.w1hkj.com/FlarqHelpFiles/ARQ2.pdf diff --git a/fldigi_doxygen/images/ColorsFonts-buttons.png b/fldigi_doxygen/images/ColorsFonts-buttons.png index 7be852c6..fbaa21ce 100644 Binary files a/fldigi_doxygen/images/ColorsFonts-buttons.png and b/fldigi_doxygen/images/ColorsFonts-buttons.png differ diff --git a/fldigi_doxygen/images/ColorsFonts-rxtx.png b/fldigi_doxygen/images/ColorsFonts-rxtx.png index 74afe8ab..60896557 100644 Binary files a/fldigi_doxygen/images/ColorsFonts-rxtx.png and b/fldigi_doxygen/images/ColorsFonts-rxtx.png differ diff --git a/fldigi_doxygen/images/FreqAnal.png b/fldigi_doxygen/images/FreqAnal.png index dccbc058..378d2376 100644 Binary files a/fldigi_doxygen/images/FreqAnal.png and b/fldigi_doxygen/images/FreqAnal.png differ diff --git a/fldigi_doxygen/images/KML-Config.png b/fldigi_doxygen/images/KML-Config.png index 11a50ade..cbcfa537 100644 Binary files a/fldigi_doxygen/images/KML-Config.png and b/fldigi_doxygen/images/KML-Config.png differ diff --git a/fldigi_doxygen/images/MFSK-rx-images.png b/fldigi_doxygen/images/MFSK-rx-images.png new file mode 100644 index 00000000..faeca9a1 Binary files /dev/null and b/fldigi_doxygen/images/MFSK-rx-images.png differ diff --git a/fldigi_doxygen/images/Navtex-Config-Tab-With-Kml.png b/fldigi_doxygen/images/Navtex-Config-Tab-With-Kml.png index 16d8b3f5..104e9d19 100644 Binary files a/fldigi_doxygen/images/Navtex-Config-Tab-With-Kml.png and b/fldigi_doxygen/images/Navtex-Config-Tab-With-Kml.png differ diff --git a/fldigi_doxygen/images/RTTY-Config-Tab-With-Synop.png b/fldigi_doxygen/images/RTTY-Config-Tab-With-Synop.png index 563c2dc8..2623156d 100644 Binary files a/fldigi_doxygen/images/RTTY-Config-Tab-With-Synop.png and b/fldigi_doxygen/images/RTTY-Config-Tab-With-Synop.png differ diff --git a/fldigi_doxygen/images/TxCursor.png b/fldigi_doxygen/images/TxCursor.png new file mode 100644 index 00000000..2cccdd2c Binary files /dev/null and b/fldigi_doxygen/images/TxCursor.png differ diff --git a/fldigi_doxygen/images/Wefax-Configuration.png b/fldigi_doxygen/images/Wefax-Configuration.png index 81caae3b..67f2ba9c 100644 Binary files a/fldigi_doxygen/images/Wefax-Configuration.png and b/fldigi_doxygen/images/Wefax-Configuration.png differ diff --git a/fldigi_doxygen/images/Xmt-Pix.png b/fldigi_doxygen/images/Xmt-Pix.png index 74d27b00..4e0ec124 100644 Binary files a/fldigi_doxygen/images/Xmt-Pix.png and b/fldigi_doxygen/images/Xmt-Pix.png differ diff --git a/fldigi_doxygen/images/Xmt-Pix1.png b/fldigi_doxygen/images/Xmt-Pix1.png index 6c5e16a6..b1b47495 100644 Binary files a/fldigi_doxygen/images/Xmt-Pix1.png and b/fldigi_doxygen/images/Xmt-Pix1.png differ diff --git a/fldigi_doxygen/images/Xmt-Pix2.png b/fldigi_doxygen/images/Xmt-Pix2.png new file mode 100644 index 00000000..2dcad70b Binary files /dev/null and b/fldigi_doxygen/images/Xmt-Pix2.png differ diff --git a/fldigi_doxygen/images/Xmt-Pix3.png b/fldigi_doxygen/images/Xmt-Pix3.png index 0f130bc1..efee8771 100644 Binary files a/fldigi_doxygen/images/Xmt-Pix3.png and b/fldigi_doxygen/images/Xmt-Pix3.png differ diff --git a/fldigi_doxygen/images/Xmt-Pix4.png b/fldigi_doxygen/images/Xmt-Pix4.png deleted file mode 100644 index fb5b2c31..00000000 Binary files a/fldigi_doxygen/images/Xmt-Pix4.png and /dev/null differ diff --git a/fldigi_doxygen/images/blossoms-1.png b/fldigi_doxygen/images/blossoms-1.png new file mode 100644 index 00000000..2995fa82 Binary files /dev/null and b/fldigi_doxygen/images/blossoms-1.png differ diff --git a/fldigi_doxygen/images/blossoms-2.png b/fldigi_doxygen/images/blossoms-2.png new file mode 100644 index 00000000..65d1e898 Binary files /dev/null and b/fldigi_doxygen/images/blossoms-2.png differ diff --git a/fldigi_doxygen/images/blossoms-3.png b/fldigi_doxygen/images/blossoms-3.png new file mode 100644 index 00000000..54de301d Binary files /dev/null and b/fldigi_doxygen/images/blossoms-3.png differ diff --git a/fldigi_doxygen/images/blossoms.png b/fldigi_doxygen/images/blossoms.png new file mode 100644 index 00000000..f4d71a2e Binary files /dev/null and b/fldigi_doxygen/images/blossoms.png differ diff --git a/fldigi_doxygen/images/config-audio-right.png b/fldigi_doxygen/images/config-audio-right.png index b7360f53..7a7829de 100644 Binary files a/fldigi_doxygen/images/config-audio-right.png and b/fldigi_doxygen/images/config-audio-right.png differ diff --git a/fldigi_doxygen/images/config-contestia.png b/fldigi_doxygen/images/config-contestia.png index bd802d64..25edc521 100644 Binary files a/fldigi_doxygen/images/config-contestia.png and b/fldigi_doxygen/images/config-contestia.png differ diff --git a/fldigi_doxygen/images/config-fsq.png b/fldigi_doxygen/images/config-fsq.png index f4f95325..0ed18b42 100644 Binary files a/fldigi_doxygen/images/config-fsq.png and b/fldigi_doxygen/images/config-fsq.png differ diff --git a/fldigi_doxygen/images/config-ifkp.png b/fldigi_doxygen/images/config-ifkp.png new file mode 100644 index 00000000..7e7a3c80 Binary files /dev/null and b/fldigi_doxygen/images/config-ifkp.png differ diff --git a/fldigi_doxygen/images/config-io-kiss.png b/fldigi_doxygen/images/config-io-kiss.png index b6400bbc..b70691bf 100644 Binary files a/fldigi_doxygen/images/config-io-kiss.png and b/fldigi_doxygen/images/config-io-kiss.png differ diff --git a/fldigi_doxygen/images/config-io-locked.png b/fldigi_doxygen/images/config-io-locked.png index c08d01bb..bb5fa126 100644 Binary files a/fldigi_doxygen/images/config-io-locked.png and b/fldigi_doxygen/images/config-io-locked.png differ diff --git a/fldigi_doxygen/images/config-io.png b/fldigi_doxygen/images/config-io.png index 6cbcfb68..c2a269b5 100644 Binary files a/fldigi_doxygen/images/config-io.png and b/fldigi_doxygen/images/config-io.png differ diff --git a/fldigi_doxygen/images/config-misc-kml.png b/fldigi_doxygen/images/config-misc-kml.png index 996340e6..00d27066 100644 Binary files a/fldigi_doxygen/images/config-misc-kml.png and b/fldigi_doxygen/images/config-misc-kml.png differ diff --git a/fldigi_doxygen/images/config-misc-nbems.png b/fldigi_doxygen/images/config-misc-nbems.png index 84e0563f..49768469 100644 Binary files a/fldigi_doxygen/images/config-misc-nbems.png and b/fldigi_doxygen/images/config-misc-nbems.png differ diff --git a/fldigi_doxygen/images/config-misc-sweet.png b/fldigi_doxygen/images/config-misc-sweet.png index 61f33445..fb4baacb 100644 Binary files a/fldigi_doxygen/images/config-misc-sweet.png and b/fldigi_doxygen/images/config-misc-sweet.png differ diff --git a/fldigi_doxygen/images/config-modem-navtex.png b/fldigi_doxygen/images/config-modem-navtex.png index f3bd4960..acd191e6 100644 Binary files a/fldigi_doxygen/images/config-modem-navtex.png and b/fldigi_doxygen/images/config-modem-navtex.png differ diff --git a/fldigi_doxygen/images/config-modem-scan.png b/fldigi_doxygen/images/config-modem-scan.png index 7a03fb91..3c1db858 100644 Binary files a/fldigi_doxygen/images/config-modem-scan.png and b/fldigi_doxygen/images/config-modem-scan.png differ diff --git a/fldigi_doxygen/images/config-mt63.png b/fldigi_doxygen/images/config-mt63.png index c8cf217b..bb8e0cee 100644 Binary files a/fldigi_doxygen/images/config-mt63.png and b/fldigi_doxygen/images/config-mt63.png differ diff --git a/fldigi_doxygen/images/config-olivia.png b/fldigi_doxygen/images/config-olivia.png index 4c0d5383..7914b8c6 100644 Binary files a/fldigi_doxygen/images/config-olivia.png and b/fldigi_doxygen/images/config-olivia.png differ diff --git a/fldigi_doxygen/images/config-psk-general.png b/fldigi_doxygen/images/config-psk-general.png index 00502517..6d87f8e3 100644 Binary files a/fldigi_doxygen/images/config-psk-general.png and b/fldigi_doxygen/images/config-psk-general.png differ diff --git a/fldigi_doxygen/images/config-qrz.png b/fldigi_doxygen/images/config-qrz.png index 5d83b3e7..816f1764 100644 Binary files a/fldigi_doxygen/images/config-qrz.png and b/fldigi_doxygen/images/config-qrz.png differ diff --git a/fldigi_doxygen/images/config-rig-hardware.png b/fldigi_doxygen/images/config-rig-hardware.png index a5e7acfb..1842e042 100644 Binary files a/fldigi_doxygen/images/config-rig-hardware.png and b/fldigi_doxygen/images/config-rig-hardware.png differ diff --git a/fldigi_doxygen/images/config-rtty-rx.png b/fldigi_doxygen/images/config-rtty-rx.png index 60639847..61388887 100644 Binary files a/fldigi_doxygen/images/config-rtty-rx.png and b/fldigi_doxygen/images/config-rtty-rx.png differ diff --git a/fldigi_doxygen/images/config-rtty-synop.png b/fldigi_doxygen/images/config-rtty-synop.png index 6777e43d..2f204e25 100644 Binary files a/fldigi_doxygen/images/config-rtty-synop.png and b/fldigi_doxygen/images/config-rtty-synop.png differ diff --git a/fldigi_doxygen/images/config-rtty-tx.png b/fldigi_doxygen/images/config-rtty-tx.png index 9ce1db6d..7c4512bf 100644 Binary files a/fldigi_doxygen/images/config-rtty-tx.png and b/fldigi_doxygen/images/config-rtty-tx.png differ diff --git a/fldigi_doxygen/images/config-thor.png b/fldigi_doxygen/images/config-thor.png index 0f3df7f0..e2482d8b 100644 Binary files a/fldigi_doxygen/images/config-thor.png and b/fldigi_doxygen/images/config-thor.png differ diff --git a/fldigi_doxygen/images/config-ui-log-maclogger.png b/fldigi_doxygen/images/config-ui-log-maclogger.png new file mode 100644 index 00000000..46712c48 Binary files /dev/null and b/fldigi_doxygen/images/config-ui-log-maclogger.png differ diff --git a/fldigi_doxygen/images/config-ui-macros.png b/fldigi_doxygen/images/config-ui-macros.png index a2122b40..a744d95e 100644 Binary files a/fldigi_doxygen/images/config-ui-macros.png and b/fldigi_doxygen/images/config-ui-macros.png differ diff --git a/fldigi_doxygen/images/config-ui-qso-logging.png b/fldigi_doxygen/images/config-ui-qso-logging.png index 487a3248..a9312876 100644 Binary files a/fldigi_doxygen/images/config-ui-qso-logging.png and b/fldigi_doxygen/images/config-ui-qso-logging.png differ diff --git a/fldigi_doxygen/images/config-ui-touch.png b/fldigi_doxygen/images/config-ui-touch.png index 4b7e9b1d..95a7d889 100644 Binary files a/fldigi_doxygen/images/config-ui-touch.png and b/fldigi_doxygen/images/config-ui-touch.png differ diff --git a/fldigi_doxygen/images/docked-rig-control.png b/fldigi_doxygen/images/docked-rig-control.png deleted file mode 100644 index 5096d286..00000000 Binary files a/fldigi_doxygen/images/docked-rig-control.png and /dev/null differ diff --git a/fldigi_doxygen/images/edit-freq-entry.png b/fldigi_doxygen/images/edit-freq-entry.png new file mode 100644 index 00000000..d1378d62 Binary files /dev/null and b/fldigi_doxygen/images/edit-freq-entry.png differ diff --git a/fldigi_doxygen/images/edit_freq_entry.png b/fldigi_doxygen/images/edit_freq_entry.png new file mode 100644 index 00000000..65c11873 Binary files /dev/null and b/fldigi_doxygen/images/edit_freq_entry.png differ diff --git a/fldigi_doxygen/images/event-log-menu.png b/fldigi_doxygen/images/event-log-menu.png index 618531c9..dc8bd559 100644 Binary files a/fldigi_doxygen/images/event-log-menu.png and b/fldigi_doxygen/images/event-log-menu.png differ diff --git a/fldigi_doxygen/images/fsq-config-tab.png b/fldigi_doxygen/images/fsq-config-tab.png index 154153dd..631fbb3f 100644 Binary files a/fldigi_doxygen/images/fsq-config-tab.png and b/fldigi_doxygen/images/fsq-config-tab.png differ diff --git a/fldigi_doxygen/images/fsq-directed-mode.png b/fldigi_doxygen/images/fsq-directed-mode.png index 811b77ec..fa22b779 100644 Binary files a/fldigi_doxygen/images/fsq-directed-mode.png and b/fldigi_doxygen/images/fsq-directed-mode.png differ diff --git a/fldigi_doxygen/images/fsq-directed-popup.png b/fldigi_doxygen/images/fsq-directed-popup.png index 6ffa1467..dba55d6d 100644 Binary files a/fldigi_doxygen/images/fsq-directed-popup.png and b/fldigi_doxygen/images/fsq-directed-popup.png differ diff --git a/fldigi_doxygen/images/fsq-main-dialog.png b/fldigi_doxygen/images/fsq-main-dialog.png index a12237b5..ddddef7f 100644 Binary files a/fldigi_doxygen/images/fsq-main-dialog.png and b/fldigi_doxygen/images/fsq-main-dialog.png differ diff --git a/fldigi_doxygen/images/fsq-mon-dialog.png b/fldigi_doxygen/images/fsq-mon-dialog.png index 5d224a8e..1c5fd178 100644 Binary files a/fldigi_doxygen/images/fsq-mon-dialog.png and b/fldigi_doxygen/images/fsq-mon-dialog.png differ diff --git a/fldigi_doxygen/images/fsq-s2n.png b/fldigi_doxygen/images/fsq-s2n.png index a2c8e452..da62305b 100644 Binary files a/fldigi_doxygen/images/fsq-s2n.png and b/fldigi_doxygen/images/fsq-s2n.png differ diff --git a/fldigi_doxygen/images/fsq-undirected-mode.png b/fldigi_doxygen/images/fsq-undirected-mode.png index 050176ae..7ec11166 100644 Binary files a/fldigi_doxygen/images/fsq-undirected-mode.png and b/fldigi_doxygen/images/fsq-undirected-mode.png differ diff --git a/fldigi_doxygen/images/ifkp-WF-image-mode.png b/fldigi_doxygen/images/ifkp-WF-image-mode.png new file mode 100644 index 00000000..d9500879 Binary files /dev/null and b/fldigi_doxygen/images/ifkp-WF-image-mode.png differ diff --git a/fldigi_doxygen/images/ifkp-avatar-1.png b/fldigi_doxygen/images/ifkp-avatar-1.png new file mode 100644 index 00000000..448adeb2 Binary files /dev/null and b/fldigi_doxygen/images/ifkp-avatar-1.png differ diff --git a/fldigi_doxygen/images/ifkp-avatar-2.png b/fldigi_doxygen/images/ifkp-avatar-2.png new file mode 100644 index 00000000..4346dfb5 Binary files /dev/null and b/fldigi_doxygen/images/ifkp-avatar-2.png differ diff --git a/fldigi_doxygen/images/ifkp-image-completed.png b/fldigi_doxygen/images/ifkp-image-completed.png new file mode 100644 index 00000000..faadf434 Binary files /dev/null and b/fldigi_doxygen/images/ifkp-image-completed.png differ diff --git a/fldigi_doxygen/images/ifkp-image-partial.png b/fldigi_doxygen/images/ifkp-image-partial.png new file mode 100644 index 00000000..c6c759fb Binary files /dev/null and b/fldigi_doxygen/images/ifkp-image-partial.png differ diff --git a/fldigi_doxygen/images/ifkp-image-xmt.png b/fldigi_doxygen/images/ifkp-image-xmt.png new file mode 100644 index 00000000..ccb1b16b Binary files /dev/null and b/fldigi_doxygen/images/ifkp-image-xmt.png differ diff --git a/fldigi_doxygen/images/ifkp-rx-tx.png b/fldigi_doxygen/images/ifkp-rx-tx.png new file mode 100644 index 00000000..65f786ed Binary files /dev/null and b/fldigi_doxygen/images/ifkp-rx-tx.png differ diff --git a/fldigi_doxygen/images/ifkp-send-image.png b/fldigi_doxygen/images/ifkp-send-image.png new file mode 100644 index 00000000..b784ccec Binary files /dev/null and b/fldigi_doxygen/images/ifkp-send-image.png differ diff --git a/fldigi_doxygen/images/init-rig-setup.png b/fldigi_doxygen/images/init-rig-setup.png index e656db50..bccba3d2 100644 Binary files a/fldigi_doxygen/images/init-rig-setup.png and b/fldigi_doxygen/images/init-rig-setup.png differ diff --git a/fldigi_doxygen/images/macro-matrix.png b/fldigi_doxygen/images/macro-matrix.png new file mode 100644 index 00000000..05d92de5 Binary files /dev/null and b/fldigi_doxygen/images/macro-matrix.png differ diff --git a/fldigi_doxygen/images/macro-scheme-4.png b/fldigi_doxygen/images/macro-scheme-4.png new file mode 100644 index 00000000..ab945e7d Binary files /dev/null and b/fldigi_doxygen/images/macro-scheme-4.png differ diff --git a/fldigi_doxygen/images/menu-8psk.png b/fldigi_doxygen/images/menu-8psk.png index e5adcea5..89a5be53 100644 Binary files a/fldigi_doxygen/images/menu-8psk.png and b/fldigi_doxygen/images/menu-8psk.png differ diff --git a/fldigi_doxygen/images/mfskpix-bee.png b/fldigi_doxygen/images/mfskpix-bee.png deleted file mode 100644 index 54ef0338..00000000 Binary files a/fldigi_doxygen/images/mfskpix-bee.png and /dev/null differ diff --git a/fldigi_doxygen/images/rigcat-1.png b/fldigi_doxygen/images/rigcat-1.png new file mode 100644 index 00000000..caf1606c Binary files /dev/null and b/fldigi_doxygen/images/rigcat-1.png differ diff --git a/fldigi_doxygen/images/rigcat-2.png b/fldigi_doxygen/images/rigcat-2.png new file mode 100644 index 00000000..87cf2d90 Binary files /dev/null and b/fldigi_doxygen/images/rigcat-2.png differ diff --git a/fldigi_doxygen/images/rigcat-3.png b/fldigi_doxygen/images/rigcat-3.png new file mode 100644 index 00000000..04a3826d Binary files /dev/null and b/fldigi_doxygen/images/rigcat-3.png differ diff --git a/fldigi_doxygen/images/rigcat-4.png b/fldigi_doxygen/images/rigcat-4.png new file mode 100644 index 00000000..3c3b8e57 Binary files /dev/null and b/fldigi_doxygen/images/rigcat-4.png differ diff --git a/fldigi_doxygen/images/thor-avatar-1.png b/fldigi_doxygen/images/thor-avatar-1.png new file mode 100644 index 00000000..448adeb2 Binary files /dev/null and b/fldigi_doxygen/images/thor-avatar-1.png differ diff --git a/fldigi_doxygen/images/thor-avatar-2.png b/fldigi_doxygen/images/thor-avatar-2.png new file mode 100644 index 00000000..4346dfb5 Binary files /dev/null and b/fldigi_doxygen/images/thor-avatar-2.png differ diff --git a/fldigi_doxygen/images/thor-image-completed.png b/fldigi_doxygen/images/thor-image-completed.png new file mode 100644 index 00000000..8cb62a82 Binary files /dev/null and b/fldigi_doxygen/images/thor-image-completed.png differ diff --git a/fldigi_doxygen/images/thor-image-partial.png b/fldigi_doxygen/images/thor-image-partial.png new file mode 100644 index 00000000..a2169676 Binary files /dev/null and b/fldigi_doxygen/images/thor-image-partial.png differ diff --git a/fldigi_doxygen/images/thor-image-xmt.png b/fldigi_doxygen/images/thor-image-xmt.png new file mode 100644 index 00000000..ccb1b16b Binary files /dev/null and b/fldigi_doxygen/images/thor-image-xmt.png differ diff --git a/fldigi_doxygen/images/thor-pic-transmission.png b/fldigi_doxygen/images/thor-pic-transmission.png new file mode 100644 index 00000000..596644b8 Binary files /dev/null and b/fldigi_doxygen/images/thor-pic-transmission.png differ diff --git a/fldigi_doxygen/images/thor-send-image.png b/fldigi_doxygen/images/thor-send-image.png new file mode 100644 index 00000000..b784ccec Binary files /dev/null and b/fldigi_doxygen/images/thor-send-image.png differ diff --git a/fldigi_doxygen/images/view-hide-48.png b/fldigi_doxygen/images/view-hide-48.png new file mode 100644 index 00000000..6e866f2e Binary files /dev/null and b/fldigi_doxygen/images/view-hide-48.png differ diff --git a/fldigi_doxygen/images/view_frequencies.png b/fldigi_doxygen/images/view_frequencies.png new file mode 100644 index 00000000..f2a07fb6 Binary files /dev/null and b/fldigi_doxygen/images/view_frequencies.png differ diff --git a/fldigi_doxygen/images/win10-fldigi-fft.png b/fldigi_doxygen/images/win10-fldigi-fft.png new file mode 100644 index 00000000..a0bea041 Binary files /dev/null and b/fldigi_doxygen/images/win10-fldigi-fft.png differ diff --git a/fldigi_doxygen/images/win10-fldigi-signal.png b/fldigi_doxygen/images/win10-fldigi-signal.png new file mode 100644 index 00000000..b66ab116 Binary files /dev/null and b/fldigi_doxygen/images/win10-fldigi-signal.png differ diff --git a/fldigi_doxygen/images/win10-fldigi-wf-adjust.png b/fldigi_doxygen/images/win10-fldigi-wf-adjust.png new file mode 100644 index 00000000..c9c4ecda Binary files /dev/null and b/fldigi_doxygen/images/win10-fldigi-wf-adjust.png differ diff --git a/fldigi_doxygen/images/win10-fldigi-wf.png b/fldigi_doxygen/images/win10-fldigi-wf.png new file mode 100644 index 00000000..e5f54c35 Binary files /dev/null and b/fldigi_doxygen/images/win10-fldigi-wf.png differ diff --git a/fldigi_doxygen/images/win10-mic-advanced.png b/fldigi_doxygen/images/win10-mic-advanced.png new file mode 100644 index 00000000..b2beb1f8 Binary files /dev/null and b/fldigi_doxygen/images/win10-mic-advanced.png differ diff --git a/fldigi_doxygen/images/win10-mic-levels.png b/fldigi_doxygen/images/win10-mic-levels.png new file mode 100644 index 00000000..7dec7e44 Binary files /dev/null and b/fldigi_doxygen/images/win10-mic-levels.png differ diff --git a/fldigi_doxygen/images/win10-mic-properties.png b/fldigi_doxygen/images/win10-mic-properties.png new file mode 100644 index 00000000..48e69314 Binary files /dev/null and b/fldigi_doxygen/images/win10-mic-properties.png differ diff --git a/fldigi_doxygen/images/win10-rec-properties.png b/fldigi_doxygen/images/win10-rec-properties.png new file mode 100644 index 00000000..06411bf4 Binary files /dev/null and b/fldigi_doxygen/images/win10-rec-properties.png differ diff --git a/fldigi_doxygen/user_src_docs/ConfigMisc.txt b/fldigi_doxygen/user_src_docs/ConfigMisc.txt index a45c3409..b4f82f6e 100644 --- a/fldigi_doxygen/user_src_docs/ConfigMisc.txt +++ b/fldigi_doxygen/user_src_docs/ConfigMisc.txt @@ -107,7 +107,7 @@ over HF and VHF radio.Additional information on flarq is available here: The reception of a flwrap and flmsg files can be automated by selecting -the "Enable detection & extraction" option. The wrap program +the "Enable detection" option. The wrap program can then be used to test for validity and data extraction at some later time. fldigi can recognize flmsg data files and automatically open the flmsg program with the newly received data stream. It @@ -115,6 +115,10 @@ can also transfer the data stream to flmsg and instruct flmsg to save the data file, unwrap and decode it, display the data in a fully formatted html page and then exit. Pressing "Locate flmsg" performs differently on the different OS that are supported. + +The ability to transfer incoming flmsg data streams directly to an executing +flmsg was introduced with flmsg 3.0. Check that option if you are using flmsg +3.0 or greater.

    diff --git a/fldigi_doxygen/user_src_docs/ConfigUI-macros.txt b/fldigi_doxygen/user_src_docs/ConfigUI-macros.txt index 44fb270c..212c5c12 100644 --- a/fldigi_doxygen/user_src_docs/ConfigUI-macros.txt +++ b/fldigi_doxygen/user_src_docs/ConfigUI-macros.txt @@ -30,9 +30,16 @@ fldigi macro bar positions will change immediately so you can see the selection.
    -With 2 rows shown you obtain access to the primary set with normal -Function key press. The secondary set is accessed by a -SHIFT-Function-key press. +
    +\image html macrobuttons.png "Macro Buttons" +\image latex macrobuttons.png "Macro Buttons" width=6.0in +
    +
    + +
    +\image html macro-scheme-4.png "Macro Buttons - Scheme 4" +\image latex macro-scheme-4.png "Macro Buttons - Scheme 4" width=6.0in +

    You edit any macro definition by using a mouse right-click on it's button. @@ -43,6 +50,25 @@ sub-sets. When checked you simply hover the mouse over the macro bar and roll the mouse wheel.
    +All 48 macro buttons can be displayed in a matrix. + +\image html macro-matrix.png "Macro Buttons Matrix" +\image latex macro-matrix.png "Macro Buttons Matrix" width=6.0in +
    + +The matrix display is toggled on and off using the menu item +
    +\image html view-hide-48.png "" +\image latex view-hide-48.png "" width=1.0in +
    +
    + +The matrix display can be dragged off and restored to it's position below +the main menu. The drag button is the knurled vertical button on the left +edge of the matrix. Left click on the drag button and drag the matrix with +the mouse. +
    + Fldigi manages multiple files that contain macro definitions. You may want to have the last used macro file be the one available the next time you start fldigi. If so, simply enable the "load last used Macro file on diff --git a/fldigi_doxygen/user_src_docs/Doxyfile b/fldigi_doxygen/user_src_docs/Doxyfile index 4ab5b391..0798285f 100644 --- a/fldigi_doxygen/user_src_docs/Doxyfile +++ b/fldigi_doxygen/user_src_docs/Doxyfile @@ -13,7 +13,7 @@ # input used in their production; they are not affected by this license. PROJECT_NAME = "FLDIGI Users Manual" -PROJECT_NUMBER = 3.22 +PROJECT_NUMBER = 3.23 PROJECT_BRIEF = ALLEXTERNALS = NO CASE_SENSE_NAMES = NO @@ -42,8 +42,11 @@ INPUT = index.txt \ fldigi_macros.txt fldigi_modems.txt fldigi_operating.txt \ fldigi_developer.txt \ New-Install.txt thumb_drive.txt colorsandfonts.txt \ + audio-adjust.txt \ configcallsigndb.txt configContestia.txt configCW.txt \ - configDomEX.txt configFH.txt configFSQ.txt ConfigID.txt configIO.txt ConfigMisc.txt \ + configDomEX.txt configFH.txt \ + configFSQ.txt configIFKP.txt \ + ConfigID.txt configIO.txt ConfigMisc.txt \ configModemScan.txt configMT63.txt configOlivia.txt ConfigOperator.txt \ configPSK.txt \ configRTTY.txt configThor.txt ConfigUI-browser.txt \ @@ -53,18 +56,20 @@ INPUT = index.txt \ SoundCardSetup.txt Contest-How-To.txt cabrilloreporter.txt \ Logbook.txt LogExports.txt working_logs.txt Macros.txt \ InlineMacroTags.txt atMacroTags.txt advanced_qsy.txt execmacro.txt CW.txt \ - DominoEX.txt hell.txt Contestia.txt MFSK.txt MT63.txt FSQ.txt \ + DominoEX.txt hell.txt Contestia.txt MFSK.txt MT63.txt \ + FSQ.txt IFKP.txt \ Navtex.txt psk.txt Olivia.txt RTTYFSK.txt Thor.txt \ - throb.txt tune.txt WEFAX.txt WWV-xmt.txt FrequencyAnalysis.txt \ + throb.txt WEFAX.txt WWV-xmt.txt FrequencyAnalysis.txt \ DigiscopeDisplay.txt DigiWWV.txt MousingKeyboardShortcuts.txt \ Multiples.txt Notifier.txt OperatingControls.txt RST-RSQ.txt \ Spotter.txt Synop.txt TransceiverControl.txt UTF8.txt \ pskmail_config.txt PskViewer.txt DXCC_list.txt \ - KeyboardAndKeys.txt KML.txt support_data.txt Installing.txt WindowsOS.txt \ + KeyboardAndKeys.txt xchar.txt \ + KML.txt support_data.txt Installing.txt WindowsOS.txt \ Wizard.txt Menus.txt ModeTable.txt CWkeying.txt \ PseudoFSK.txt w5zit-interface.txt rigxml.txt commandline.txt \ buildinfo.txt xmlrpc-control.txt parseUALR.txt ualr-telnet.txt \ - map.txt License.txt Recognitions.txt bpq32.txt + map.txt License.txt Recognitions.txt kiss_host_prgs.txt INCLUDE_PATH = . EXAMPLE_PATH = . OUTPUT_DIRECTORY = ../user_docs diff --git a/fldigi_doxygen/user_src_docs/FSQ.txt b/fldigi_doxygen/user_src_docs/FSQ.txt index 72dd9471..64ce7222 100644 --- a/fldigi_doxygen/user_src_docs/FSQ.txt +++ b/fldigi_doxygen/user_src_docs/FSQ.txt @@ -58,12 +58,13 @@ can be resized vertically by dragging the dividing bar which separates them. \image latex fsq-undirected-mode.png "Undirected Mode" width=1.5in + \image html fsq-directed-mode.png "Directed Mode" \image latex fsq-directed-mode.png "Directed Mode" width=1.5in - + The Rx-text panel displays only recognized text in the Directed Mode. The text @@ -72,10 +73,22 @@ the directed station callsign is your own or "allcall". FSQ is case sensitive, and your sending case must match the senders case, i.e. w1hkj and W1HKJ are not the same for the purposes of FSQ Directed Mode. -fldigi-FSQ is active and will respond to directed triggers when the SELCAL button is lit. -Toggling the SELCAL button to "sleep" causes the FSQ parser to only respond to the -∗ trigger. When the ∗ trigger is received the program will return to -the active SELCAL state. +
      +
    • FSQ-ON
      + when on the xmt and rcv are in FSQ directed mode
      + when off the xmt and rcv are in FSQ undirected mode
    • +
    • ACTIVE
      + when on the decoder will accept all incoming directed traffic
      + when off the decocer will only respond to the wake-up * trigger
    • +
    • MON
      + when on the monitor panel is visible
    • +
    • QTH
      + appends the myQTH text to the tx panel
    • +
    • QTC
      + appends the myQTC text to the tx panel
    • +
    • CQ
      + sends the FSQ cq call 'cqcqcq'
    • +
    \image html fsq-heard-list.png "Heard List Panel" @@ -85,6 +98,8 @@ the active SELCAL state. The "Heard" list displays the callsign, s/n, and time of reception of all correctly decoded transmissions. +NOTE: fldigi function keys are inoperative in the FSQ mode! +
    \section coding_and_modulation Modulation Scheme @@ -267,11 +282,11 @@ Directed Mode. In Directed Mode, only text directed to your callsign will print in the Rx panel, and only commands directed to your station will be responded to.
    -\image html fsq-mon-dialog.png "FSQ Monitor Panel - a Directed Mode Sentence" -\image latex fsq-mon-dialog.png "FSQ Monitor Panel - a Directed Mode Sentence" width=3.5in +\image html fsq-mon-dialog.png "FSQ Monitor Panel" +\image latex fsq-mon-dialog.png "FSQ Monitor Panel" width=3.5in
    -The Monitor Panel is only shown during Directed Mode operation. It is minimized +The Monitor Panel is only shown during Directed Mode operation. It is hidden when Undirected Mode is in use. All incoming traffic is printed on the Monitor Panel. This includes both Directed and Undirected traffic. The decoding is affected by the fldigi squelch setting. @@ -286,6 +301,10 @@ failed to parse correctly:
  • or it is not directed to your callsign or allcall. +The lower half of the monitor panel displays text that is queued for transmission, +for example the response to a ? or a $ trigger. Automated responses are not sent +immediately, but after a small random delay AND when the squelch is not open. + FSQCall Preamble The FSQCall preamble consists of the sending station’s callsign, a colon, and a @@ -391,7 +410,6 @@ This list shows all the reserved characters, and their current or planned use. Blank entries are reserved, with no currently planned application.
    - CHAR | ASCII | USE :-----:|:-----:|:-------------------------------------------: Space | 32 | Directed chat @@ -426,8 +444,8 @@ _ | 95 | Report the squelch setting in dB (1) \| | 124 | Send Alert } | 125 | -- ~ | 126 | Delayed Repeat command -
    (1) not supported +
  • \section fsq_commands Commands @@ -445,13 +463,13 @@ The syntax for currently defined commands is listed below.
    • callsign text Addressee station starts to print text. No trigger character used except space following callsign. You MUST use a space or the trigger will not be recognised.
    • callsign? text (Is station hearing me?) Addressee station starts to print text. When squelch closes, station responds: origin_callsign snr=xxdB -
    • callsign\* Switches station to ACTIVE if FSQSEL is in SLEEP. Addressee station starts to print. When squelch closes, station responds: callsign: Active -
    • callsign! message (Repeat my message) Addressee station starts to print. When squelch closes, station responds: callsign: message. This is a simple relay mechanism. message may contain further trigger commands. -
    • callsign~ message (Repeat my message later) Addressee station starts to print. When squelch closes, after a delay of about 15 seconds, station responds: callsign: message This delayed relay is useful when stations mentioned in message can hear and respond to the original message. +
    • callsign\* Switches station to ACTIVE if FSQSEL is in SLEEP. Addressee station starts to print. When squelch closes, station responds: callsign:CRC-VAL Active +
    • callsign! message (Repeat my message) Addressee station starts to print. When squelch closes, station responds: callsign:CRC-VAL message. This is a simple relay mechanism. message may contain further trigger commands. +
    • callsign~ message (Repeat my message later) Addressee station starts to print. When squelch closes, after a delay of about 15 seconds, station responds: callsign:CRC-VAL message This delayed relay is useful when stations mentioned in message can hear and respond to the original message.
    • callsign; [relay_to]{trigger}{message} Relay my message to the 'relay_to' station. See Relay section for details.
    • callsign!sendto message Relay message to the 'sendto' station. Addressee station starts to print. When squelch closes, station relays the message. -
    • callsign#[nnn] (Send file to station) Addressee station starts to print. Text following [nnn] will be saved in or appended to text file nnn.txt in the same folder as the log/audit files. When squelch closes, station responds callsign: Ack if the message stored OK. There is no response if the message was not received. [nnn] can be alpha, numeric or mixed. -
    • callsign#[filename.txt] (Send file to station) Addressee station starts to print. File is opened from menu, and filename appended to message before file body text, File will be saved in or appended to text file filename.txt in the same folder as the log/audit files. When squelch closes, station responds callsign: if the message stored OK. There is no response if the message was not received. [nnn] can be alpha, numeric or mixed. +
    • callsign#[nnn] (Send file to station) Addressee station starts to print. Text following [nnn] will be saved in or appended to text file nnn.txt in the same folder as the log/audit files. When squelch closes, station responds callsign:CRC-VAL Ack if the message stored OK. There is no response if the message was not received. [nnn] can be alpha, numeric or mixed. +
    • callsign#[filename.txt] (Send file to station) Addressee station starts to print. File is opened from menu, and filename appended to message before file body text, File will be saved in or appended to text file filename.txt in the same folder as the log/audit files. When squelch closes, station responds callsign:CRC-VAL if the message stored OK. There is no response if the message was not received. [nnn] can be alpha, numeric or mixed.
    • callsign\@ (Request station position or location information) Addressee station starts to print. When squelch closes, station responds with pre-recorded sentence, typically containing QTH information. This could be GPS position, locator, or physical address. This is the message stored and retreived by the QTH button.
    • callsign& (Request station message) Addressee station starts to print. When squelch closes, station responds with pre-recorded sentence, typically containing station information or an 'Out to Lunch' message. This is the message stored by the QTC button.
    • callsign^ (Request Software Version) Addressee station starts to print. When squelch closes, station responds with current FSQCALL software version. @@ -469,7 +487,7 @@ If the speed is already at the maximum or minimum speed, the response is the sam and there is no speed change.
    • allcall#[nnn] (Send file to all stations) All stations within range start to print. Text following [nnn] will be saved in or appended to text file nnn.txt. When -squelch closes, station responds callsign: Ack if the message stored OK. There +squelch closes, station responds callsign:CRC-VAL Ack if the message stored OK. There is no response if the message was not received. allcall#[filename.txt] works the same as callsign#[filename.txt].
    diff --git a/fldigi_doxygen/user_src_docs/IFKP.txt b/fldigi_doxygen/user_src_docs/IFKP.txt new file mode 100644 index 00000000..7a5a2360 --- /dev/null +++ b/fldigi_doxygen/user_src_docs/IFKP.txt @@ -0,0 +1,472 @@ +/** +\page ifkp_page IFKP + +\tableofcontents + +\section IFKPplus Incremental Frequency Keying Plus + +
    +
    +\image html ifkp-rx-tx.png "ifkp main dialog" +\image latex ifkp-rx-tx.png "ifkp main dialog" width=4.0in +
    +
    + +The main dialog ifkp user interface provides an Rx-text panel, a Tx-text panel, +a "Heard" list, and an ifkp signal to noise indicator, and an avatar image. The +default avatar is the "Tux" logo. Sending, receiving and saving avatars is discussed +in the avatar section. + +Keyboard operation in ifkp is identical to other digital modes such as PSK, MFSK, +DominoEX, etc. with a primary difference; the alphabet is a truncated version of +the MicroSoft Code Page 1250, CP1250. This alphabet is described in the ifkp varicode +section. + +Unlike FSQ, which uses a similar incremental frequency keying technique, IFKP does +not employ any special protocols. The exception to this rule is for the transmission +and reception of IFKP images. + +IFKP transmission and reception can occur anywhere within the nominal passband of +500 to 3500 Hertz. fldigi will adjust the waterfall tracking point if the center frequency +selected would create a signal that is either above or below the nominal passband. +The default audio frequency is 1500 and most operators will elect to use the default. + +\section IFKPheard IFKP heard list + +The IFKP decoder includes a parser which continuously examines the received text +stream looking for a sequence of characters which begins with \de\, independent +of case. \ is the space character. The ensuing word is then tested for validity +as a callsign. The following examples would all be qualified as a valid callsign: +
    +" DE W1HKJ "
    +" de kl7cgf "
    +" de     W3FQN "
    +" de K2LBM"
    +"de N2IKY"
    +
    +Note that the white space can be extended between the "de" and the callsign. The +callsign can be terminated with either a space character or a new line character. + +When a valid callsign is discovered it is added to the heard list along with the time +and detected signal to noise ratio. New callsigns are always prepended to the top of +the heard list. Any older heard list entries with the same callsign are purged. + +Left clicking on a heard list entry inserts that callsign in the Tx panel at the +cursor position. Right clicking on a heard list entry deletes that entry from +the list. + +\section IFKPspec IFKP specification + +IFKP is a incremental frequency keyed mode with an offset of +1. It is designed +for very high coding efficiency. This version uses 33 tones (32 differences), +a Varicoded Alphabet, with a rotating difference frequency. Modem statistics: +
    +
    +| Parameter | Value +:--------------|----------: +Samplerate | 16000 | +Bandwidth | 386 | +Center freq | 1500(1) | +Symbol length | 4096 | +Lower case cps | 3.65 | +(1) nominal, adjustable from 500 to 3500 Hertz +
    +
    +Tone differences are expressed as decimal numbers 0 - 31. The alphabet design +uses single-symbol and two-symbol character codes. The character set does not +include much extended ASCII, and has only 116 different codes. It is a strongly +'unsquare' design (29 x 3), which restricts the number of codes, but we don't +need the maximum anyway. This 'unsquare' code maximizes the single-symbol set to +29, so will fit all lower case in one symbol. Using 29 initials means using a +comparison process to discover where the initial symbols are. +
    + +Amateur communications does not follow standard English text for letter frequency. +It has a higher incidence of letters such as Q, X and Z (in Q codes and callsigns). +Lower case letters are more common than upper case. Numbers are considered equal +in frequency of occurance to upper case characters. +
    + +The IFKP character set has been designed for one set of 29 single-symbol characters, +and three two-symbol sets of upper case letters, number and punctuation. There +is some spare space, and a few extended ASCII characters have been included (± ÷ ° £ ×). +
    + +There are 29 single-symbol characters, 87 two-symbol codes, and a total +alphabet of 116 codes. This allows coding all upper case, lower case and +punctuation. The most common symbol is the NULL, a non printing character +and is assigned a single symbol entry in the table. +
    + +The nomenclature used for the character symbol numbers in the tables is +
    +[1st_symbol], ([2nd_symbol])
    +
    +expressed in decimal, where the [1st_symbol] always has values less than 29, +and the [2nd_symbol] will have a value of 30 or 31. +
    +\section IFKPvaricode IFKP Varicode + +The IFKP varicode table is defined as shown in the following tables: +
    +| CHAR | ASCII | VAR | CHAR | ASCII | VAR | CHAR | ASCII | VAR +:------:|------:|-------:|:-----:|------:|-------:|:-----:|------:|-------: +| IDLE | 0 | 0 | \@ | 64 | 0,29 | ` | 96 | 9,31 +| ! | 33 | 11,30 | A | 65 | 1,29 | a | 97 | 1 +| \" | 34 | 12,30 | B | 66 | 2,29 | b | 98 | 2 +| # | 35 | 13,30 | C | 67 | 3,29 | c | 99 | 3 +| $ | 36 | 14,30 | D | 68 | 4,29 | d | 100 | 4 +| % | 37 | 15,30 | E | 69 | 5,29 | e | 101 | 5 +| & | 38 | 16,30 | F | 70 | 6,29 | f | 102 | 6 +| ' | 39 | 17,30 | G | 71 | 7,29 | g | 103 | 7 +| ( | 40 | 18,30 | H | 72 | 8,29 | h | 104 | 8 +| ) | 41 | 19,30 | I | 73 | 9,29 | i | 105 | 9 +| * | 42 | 20,30 | J | 74 | 10,29 | j | 106 | 10 +| + | 43 | 21,30 | K | 75 | 11,29 | k | 107 | 11 +| , | 44 | 27,29 | L | 76 | 12,29 | l | 108 | 12 +| - | 45 | 22,30 | M | 77 | 13,29 | m | 109 | 13 +| . | 46 | 27 | N | 78 | 14,29 | n | 110 | 14 +| / | 47 | 23,30 | O | 79 | 15,29 | o | 111 | 15 +| 0 | 48 | 10,30 | P | 80 | 16,29 | p | 112 | 16 +| 1 | 49 | 1,30 | Q | 81 | 17,29 | q | 113 | 17 +| 2 | 50 | 2,30 | R | 82 | 18,29 | r | 114 | 18 +| 3 | 51 | 3,30 | S | 83 | 19,29 | s | 115 | 19 +| 4 | 52 | 4,30 | T | 84 | 20,29 | t | 116 | 20 +| 5 | 53 | 5,30 | U | 85 | 21,29 | u | 117 | 21 +| 6 | 54 | 6,30 | V | 86 | 22,29 | v | 118 | 22 +| 7 | 55 | 7,30 | W | 87 | 23,29 | w | 119 | 23 +| 8 | 56 | 8,30 | X | 88 | 24,29 | x | 120 | 24 +| 9 | 57 | 9,30 | Y | 89 | 25,29 | y | 121 | 25 +| : | 58 | 24,30 | Z | 90 | 26,29 | z | 122 | 26 +| ; | 59 | 25,30 | [ | 91 | 1,31 | { | 123 | 6,31 +| < | 60 | 26,30 | \\ | 92 | 2,31 | \| | 124 | 7,31 +| = | 61 | 0,31 | ] | 93 | 3,31 | } | 125 | 8,31 +| > | 62 | 27,30 | ^ | 94 | 4,31 | ~ | 126 | 0,30 +| ? | 63 | 28,29 | _ | 95 | 5,31 | DEL | 127 | 28,31 +| CHAR | ASCII | VAR +:------:|------:|-------: +| CRLF | 13/10 | 28,30 +| SPACE | 32 | 28 +| ± | 241 | 10,31 +| ÷ | 246 | 11,31 +| ° | 248 | 12,31 +| × | 158 | 13,31 +| £ | 156 | 14,31 +| BS | 8 | 27,31 +
    +
    + +Here is a simple analysis of projected text efficiency compared with DominoEX: +
    +
    +          |                       Symbols                         | Nbr
    +Message   |The Quick Brown Fox jumps over the lazy dog 1234567890.|     
    +DominoEX  |2211221221211211212122222112111121121221212122222222222|88   
    +IFKP      |2111211111211111211111111111111111111111111122222222221|69   
    +Message   |vk2abc de zl1xyz ge om ur rst529 name fred. hw? kkk    |     
    +DominoEX  |222121111122222212111211111112221112112111212221222    |75   
    +IFKP      |112111111111211111111111111112221111111111111121111    |57   
    +
    +
    +It is about 27% more efficient than DominoEX. Note especially the score sending +typical 'ham speak' - some 30% more efficient than DominoEX. The typing speed at +3.65 cps is about 37 WPM. Q codes and callsigns should be sent in lower case when +possible. +
    + +Character rate statistics for various character sets when sent using IFKP, +
    +
    +text: abcdefghijklmnopqrstuvwxyz
    +chars/sec: 3.65
    +
    +text: ABCDEFGHIJKLMNOPQRSTUVWXYZ
    +chars/sec: 1.84
    +
    +text: 0123456789
    +chars/sec: 1.84
    +
    +text: !@#$%&*()_+-=[]{}\|;:'",\<\>/?\\
    +chars/sec: 1.84
    +
    + +\section IFKPspeed IFKP xmt speed + +fldigi-ifkp can transmit text in one of 3 speeds, 0.5X, 1.0X and 2.0X. The 1.0X +speed is the natural speed of the modem. The 0.5X and 2.0X speeds are obtained by +dividing or multiplying the symbol length by 2 respectively. You can expect to +experience decreased decoding errors with the 0.5X speed. Use it when s/n conditions +are well below minux 10 dB on the IFKP signal strength meter. The 2.0X speed should +probably not be used unless the s/n is well above plus 10 dB on the IFKP signal +strength meter. + +The three speeds can be selected at the time that IFKP is chosen from the mode menu. +The speed can also be changed using the IFKP modem configuration tab. The quickest +way to change speed is to left click on the left-most status indicator on the fldigi +status bar (lowest set of controls on the main dialog). A pop-up menu will appear with +the speed selections. The quick mode change and the configuration tab changes will +occur immediately even during transmission. The selection from the mode menu will +cause a complete reset of the IFKP modem. + +\section IFKPimage IFKP Image Mode + +fldigi-ifkp has the ability to transmit and receive small digital images selected +from those stored on the disk. The image transmission is similar to but not +compatible with the MFSKpic modes. IFKP images are always transmitted in a fixed +width to height ratio. The W x H format is not limited to a single ratio, nor is +it limited to just color, or just gray scale. The image mode is nearly identical +to the FSQ image mode with the exception of the RGB transmission sequence. IFKP +transmits in Blue-Green-Red order, whereas IFKP transmits in Red-Green-Blue order. +The IFKP image bandwidth is less than 400 Hz. + +The start of the picture is signalled digitally, and the receiver simply captures +data continuously for W lines of H pixels, as requested, resulting in a WxH pixel +image, then reception stops. + +IFKP Image Mode was designed for NVIS propagation on the lower HF bands. +Unlike SSTV, the pictures are sent relatively slowly, in a narrow bandwidth +(1/4 of SSTV), and as a result the picture signal to noise ratio is generally +better than SSTV for the same transmission power. As a guideline, IFKP signals +(before the picture is started) need to be about +10dB SNR for relatively +noise-free picture reception. + +IFKP pictures also offer significantly better reception than SSTV under NVIS +conditions. Because there is no picture sync, there is no risk of the picture +tearing due to timing changes, or breaking up during selective fades. All that +happens is that the image may noise up momentarily, but will stay correctly +aligned. The mode is also significantly less affected by ghosting. + +Image Format + +The images are approximately in 4:3 or 3:4 aspect ratio. IFKP images can be received +by any IFKP capable decoder. + +Available image aspect ratios / formats include: + +
      +
    • 59x74 color +
    • 160x120 color +
    • 320x240 color +
    • 640x480 grey scale +
    • 640x480 color +
    • 240x300 color +
    • 240x300 grey scale +
    • 120x150 color +
    • 120x150 grey scale +
    + +These formats correspond roughly to a portrait (3x4) and landscape (4x3) photo. +fldigi will scale any computer stored image to the target image. You should +edit the images off line to be at least close to the 3x4 or 4x3 ratio. That will +prevent the fldigi loader from distorting the loaded image. + +The image mode sampling rate is 16,000 samples/sec, the same as the text mode. +Each pixel consists of 8 samples, and there are P pixels/line. Therefore the +line period is 8 x P/16000 seconds, or the line rate 16000/(8 x P) lines/sec. +In colour, each line is sent three times, in Red-Green-Blue (RGB) order. + +As an example, if there were 320 pixels per line, and 240 lines, the line rate +would be 6.25 lines/sec, and 240 x 3 (for RGB) lines would take 115.2 seconds, or +1.92 minutes for a colour picture containing 76,800 pixels. + +There is a single sync signal sent at the beginning of each image. This sync signal +is a tone placed 186 Hz below the center frequency, or at 1384 Hertz. The sync signal +is 1.5 symbol lengths in duration, or 5.8 seconds. + +If the sound cards in the transmitting and receiving computers differ markedly +in sample rate, the resulting picture can also be skewed. A small timing +difference is enough to cause a noticeable slant in the picture. This is easily +fixed after reception using the Slant control. High quality sound cards should +be better than 5ppm, and result in barely noticeable slant, but some cheaper +computer built-in sound modules may be rather worse. If you plan to send IFKP +images you should calibrate your sound card to WWV. + +Transmit Image + +Transmitting an image in IFKP is initiated by selecting the "Send image" menu item +from the pop up Tx menu. Right click on the Tx panel + +
    +\image html ifkp-send-image.png "Send Image" +\image latex ifkp-send-image.png "Send Image" width=2in +
    + +This selection opens up the Send Image dialog + +
    +\image html ifkp-image-xmt.png "Send Image Dialog" +\image latex ifkp-image-xmt.png "Send Image Dialog" width=3.5in +
    + +shown with a 160x120 color image loaded and ready to transmit. + +Transmission begins when you press the "Xmt" button. fldigi will insert the text +preamble and immediately begin the image transmission. fldigi returns to the receive +mode when the image transmission is completed. + +
    +\image html ifkp-WF-image-mode.png "Image Mode Waterfall" +\image latex ifkp-WF-image-mode.png "Image Mode Waterfall" width=3.5in +
    + +There is an alternate way of sending an image, but one which only transmits a color +image with no provision for slant correction. This may be more convenient +for sharing images when you do not need the additional utility of the image dialog. +
    + +Open a file folder to the location of your image files that are suitable for MFSK +transmission. These images should be constrained to be 240 x 200 or less for +reasonable transmit times. Optionally prepare fldigi for the MFSK image +transmission by entering some suitable text to precede the transmission. +You may be sending the image, blossoms.jpg, for example. +
    + +
    +\image html blossoms.png "image in files folder" +\image latex blossoms.png "image in files folder" width=3.0in +
    + +One might enter: + +\image html blossoms-1.png "" +\image latex blossoms-1.png "" width=4.0in + +Then drag and drop the the image file from the files folder to the transmit +text panel in fldigi. The program will automatically resize the image to the +nearest scale-aspect ratio less than or equal to the actual image size. +
    + +The TX panel text will then change to + +\image html blossoms-2.png "" +\image latex blossoms-2.png "" width=4.0in + +The ^! is the character sequence used by the fldigi TX parser to indicate +that there is a pending execution command. In this case it is to transmit +the blossoms.jpg file. +
    + +Add some suitable ending text and the sequence ^r to the next line and +then press the T/R button (if not already transmitting). At the end of the +image the TX parser will find the ^r and return the program to the receive +mode. + +The Rx panel will echo the transmitted data: +
    +\image html thor-pic-transmission.png "" +\image latex thor-pic-transmission.png "" width=4.0in + +The transmit progress dialog will close at the conclusion of the image transmission. + +Receive Image + +Reception is completely automatic. The decoder will identify the picture start, +and record the picture. In doing so, it automatically opens a separate "IFKP Rx Image" dialog. + +
    +\image html ifkp-image-partial.png "Image Reception" +\image latex ifkp-image-partial.png "Image Reception" width=3.5in +
    + +Demodulation uses a phase detection algorithm based on quadrature demodulation +using the current and previous samples at 16000 samples/sec. All the samples are +converted to pixels and stored, but only the average over every 16 samples is +displayed. + +The raw image is stored in a temporary buffer of expanded size, which allows +fine adjustment of the slant and phase to be made before the image is sampled +and displayed. + +If the transmitting station goes off the air or reception is lost during +recording of a picture, the recording will continue until the necessary number +of samples has been made, then reception stops. + +
    +\image html ifkp-image-completed.png "Image Reception Completed" +\image latex ifkp-image-completed.png "Image Reception Completed" width=3.5in +
    + +The Rx Image dialog controls from left to right are: +- Reset: clears all rx data +- Phase adjustment: moves image left and right +- Slant adjustment: slews image diagonally +- Save: saves the image to the fldigi image folder with a date-time stamped file name +- Close: closes the image dialog + +Image phase and slant should not be adjusted before the picture reception has +finished, as then only part of the image will be corrected. + +\section ifkp_avatars Avatars + +Avatar images are 59 x 74 (width x height) color images that are associated with +a call sign. The avatar images are stored in the folder + +
    +C:\\Documents and Settings\\\\\fldigi.files\\avatars\\
    +C:\\Users\\\\\fldigi.files\\avatars\\
    +/home/\/.fldigi/avatars/
    +
    + +as "png" images. + +You should prepare an image file for your own call sign, in lower case. For example + +
    +/home/dave/.fldigi/avatars/w1hkj.png
    +
    + +in a 4x5 aspect ratio, preferably in the 59x74 format, but any larger 4x5 image can be used. +fldigi will scale the image to 59x74 when it is read from the file. + +You can send your avatar very simply by right clicking on the IFKP avatar. + +If you receive an avatar from another station it will automatically be displayed in +the avatar box. You should have previously entered the call sign of the other station in +the Call logging control. Left clicking on the avatar will then save the image in the +avatars folder with the appropriate callsign. The correct avatar will then be displayed +the next time you enter that call sign in the Call logging control. This is an example +of a received avatar with timing misalignment. + +
    +
    +\image html ifkp-avatar-1.png "received avatar" +\image latex ifkp-avatar-1.png "received avatar" width=1.0in +
    +
    + +The received image may be misaligned left or right in the image box. This is caused +by an error in the start timing of the reception. You can realign the image using a +combination of SHIFT, CONTROL and LEFT/RIGHT mouse clicks on the image. Be careful +to use either the SHIFT or CONTROL in combination with the mouse button. Mouse left +and right click without the SHIFT/CONTROL will cause either a save or an own avatar +transmit to occur. + +
    +CONTROL LEFT click  - move image left by 1 pixel
    +SHIFT   LEFT click  - move image left by 5 pixels
    +
    +CONTROL RIGHT click - move image right by 1 pixel
    +SHIFT   RIGHT click - move image right by 5 pixels
    +
    + +The same image after alignment. + +
    +
    +\image html ifkp-avatar-2.png "received avatar" +\image latex ifkp-avatar-2.png "received avatar" width=1.0in +
    +
    + +You will probably need to manage the avatar images using your OS file explorer. Easy +access to the image folder is obtained by the menu item File/Folders. + +The avatar image format is identical to the IFKP image 59x74 format. If you receive +and save a 59x74 image you can always rename the saved image (date-time-stamped) to +a \"callsign.png\" in the avatar folder. + +\ref ifkp_page "Return to Top of Page" +
    +\ref main_page "Return to Main Page" +*/ + diff --git a/fldigi_doxygen/user_src_docs/KeyboardAndKeys.txt b/fldigi_doxygen/user_src_docs/KeyboardAndKeys.txt index f3fab511..86cb6c38 100644 --- a/fldigi_doxygen/user_src_docs/KeyboardAndKeys.txt +++ b/fldigi_doxygen/user_src_docs/KeyboardAndKeys.txt @@ -23,12 +23,20 @@ text into the transmit buffer. There is one very important exception:
    -The caret "^" symbol. This is used in the macro expansion routine -and also used by the transmit buffer evaluator. A ^r puts fldigi into -receive mode. So you can enter the ^r (caret followed by the r) at the end -of your transmit buffer and when the sent character cursor (red chars) gets to -that point the program will clear the text and return to the receive -mode. +The caret "^" symbol, which fldigi uses as a meta character. The ^ is +used in the macro expansion routine and also used by the transmit buffer +evaluator. A ^r puts fldigi into receive mode. So you can enter the ^r +(caret followed by the r) at the end of your transmit buffer and when +the sent character cursor (red chars) gets to that point the program will +clear the text and return to the receive mode. +
    + +Other useful meta combinations: +
      +
    • ^l ^L - save the log entry when meta combination parsed
    • +
    • ^p ^P - pause transmission at this point in transmit text
    • +
    • ^r ^R - return to receive clear all transmit text
    • +

    You can load the transmit buffer with any ASCII Text file of your @@ -81,14 +89,33 @@ fldigi text widget supports some short cuts to make your life easier:
  • Alt/Meta-R will perform the same function as the Pause/Break key
  • -
  • Tab moves the cursor to the end of the transmitted text (which - also pauses tx). A tab press at that position moves the cursor to the - character following the last one transmitted. CW operation is slightly - different, see the help for \ref cw_page .
  • - -
  • Ctrl + three digits will insert the ASCII character designated by - that entry.
  • +
  • Tab moves the text insert cursor to the end of the transmitted text + (which also pauses tx). Characters entered from the keyboard will be + transmitted as entered until the tx text entry point is returned to the + end of the tx buffer. A tab press at that position returns the cursor + to the end of the text buffer. Transmitted text and text pending transmit + are color coded red and black respectively (default colors): + +
    + \image html TxCursor.png "Tx Cursor Position" + \image latex TxCursor.png "Tx Cursor Position" width=2.5in +
    + + Be aware that fldigi will NEVER transmit past the text insert cursor! You + may be caught by that behavior if you are modifying the buffer and transmitting + at the same time. Or you may have accidentally mouse clicked in the middle of + the Tx text with the result that fldigi suddenly stops transmitting. In either + case the Tab key will return the text insert cursor to the end of the tx buffer. + + CW operation is slightly different, see the help for \ref cw_page .
  • +
  • Extended UTF-8 characters can be entered into all text entry controls + using Ctrl + three digits. These characters can also be entered using + the right-click pop-up menu item \"Spec Char \". The extended character + transmitted by fldigi will actually be a 2 byte UTF-8 string. + + see \ref xchar_page "Extended Characters" +
\section function_keys Function Keys diff --git a/fldigi_doxygen/user_src_docs/MFSK.txt b/fldigi_doxygen/user_src_docs/MFSK.txt index cb036f44..3b31e739 100644 --- a/fldigi_doxygen/user_src_docs/MFSK.txt +++ b/fldigi_doxygen/user_src_docs/MFSK.txt @@ -27,7 +27,6 @@ This is an example of properly tuned MFSK16 signal with a s/n of approximately 9 dB.
- \image html mfsk-9db.png " MFSK16 signal" \image latex mfsk-9db.png " MFSK16 signal" width=6.0in
@@ -61,15 +60,6 @@ is subject to burst and phase noise on the transmission path. It can provide excellent photo transmission on a really good path.
-\image html mfskpix-bee.png "Received MFSK Image" -\image latex mfskpix-bee.png "Received MFSK Image" width=2.0in -
- -This is an example of a photo received on a bench test. The received -image is an exact replica of the transmitted image. The color depth is -a full 24 bits. -
- Images should be carefully selected for size before beginning a transmission. To calculate the transmit time for an image use the following formula: @@ -100,12 +90,11 @@ Received images are saved in the default folder $HOME/.fldigi/images \section mfsk_tx_image Transmitting an Image - \image html Xmt-Pix.png "Xmit Picture Dialog box" \image latex Xmt-Pix.png "Xmit Picture Dialog box" width=3.0in
-You can only transmit an image while in the MFSK-16 mode. The +You can only transmit an image while in the MFSK-16/32/64/128 modes. The image can be prepared for transmission while in the receive mode. Right click in the transmit text box and select "Send Image" from the popup menu. This will open up the transmit image dialog which will be blank to start. @@ -159,28 +148,84 @@ will then have to toggle the T/R button if you want to return to receive.
-\image html Xmt-Pix3.png "Received MFSK Image" -\image latex Xmt-Pix3.png "Received MFSK Image" width=1.5in +There is an alternate way of sending an image, but one which only transmits a color +image with no provision for slant correction. This may be more convenient +for sharing images when you do not need the additional utility of the image dialog.
-The receiving program decodes the "Pic:110x119C;" as a color picture -110 wide by 119 high. Here is shown being received on a computer -running Vista Home Premium. +Open a file folder to the location of your image files that are suitable for MFSK +transmission. These images should be constrained to be 240 x 200 or less for +reasonable transmit times. Optionally prepare fldigi for the MFSK image +transmission by entering some suitable text to precede the transmission. +You may be sending the image, blossoms.jpg, for example.
+
+\image html blossoms.png "image in files folder" +\image latex blossoms.png "image in files folder" width=3.0in +
-\image html Xmt-Pix4.png "Waterfall of a MFSK Image" -\image latex Xmt-Pix4.png "Waterfall of a MFSK Image" width=3.5in +One might enter: + +\image html blossoms-1.png "" +\image latex blossoms-1.png "" width=4.0in + +Then drag and drop the the image file from the files folder to the transmit +text panel in fldigi. +
+ +The TX panel text will then change to + +\image html blossoms-2.png "" +\image latex blossoms-2.png "" width=4.0in + +The ^! is the character sequence used by the fldigi TX parser to indicate +that there is a pending execution command. In this case it is to transmit +the blossoms.jpg file. +
+ +Add some suitable ending text and the sequence ^r to the next line and +then press the T/R button (if not already transmitting). At the end of the +image the TX parser will find the ^r and return the program to the receive +mode. + +The Rx panel will echo the transmitted data: +
+\image html blossoms-3.png "" +\image latex blossoms-3.png "" width=4.0in + +The image progress dialog will close at the end of the image transfer. + +\section mfsk_rx_image Receiving an Image + +The receiving program decodes the "Pic:240x160C;" as a color picture +240 wide by 160 high. +
+\image html Xmt-Pix2.png "Received MFSK Image" +\image latex Xmt-Pix2.png "Received MFSK Image" width=3.0in +
This is what the waterfall will look like during the reception of an -MFSK-16 image. +MFSK-64 image.
+
+\image html Xmt-Pix3.png "MFSK Image - Waterfall" +\image latex Xmt-Pix3.png "MFSK Image - Waterfall" width=4.5in +
The actual spectrum signature will vary with the image bytes being -transmitted. The waterfall scale is in the x4 mode and the above -photo was being transmitted in 24 bit color for this screenshot. The +transmitted. The image was being transmitted in 24 bit color for this screenshot. The waterfall clearly shows that the image transmission is within the bandwidth -occupied by MFSK-16. +occupied by MFSK-64. + +Received images are automatically saved to the images folder and annotated with +a date-time stamp. + +
+\image html MFSK-rx-images.png "MFSK Rx Images" +\image latex MFSK-rx-images.png "MFSK Rx Images" width=4.5in +
+
\section mfsk_picture_slant Picture with a slant @@ -203,9 +248,8 @@ move the mouse to bottom left or right corner of the slanted images (the corner that clearly visible). Then left click on that corner. The program will correct for the slant. The correction will not be perfect but it may help to make the image more -viewable. -
- +viewable. Right click to undo the slant correction. Slant corrections are +not saved to the Rx image file.
\ref mfsk_page "Return to Top of Page" diff --git a/fldigi_doxygen/user_src_docs/Macros.txt b/fldigi_doxygen/user_src_docs/Macros.txt index bbbdf193..5ac9aec3 100644 --- a/fldigi_doxygen/user_src_docs/Macros.txt +++ b/fldigi_doxygen/user_src_docs/Macros.txt @@ -4,9 +4,17 @@ \tableofcontents Macros are short text statements that contain imbedded references to text -data used by the program fldigi. Macro definition files(s) are located -in the $HOME/.fldigi/macros/ directory and all have the extention ".mdf". The -default set of macros are contained in the +data used by the program fldigi. A macro is accessed via the macro button +bar or function key. + +
+\image html macrobuttons.png "Macro Buttons" +\image latex macrobuttons.png "Macro Buttons" width=6.0in +
+
+ +Macro definition files(s) are located in the $HOME/.fldigi/macros/ directory +and all have the extention ".mdf". The default set of macros are contained in the file $HOME/.fldigi/macros/macros.mdf. Fldigi will create this file with a set of default macros on its first @@ -15,7 +23,23 @@ execution. Fldigi supports up to 48 macro definitions in sets of 12. Macro definitions are not recursive, that is; a macro cannot reference -another macro or itself. +another macro or itself. All 48 macro buttons can be displayed in a matrix. + +\image html macro-matrix.png "Macro Buttons Matrix" +\image latex macro-matrix.png "Macro Buttons Matrix" width=6.0in +
+ +The matrix display is toggled on and off using the menu item +
+\image html view-hide-48.png "" +\image latex view-hide-48.png "" width=1.0in +
+
+ +The matrix display can be dragged off and restored to it's position below +the main menu. The drag button is the knurled vertical button on the left +edge of the matrix. Left click on the drag button and drag the matrix with +the mouse.
The imbedded references are similar to those used by DigiPan and other @@ -211,26 +235,6 @@ Macro | Description -
- -\verbatim - * Added macro to insert QRG text into Rx stream - - * Added save macro tag - * Added export strings - - FLDIGI_LOG_FILE - current logbook file name - - FLDIGI_MACRO_FILE - current macro file name - * Added tag - - returns to receive, but does not clear Tx buffer - * Added tag to control - transmit attenuator control from within a macro. - * Added macro tag - a do nothing that disappears from the transmitted - text -\endverbatim - -
- \section modem_macro_tags Modem macro tags Macro tags are also assigned to each supported modem type and sub-modem type diff --git a/fldigi_doxygen/user_src_docs/Menus.txt b/fldigi_doxygen/user_src_docs/Menus.txt index 5805ed29..d746d087 100644 --- a/fldigi_doxygen/user_src_docs/Menus.txt +++ b/fldigi_doxygen/user_src_docs/Menus.txt @@ -538,7 +538,7 @@ See \ref configuration_page Page
  • Tune button - toggles the "Tune" mode which causes fldigi to insert a tone at the current waterfall frequency. The peak-to-peak amplitude of this tone is the standard by which you should - \ref tune_page "set your transmitter drive" or adjust your antenna + \ref audio_adjust_page "set your transmitter drive" or adjust your antenna matching network.
  • The right most button is normally not visible. This is the count-down timer button that is enabled when a macro button has been diff --git a/fldigi_doxygen/user_src_docs/OperatingControls.txt b/fldigi_doxygen/user_src_docs/OperatingControls.txt index cfa5ff78..bd67f95f 100644 --- a/fldigi_doxygen/user_src_docs/OperatingControls.txt +++ b/fldigi_doxygen/user_src_docs/OperatingControls.txt @@ -137,7 +137,7 @@ FT950
  • \\
  • -The M\> button allows you to +The Store button allows you to store, recall and manage mode/frequency pairs. If you want to save the current mode and frequency simply left click the button. A right click will enable a popup menu from which you can select diff --git a/fldigi_doxygen/user_src_docs/Thor.txt b/fldigi_doxygen/user_src_docs/Thor.txt index 9fec94a2..85379713 100644 --- a/fldigi_doxygen/user_src_docs/Thor.txt +++ b/fldigi_doxygen/user_src_docs/Thor.txt @@ -20,6 +20,10 @@ detector that can lock on and detect the incoming signal even when badly mistuned. Frequency domain oversampling is used to allow proper tone detection without the need for AFC. The AFC control does not alter the decoder in any way. + +The fldigi implementation of the Thor modem includes the ability to send and +receive images and avatars. The default avatar is the "Tux" logo. +Sending, receiving and saving avatars is discussed in the avatar section.
    The waterfall and digiscope will appear as: @@ -40,11 +44,6 @@ tone pairs moving through the tone filters. You can also use an alternate digiscope display (left click on the digiscope display area).
    - -\image html dominoex-1a.png "DominoEx" -\image latex dominoex-1a.png "DominoEx" width=1.0in -
    - In this display mode the red line represents the center of the multiple tone bins that are in the detector. The dots will be blurry if the AFC is not locked on and become very distinct when AFC lock has been achieved. The @@ -52,22 +51,256 @@ tone dots will move from bottom to top (opposite the direction of the waterfall).
    -This is the same signal mistuned: +\section THORimage Thor Image Mode + +fldigi-thor can send and receive images and avatars when the modem is set to 11, 16 or 22 baud. + +Small digital images are selected from those stored on the disk. The image +transmission is similar to but not compatible with the IFKP image mode. +Thor images are always transmitted in a fixed width to height ratio. +The W x H format is not limited to a single ratio, nor is it limited to just +color, or just gray scale. Thor transmits the image in Blue-Green-Red +order. The thor image bandwidth is the same as the signal bandwidth for +for Thor mode in use. + +The start of the picture is signalled digitally, and the receiver simply captures +data continuously for W lines of H pixels, as requested, resulting in a WxH pixel +image, then reception stops. + +A brief period of silence, followed by a sync signal will be transmitted at the +beginning of each image or avatar. The sync signal is used to align the start of +the received image. This is the equivalent of a vertical sync signal in an +analog television signal. There is no equivalent of horizontal sync, therefore +there is no risk of the picture tearing due to timing changes, or breaking up +during selective fades. All that happens is that the image may noise up momentarily, +but will stay correctly aligned. + +Image Format + +The images are approximately in 4:3 or 3:4 aspect ratio. thor images can be received +by any thor capable decoder. + +Available image aspect ratios / formats include: + +
      +
    • 59x74 color +
    • 160x120 color +
    • 320x240 color +
    • 640x480 grey scale +
    • 640x480 color +
    • 240x300 color +
    • 240x300 grey scale +
    • 120x150 color +
    • 120x150 grey scale +
    + +These formats correspond roughly to a portrait (3x4) and landscape (4x3) photo. +fldigi will scale any computer stored image to the target image. You should +edit the images off line to be at least close to the 3x4 or 4x3 ratio. That will +prevent the fldigi loader from distorting the loaded image. + +The image mode sampling rate is the same as the base baud samplerate: +
      +
    • Thor-11 11025 samples/sec
    • +
    • Thor-16 8000 sampels/sec
    • +
    • Thor-22 11025 sampels/sec
    • +
    + +Each pixel consists of 10 samples, and there are P pixels/line. Therefore the +line period is 10 x P/sample-rate seconds, or the line rate sample-rate/(10 x P) lines/sec. +In colour, each line is sent three times, in Red-Green-Blue (RGB) order. + +The is a single sync signal sent at the beginning of each image is a tone placed 186 Hz +below the center frequency. The sync signal is 20 symbol lengths of silence followed by +20 symbol lengths of the tone. + +If the sound cards in the transmitting and receiving computers differ markedly +in sample rate, the resulting picture can be skewed. A small timing +difference is enough to cause a noticeable slant in the picture. This is easily +fixed after reception using the Slant control. High quality sound cards should +be better than 5ppm, and result in barely noticeable slant, but some cheaper +computer built-in sound modules may be rather worse. If you plan to send thor +images you should calibrate your sound card to WWV. There should be no slant if +both the transmit and receive sound cards are calibrated to WWV + +Transmit Image + +Transmitting an image in thor is initiated by selecting the "Send image" menu item +from the pop up Tx menu. Right click on the Tx panel + +
    +\image html thor-send-image.png "Send Image" +\image latex thor-send-image.png "Send Image" width=2in +
    + +This selection opens up the Send Image dialog + +
    +\image html thor-image-xmt.png "Send Image Dialog" +\image latex thor-image-xmt.png "Send Image Dialog" width=3.5in +
    + +shown with a 160x120 color image loaded and ready to transmit. + +Transmission begins when you press the "Xmt" button. fldigi will insert the text +preamble and immediately begin the image transmission. fldigi returns to the receive +mode when the image transmission is completed. + +There is an alternate way of sending an image, but one which only transmits a color +image with no provision for slant correction. This may be more convenient +for sharing images when you do not need the additional utility of the image dialog.
    -\image html dominoex-2.png "DominoEx Mistuned" -\image latex dominoex-2.png "DominoEx Mistuned" width=6.0in +Open a file folder to the location of your image files that are suitable for MFSK +transmission. These images should be constrained to be 240 x 200 or less for +reasonable transmit times. Optionally prepare fldigi for the MFSK image +transmission by entering some suitable text to precede the transmission. +You may be sending the image, blossoms.jpg, for example.
    -and with the signal badly mistuned: +
    +\image html blossoms.png "image in files folder" +\image latex blossoms.png "image in files folder" width=3.0in +
    + +One might enter: + +\image html blossoms-1.png "" +\image latex blossoms-1.png "" width=4.0in + +Then drag and drop the the image file from the files folder to the transmit +text panel in fldigi. The program will automatically resize the image to the +nearest scale-aspect ratio less than or equal to the actual image size.
    -\image html dominoex-3.png "DominoEx Mistuned 2" -\image latex dominoex-3.png "DominoEx Mistuned 2" width=6.0in +The TX panel text will then change to + +\image html blossoms-2.png "" +\image latex blossoms-2.png "" width=4.0in + +The ^! is the character sequence used by the fldigi TX parser to indicate +that there is a pending execution command. In this case it is to transmit +the blossoms.jpg file.
    +Add some suitable ending text and the sequence ^r to the next line and +then press the T/R button (if not already transmitting). At the end of the +image the TX parser will find the ^r and return the program to the receive +mode. + +The Rx panel will echo the transmitted data: +
    +\image html thor-pic-transmission.png "" +\image latex thor-pic-transmission.png "" width=4.0in + +The transmit progress dialog will close at the conclusion of the image transmission. + +Receive Image + +Reception is completely automatic. The decoder will identify the picture start, +and record the picture. In doing so, it automatically opens a separate "thor Rx Image" dialog. + +
    +\image html thor-image-partial.png "Image Reception" +\image latex thor-image-partial.png "Image Reception" width=6.0in +
    + +Demodulation uses a phase detection algorithm based on quadrature demodulation +using the current and previous samples. All the samples are converted to pixels and stored, +but only the average over every 10 samples is displayed. + +The raw image is stored in a temporary buffer of expanded size, which allows +fine adjustment of the slant and phase to be made before the image is sampled +and displayed. + +If the transmitting station goes off the air or reception is lost during +recording of a picture, the recording will continue until the necessary number +of samples has been made, then reception stops. + +
    +\image html thor-image-completed.png "Image Reception Completed" +\image latex thor-image-completed.png "Image Reception Completed" width=3.5in +
    + +The Rx Image dialog controls from left to right are: +- Reset: clears all rx data +- Phase adjustment: moves image left and right +- Slant adjustment: slews image diagonally +- Save: saves the image to the fldigi image folder with a date-time stamped file name +- Close: closes the image dialog + +Image phase and slant should not be adjusted before the picture reception has +finished, as then only part of the image will be corrected. + +\section thor_avatars Avatars + +Avatar images are 59 x 74 (width x height) color images that are associated with +a call sign. The avatar images are stored in the folder + +
    +C:\\Documents and Settings\\\\\fldigi.files\\avatars\\
    +C:\\Users\\\\\fldigi.files\\avatars\\
    +/home/\/.fldigi/avatars/
    +
    + +as "png" images. + +You should prepare an image file for your own call sign, in lower case. For example + +
    +/home/dave/.fldigi/avatars/w1hkj.png
    +
    + +in a 4x5 aspect ratio, preferably in the 59x74 format, but any larger 4x5 image can be used. +fldigi will scale the image to 59x74 when it is read from the file. + +You can send your avatar very simply by right clicking on the thor avatar. + +If you receive an avatar from another station it will automatically be displayed in +the avatar box. You should have previously entered the call sign of the other station in +the Call logging control. Left clicking on the avatar will then save the image in the +avatars folder with the appropriate callsign. The correct avatar will then be displayed +the next time you enter that call sign in the Call logging control. This is an example +of a received avatar with timing misalignment.
    +
    +\image html thor-avatar-1.png "received avatar" +\image latex thor-avatar-1.png "received avatar" width=1.0in +
    +
    + +The received image may be misaligned left or right in the image box. This is caused +by an error in the start timing of the reception. You can realign the image using a +combination of SHIFT, CONTROL and LEFT/RIGHT mouse clicks on the image. Be careful +to use either the SHIFT or CONTROL in combination with the mouse button. Mouse left +and right click without the SHIFT/CONTROL will cause either a save or an own avatar +transmit to occur. + +
    +CONTROL LEFT click  - move image left by 1 pixel
    +SHIFT   LEFT click  - move image left by 5 pixels
    +
    +CONTROL RIGHT click - move image right by 1 pixel
    +SHIFT   RIGHT click - move image right by 5 pixels
    +
    + +The same image after alignment. + +
    +
    +\image html thor-avatar-2.png "received avatar" +\image latex thor-avatar-2.png "received avatar" width=1.0in +
    +
    + +You will probably need to manage the avatar images using your OS file explorer. Easy +access to the image folder is obtained by the menu item File/Folders. + +The avatar image format is identical to the thor image 59x74 format. If you receive +and save a 59x74 image you can always rename the saved image (date-time-stamped) to +a \"callsign.png\" in the avatar folder. + \ref thor_page "Return to Top of Page"
    \ref main_page "Return to Main Page" diff --git a/fldigi_doxygen/user_src_docs/TransceiverControl.txt b/fldigi_doxygen/user_src_docs/TransceiverControl.txt index 0342069a..f6b06e31 100644 --- a/fldigi_doxygen/user_src_docs/TransceiverControl.txt +++ b/fldigi_doxygen/user_src_docs/TransceiverControl.txt @@ -4,22 +4,11 @@ \tableofcontents -\image html init-rig-setup.png "Initial Rig Setup" -\image latex init-rig-setup.png "Initial Rig Setup" width=2.0in +\image html init-rig-setup.png "Basic Rig Control" +\image latex init-rig-setup.png "Basic Rig Control" width=2.0in
    -CAT not enabled -
    - - -\image html docked-rig-control.png "Docked Rig Control" -\image latex docked-rig-control.png "Docked Rig Control" width=5.0in -
    - -CAT not enabled, Manual Entry of transceiver frequency -
    - -Note: The same control is also used for both manual entry of the +The same control is used for both manual entry of the transceiver frequency or with full CAT control. When no CAT is available the control is simply a convenient way of keeping track of the transceiver USB/LSB suppressed carrier frequency, the mode and the audio tracking @@ -30,31 +19,6 @@ compute the logged frequency. The logged frequency value will only be correct for LSB and USB operation.
    -The frequency/mode pick list is displayed when the book button is -pressed. Pressing the book button a second time will restore the -original logging panel. -
    - -The pick list buttons control selecting, adding and deleting entries in -the frequency/mode list. -
    - -
      -
    • add the current frequency / mode / audio track point to the list
    • -
    • select the current list entry
    • -
    • delete the highlighted entry from the list
    • -
    • delete all entries from the list (a warning prompt will appear)
    • -
    • show active frequencies based on either the entry field to the - right or the stations locator, - see \ref psk_reporter_page "pskreporter/spotter".
    • -
    • entry field for active frequencies search, for example "EM."
    • -
    - - -The browser list contains frequency, sideband, modem type and audio -frequency. The list is saved when fldigi is shut down. -
    - The combo box on the left will allow the selection and control of the operating mode of the transceiver.
    @@ -95,6 +59,47 @@ accordingly. FLDigi queries the transceiver 10 times per second to maintain a lock step with the transceiver.
    +\section frequencies_list Frequency List + +The frequency/mode pick list is displayed when the book button is +pressed. Pressing the book button a second time will restore the +original logging panel. +
    + +\image html view_frequencies.png "Frequency Pick List" +\image latex view_frequencies.png "Frequency Pick List" width=3.0in + +The pick list buttons control selecting, adding and deleting entries in +the frequency/mode list. +
    + +
      +
    • add the current frequency / mode / audio track point to the list
    • +
    • select the current list entry
    • +
    • delete the highlighted entry from the list
    • +
    • delete all entries from the list (a warning prompt will appear)
    • +
    • show active frequencies based on either the entry field to the + right or the stations locator, + see \ref psk_reporter_page "pskreporter/spotter".
    • +
    • entry field for active frequencies search, for example "EM."
    • +
    + + +The browser list contains frequency, sideband, modem type, audio +frequency, and a text describing usage. To edit the usage string: +
      +
    • highlight the entry to be edited
    • +
    • press the combination of SHIFT and right arrow while pointing to the line
    • +
    +This will hide the frequencies browser and display the data relative to that line + +\image html edit_freq_entry.png "Edit frequency list entry" +\image latex edit_freq_entry.png "Edit frequency list entry" width=3.0in + +Edit the text entry and press the "Enter" button when finished. + +The list is saved when fldigi is shut down. + \section rig_config Rig Configuration Hardware PTT control diff --git a/fldigi_doxygen/user_src_docs/audio-adjust.txt b/fldigi_doxygen/user_src_docs/audio-adjust.txt new file mode 100644 index 00000000..73846bd6 --- /dev/null +++ b/fldigi_doxygen/user_src_docs/audio-adjust.txt @@ -0,0 +1,188 @@ +/** +\page audio_adjust_page RX/TX Audio Adjustment + +\tableofcontents + +\section rx_audio Receive audio + +Setting the correct hardware, operating system, and fldigi received audio +levels is not difficult, but it is the one setup procedure most often done +incorrectly. The most commonly used sound card devices contain either a +16 or 24 bit analog to digital (a/d) converter. A 16 bit a/d can provide +approximately 90 db of signal conversion. For the 16 bit converter, if the +peak audio signal that the a/d can handle is +/- 1 volt then the minimum +discernable signal (1 bit) will be +/- 30.5 microvolts. If more than a +/- 1 volt +signal is applied to the a/d input then either one of two things may occur, +(1) the audio is clipped, or (2) the audio is wrapped, large positive signals +wrap to large negative signals and vice versa. + +The objective in adjusting the Rx audio is to use the full dynamic range of the +a/d without incurring overdrive. fldigi provides a number of display controls to +assist in setting up the Rx audio. There are two controls that ONLY adjust the +visual appearance of the waterfall and DO NOT effect the a/d or the signal decoders. +These controls are below and to the left of the waterfall, "Upper signal level (dB)", and +"Signal range (dB)". + +
    +\image html win10-fldigi-wf-adjust.png "Waterfall level/range controls" +\image latex win10-fldigi-wf-adjust.png "Waterfall level/range controls" width=1.5in +
    + +Change the waterfall display to the "Scope" view. Do this by pressing the "WF" button twice if +it is currently displaying the waterfall. You can also right click once on that button. That +button acts as a rotary and is left/right click sensitive. The display should show what looks +like an oscilloscope view of the received audio. This is the entire audio signal and not just +the signal that is currently decoded. + +
    +\image html win10-fldigi-signal.png "Scope view" +\image latex win10-fldigi-signal.png "Scope view" width=1.5in +
    + +If your sound card a/d (also referred to as codec) is functioning correctly there +should be no signal offset and the signal will be centered vertically about the y-axis. Set your +transceiver to a portion of the band with digital signals, 14.070 MHz is a good spot. Now adjust +the transceiver audio output and the operating system mixer controls so that the peak signals do +not exceed the upper/lower gray lines on the display. The diamond indicator to the left of the +fldigi AFC button will be colored as follows: +
      +
    • BLACK - no signal, or insufficient Rx audio
    • +
    • GREEN - signals are in the correct range
    • +
    • YELLOW - signals are exceed 75% of maximum, but are less than 90% of maximum
    • +
    • RED - signals exceed 90% of maximum a/d capability - WARNING WILL ROBINSON!
    • +
    +You can then proceed to adjust the waterfall/fft appearance when you have the audio Rx level adjusted correctly. + +The three signal views should be similar to this with the level/range controls set to 0 and 60 respectively. The +waterfall palette used is "default.pal", and the received signal is about 20 dB above the noise floor. +
    + + + + + + +
    + \image html win10-fldigi-wf.png "Waterfall" + \image latex win10-fldigi-wf.png "Waterfal" width=1.5in + + \image html win10-fldigi-fft.png "FFT" + \image latex win10-fldigi-fft.png "FFT" width=1.5in + + \image html win10-fldigi-signal.png "Scope" + \image latex win10-fldigi-signal.png "Scope" width=1.5in +
    +
    +\section rx_win10 Windows Audio Properties +A combination of the Windows operating system and certain audio codecs needs to be accommodated. The codecs +used by devices like the SignaLink-USB, the TS590S, and recent Icom transceivers are identified by the +Windows operating system as "microphone" devices. The Windows mixer controls for that device +are then set to insert about 30 dB of gain in the signal path. To compensate most users simply lower the +transceiver audio output. The result is very poor decoding. The correct procedure is to force the Windows +mixer controls to remove that 30 dB of gain. This procedure is for Windows 10, but is similar on Windows 7, +and Windows 8. + +Right click on the task bar speaker icon and select the "Recording devices" menu item. This will open the +Sound devices dialog: +
    +\image html win10-rec-properties.png "Sound Devices" +\image latex win10-rec-properties.png "Sound Devices" width=3.5in +
    +This is the dialog on my Windows 10 test computer with a SignaLink-USB connected to a USB hub. The +SignaLink-USB shows up as a Microphone USB Audio CODEC. Right click on the device entry and +select Properties. This opens up the Microphone Properties dialog: +
    +\image html win10-mic-properties.png "Microphone Properties" +\image latex win10-mic-properties.png "Microphone Properties" width=3.5in +
    +Select the "Levels" tab and set the level to as close to 0 dB as is available: +
    +\image html win10-mic-levels.png "Microphone Level" +\image latex win10-mic-levels.png "Microphone Level" width=3.5in +
    +Then select the "Advanced" tab and change the type of converter. +
    +\image html win10-mic-advanced.png "Microphone Advanced Tab" +\image latex win10-mic-advanced.png "Microphone Advanced Tab" width=3.5in +
    +Apply and save the changes. The last step is +usually needed to insure that the settings are not lost when the operating system is closed and restarted. + + +\section tx_audio Transmit audio + +Too often you see an overdriven signals on the digital sub-bands; +multiple audio sidebands on PSK, splatter from overdriven MFSK and +RTTY. There is absolutely no reason for a transceiver driven +by fldigi to exhibit this type of performance. You can set up +your computer / transceiver for good solid performance without excessive +drive. +
    + +The "TUNE" button generates a continuous single frequency audio signal +at the exact frequency to which the waterfall cursor has been set. The peak +amplitude of this signal is the peak amplitude of every modem signal +generated by fldigi. None will exceed this value, even the simultaneous +multi-tone modes like Throb. Every modern SSB transmitter uses some automatic +level control ALC for preventing overdrive for SSB voice. A little overdrive +on a voice channel can be tolerated to a degree. In fact, that is what +an analog RF compressor does, overdrive and then subsequent filtering. +But you absolutely cannot tolerate that with the digital modes. Here is the +way to set up your transceiver for a clean signal. I recommend starting out +with a dummy load, but an "off hour" for a band might work just as well if +you do not have a dummy load. +
    + +
      +
    • For Windows users
    • +
        +
      • Set your sound card output level to the minimum on the Windows + mixer
      • +
      +
    • For Linux users
    • +
        +
      • Set your PCM level to about 80%
      • +
      • Set your Transmit Level control for minimum output level.
      • +
      +
    • Set the fldigi transmit attenuator to -3 dB (control to the left of the AFC button)
    • +
    • Set the waterfall cursor to 1000 Hz
    • +
    • Enable the "Tune" mode in fldigi ... you do have CAT or PTT set up ...right?
    • +
    • Make sure your transceiver's speech compression control is OFF
    • +
    • Slowly bring up the Mixer audio out until your rig's ALC just starts + to function (a light blinking or a meter showing this condition).
    • +
    • Reduce the Mixer audio output until the ALC is disabled.
    • +
    • You are now transmitting at maximum output power without distortion.
    • +
    • You can use the fldigi transmit attenuator to make small adjustments + in the output power to compensate for variations in the SSB transmit filter.
    • +
    + +You can use any level below this and be assured that your output signal +will be clean. All digital signals that fldigi generates will be limited to +this peak-to-peak voltage. You should always use the minimum power necessary +to maintain good comms, remember that even if you are clean at 100 W you +signal will be so strong among the QRP signals that it will overpower the +AGC on many receivers that are working another digital station within the +same SSB bandwidth that you are on. You will appreciate this the first +time that you are working a weak PSK DX station and someone blasts through +and captures your AGC. +
    + +You should try the the above adjustments at different audio +frequencies. Transceivers that achieve the SSB filtering with crystal or +mechanical filters will have a considerable amount of variation across the +passband of the filter. This will show up as a varying amount of ALC that is +dependent on the audio frequency. Once you are comfortable with the process +you can very quickly repeat the "Tune" and set the power for the frequency +to which the waterfall is set. The fldigi transmit attenuator control should +have sufficient range to compensate for transmit SSB filter variation. You +do not want to transmit (or receive) near the cutoff frequencies of the SSB +filter. The transceiver filter will introduce both phase and amplitude +distortion over the signal bandwidth. +
    + +\ref tune_page "Return to Top of Page" +
    +\ref main_page "Return to Main Page" + + +*/ diff --git a/fldigi_doxygen/user_src_docs/bpq32.txt b/fldigi_doxygen/user_src_docs/bpq32.txt deleted file mode 100644 index 4eb8d807..00000000 --- a/fldigi_doxygen/user_src_docs/bpq32.txt +++ /dev/null @@ -1,41 +0,0 @@ -/** -\page bpq32_page Using BPQ32 with FLDIGI - -\tableofcontents - -\section sGeneralInfoBpq32 General Information, BPQ32 - -Setting up FLDIGI to use BPQ32 require the use of the KISS I/O port. -see \ref config_io_page page for instructions. - -BPQ32 is beyond the scope of this document. The following links are available -for detailed information about the program and it's use with FLDIGI. - -Documentation:
    -BPQ32 Documents -
    -and for a specific reference to FLDIGI (search for keyword FLDigi) -
    -BPQ32 Documents (FLDIGI) -
    -Installation files:
    -Program and Support Data -
    -\par Note: - The Macintosh Binary located on John's website are for PowerPC systems. - Binaries for Intel systems are available on request by contacting - Robert, KK5VD kk5vd(at)yahoo(dot)com or via John's email listed below. - -BPQ32 is copyrighted © work of John Wiseman, G8BPQ. Any inquires about -the software can be directed to: - -john(dot)wiseman(at)cantab(dot)net - - -
    -\ref bpq32_page "Return to Top of Page" -
    -\ref main_page "Return to Main Page" - -*/ - diff --git a/fldigi_doxygen/user_src_docs/configFSQ.txt b/fldigi_doxygen/user_src_docs/configFSQ.txt index 60c787a9..cd563d6a 100644 --- a/fldigi_doxygen/user_src_docs/configFSQ.txt +++ b/fldigi_doxygen/user_src_docs/configFSQ.txt @@ -63,19 +63,19 @@ are located in the fldigi temp folder: - + - + - + - + diff --git a/fldigi_doxygen/user_src_docs/configIFKP.txt b/fldigi_doxygen/user_src_docs/configIFKP.txt new file mode 100644 index 00000000..4ea113b5 --- /dev/null +++ b/fldigi_doxygen/user_src_docs/configIFKP.txt @@ -0,0 +1,74 @@ +/** +\page ifkp_configuration_page IFKP Configuration + +\tableofcontents +\image html config-ifkp.png "" +\image latex config-ifkp.png "" width=5.0in +
    + +\section IFKP_tx_parameters Tx Parameters + +IFKP transmissions can occur ar 0.5, 1, or 2 times the nominal baud rate. The +baud rate can be selected on the IFKP configuration tab, or by left clicking on the left +most entry on the fldigi main dialog status bar. + +Lower case letters are transmitted within a single symbol length, while +upper case letters require two symbols. You may configure IFKP to always +transmit your own call sign, MYCALL, and the other call, CALLSIGN, using +lower case letters. + +The transmit center frequency can be locked to 1500 Hertz. + +\section IFKP_logging Logging + +Any of the text in the Rx Panel for copy, and saving to a file. Simply +right click on the panel for a pop menu. + +Fldigi's IFKP can save a continuous record of all received date to +an audit log. The heard list can also save a record of all stations +added to the IFKP heard list. These logs are named IFKP_audit_log.txt and +IFKP_heard_log.txt respectively. The logs are never cleared unless the operator +does so using the operating system file handling facilities. Data is +appended to each log as it occurs. These logs are located in the fldigi temp folder: +
    +
    +
    XPC:\\Documents and Settings\\\\fldigi.files\\tempC:\\Documents and Settings\\\\\fldigi.files\\temp
    VistaC:\\Users\\\\fldigi.files\\tempC:\\Users\\\\\fldigi.files\\temp
    Win7C:\\Users\\\\fldigi.files\\tempC:\\Users\\\\\fldigi.files\\temp
    Win8C:\\Users\\\\fldigi.files\\tempC:\\Users\\\\\fldigi.files\\temp
    Linux
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    XPC:\\Documents and Settings\\\\\fldigi.files\\temp
    VistaC:\\Users\\\\\fldigi.files\\temp
    Win7C:\\Users\\\\\fldigi.files\\temp
    Win8C:\\Users\\\\\fldigi.files\\temp
    Linux/home/\/.fldigi/temp
    OS X/home/\/.fldigi/temp
    Unix/home/\/.fldigi/temp
    + + +You can change the name of each log and elect to disable the logging functions. + +
    +\ref ifkp_configuration_page "Return to Top of Page" +
    +\ref main_page "Return to Main Page" + +*/ diff --git a/fldigi_doxygen/user_src_docs/configIO.txt b/fldigi_doxygen/user_src_docs/configIO.txt index f964230e..a6b5fe15 100644 --- a/fldigi_doxygen/user_src_docs/configIO.txt +++ b/fldigi_doxygen/user_src_docs/configIO.txt @@ -19,9 +19,9 @@ I/O configuration panel as seen above allows the user to select one of the IO interfaces. Each of the two interface options are used for different purpose(s). ARQ is selected when the user requires the use of the FLDIGI suite of programs (FLARQ, FLMSG, FLAMP, etc). The KISS interface -is used with Ax25/ARQ networking software. Currently the only -software tested and verified to work with FLDIGI's KISS interface is -BPQ32. See \ref bpq32_page "Using BPQ32 with FLDIGI" +is used with Ax25/ARQ networking software. With the this interconnectivity +multiple host programs are available to leverage this option. See +\ref kiss_host_prgs_page "KISS Host Program(s) and FLDIGI" \par Note: Any changes to the IP Address and/or port numbers requires FLDIGI restart. @@ -59,14 +59,16 @@ To select KISS I/O, mouse click on the [ ] Enable KISS check box. Setting and configuring IP address and ports numbers are described in the ARQ section. -\subsubsection ssDualPort Dual Port +\subsection ssAx25Decode Ax25 Decoding -Since the data exchange protocol is based on UDP/IP (connectionless) loopback -issues can arise if the two programs are hosted on the same machine. By -allowing more then one port number. The loopback condition can be -avoided. Both programs must support dual port for proper communications. +If the data received is using Ax25 protocol enabling this option translates +the protocol into human readable form. Only available when KISS I/O selected. -\subsubsection ssKISSCsma KISS I/O CSMA +\par NOTE: + When actived, only valid ax25 data will be displayed to the receive + panel. No un-squelched random characters will be seen. + +\subsection ssKISSCsma KISS I/O CSMA Selecting this option enables Carrier Sense Multiple Access. Basically in conjunction with KPSQL it monitors for busy signals. When the frequency is @@ -75,14 +77,86 @@ transmitting. This variance allows other CSMA stations time to monitor the frequency in an attempt to prevent/limit packet collisions. Only available when KISS I/O selected. -\subsubsection ssAx25Decode Ax25 Decoding +\subsection ssKISS KISS over IP -If the data received is using Ax25 protocol enabling this option translates -the protocol into human readable form. Only available when KISS I/O selected. +FLDIGI supports KISS data tranfers over two types of IP communications. +UDP (connectionles) and TCP (connection). Each method have is avantages +and disavantages. If you wish to know more about the differences performing +a search on the internet using key words: -\par NOTE: - When actived, only valid ax25 data will be displayed to the receive - panel. No un-squelched random characters will be seen. +"TCP/IP UDP/IP" + +If you are a programmer a good source and free documentation on the subject +can be found by performing a search on these keywords: + +"Beej's Guide to Network Programming" + +\subsubsection ssUDPIP Connectionless UDP/IP [UDP] + +Selecting UDP/IP envoks a connectionless communications path. Host software +must support UDP/IP data transfers in order to use this option. + +\subsubsection ssDualPort Dual Port [DP] + +Used with UDP/IP communications and does not functions with TCP/IP +connections. + +Since the data exchange protocol is based on UDP/IP (connectionless) a +loopback issue can arise if the two programs are hosted on the same machine. +By allowing more then one port number the loopback condition can be avoided. +Host programs must support dual port for proper communications. + +\subsubsection ssTCPIP Connection TCP/IP [TCP] + +TCP connections are far more reliable then UDP since the protocol confirms data +transfers between programs. UDP communications on the same machine is +generally a non issue though. It's normally an issues when distance and +congestion comes into play as packet might timeout in the transfer process. +TCP/IP can resend the data where UDP doesn't. + +Select TCP/IP if the host program supports it. + +\subsubsection ssLISTEN_BIND Listen/Bind + +When selected (checked) with TCP/IP the interface will wait/listen for TCP/IP +connections from the host program. If unchecked the user will press the start +button and FLDIGI will attempt to connect to the host program multiple time +over a ten second period. + +If the connection fails the user should ensure the FLDIGI/host program is +running and configured correctly. + +The Binding is a operating system process for a given IP address and port +number. The binding of an address/port number can only occur once on the same +machine no matter how many programs use the same address and port number. If +you are getting errors as a results of binding it's possible another program +on the same machine has bound the address/port number already. Unchecking this +option may help in this circumstance. Listen/Bind is required if you want +FLDIGI to wait for connections. + +To start the Listening state pressing the start button is required. In the +event the host programs disconnects FLDIGI will return to Listen state unless +the user selects the Stop button. The Start and Stop button is the same button +that is renamed depending the connection state. + +\subsubsection ssAutoConnect Auto Connect [AC] + +Auto connect is used to connect to the host program on start up. Configure +KISS interface as needed then enable (check) the [x] AC option. Press the +[Save] button at the botton of the configuration panel in order for it to +take effect on the next restart. This is a useful option in the event of +power failures. + +\subsubsection ssInhibit7bit Inhibit 7bit Modem + +Selecting this option will disable the warning message reported by FLDIGI +in the event there is a change to a modem type that is not KISS IO compatible. +The invalid modem will be ignored and FLDIGI will remain in the current valid +modem. Deselecting this option allows the operator to approve the modem +change. + +This is an option that should be disabled when FLDIGI is used in an automated +state as FLDIGI will wait indefinitely for a response from the operator. \subsubsection ssBusyChannel Busy Channel @@ -104,7 +178,7 @@ card to audio card connection. KPSQL monitors for differences in the signal strength within the bandpass of the modem. Making it tolerant to AGC variations from the radio. -\subsubsection ssModemSelection Modem Selection Kiss I/O +\subsection ssModemSelection Modem Selection Kiss I/O Use of the KISS I/O places a limit on the number of available modems. These modems support 8 bit transfers. The slowest of these modems have been omitted @@ -113,6 +187,8 @@ MT63 at various baud rates. Any attempt to select a modem not supported FLDIGI will ignore the request. If you are unsure, open the event log under the Help menu and note a message indicating that particular modem is not supported. +See \ref ssInhibit7bit to change the behaviour of this modem check. +
    \image html invalid_kiss_io_modem.png "Invalid Modem for KISS I/O" \image latex invalid_kiss_io_modem.png "Invalid Modem for KISS I/O" width=5.5in diff --git a/fldigi_doxygen/user_src_docs/configOlivia.txt b/fldigi_doxygen/user_src_docs/configOlivia.txt index dae6bb6b..5ddff48f 100644 --- a/fldigi_doxygen/user_src_docs/configOlivia.txt +++ b/fldigi_doxygen/user_src_docs/configOlivia.txt @@ -23,6 +23,12 @@ rate, and excessive latency which is the apparent typing delay caused by the integration period.
    +Each Olivia transmission can start and end with two distinctive tones. These tones +are exactly at the lowest and uppermost tones for the selection of tones and bandwidth. +They can assist the receiving station in tuning the Olivia signal on the waterfall. + +The start/stop tones can be disabled. + See \ref olivia_page "Operating Olivia" for additional information.
    diff --git a/fldigi_doxygen/user_src_docs/configPSK.txt b/fldigi_doxygen/user_src_docs/configPSK.txt index 74082182..ade60207 100644 --- a/fldigi_doxygen/user_src_docs/configPSK.txt +++ b/fldigi_doxygen/user_src_docs/configPSK.txt @@ -43,6 +43,7 @@ This table shows the amount of transmit power used by the pilot tone dB | -20 | -26 | -29 | -32 | -36 | -40 :------:|:----:|:----:|:----:|:----:|:----:|:---- Pwr Lvl | 10% | 5% | 3.5% | 2.5% | 1.6% | 1.0% +
    \ref signal_browser_page "Signal Browser" diff --git a/fldigi_doxygen/user_src_docs/fldigi_configuration.txt b/fldigi_doxygen/user_src_docs/fldigi_configuration.txt index 844c2d6f..1882e18a 100644 --- a/fldigi_doxygen/user_src_docs/fldigi_configuration.txt +++ b/fldigi_doxygen/user_src_docs/fldigi_configuration.txt @@ -23,6 +23,7 @@ You should initially configure the following:
  • \subpage operator_configuration_page
  • \subpage sound_card_configuration_page
  • \subpage rig_control_page
  • +
  • \subpage audio_adjust_page
  • \subpage new_installation_page
  • \subpage config_io_page
  • @@ -77,6 +78,7 @@ but the defaults should be satisfactory for most users.
  • \subpage domino_ex_configuration_page
  • \subpage feld_hell_configuration_page
  • \subpage fsq_configuration_page
  • +
  • \subpage ifkp_configuration_page
  • \subpage id_configuration_page
  • \subpage miscellaneous_configuration_page
  • \subpage mt63_configuration_page
  • diff --git a/fldigi_doxygen/user_src_docs/fldigi_modems.txt b/fldigi_doxygen/user_src_docs/fldigi_modems.txt index 8c1be970..39cfedc2 100644 --- a/fldigi_doxygen/user_src_docs/fldigi_modems.txt +++ b/fldigi_doxygen/user_src_docs/fldigi_modems.txt @@ -8,6 +8,7 @@
  • \subpage domino_ex_page
  • \subpage feld_hell_page
  • \subpage fsq_page
  • +
  • \subpage ifkp_page
  • \subpage mfsk_page
  • \subpage mt63_page
  • \subpage navtex_and_sitorb_page
  • @@ -16,7 +17,6 @@
  • \subpage rtty_page
  • \subpage thor_page
  • \subpage throb_page
  • -
  • \subpage tune_page
  • \subpage wefax_page
  • \subpage wwv_tx_mode
  • \subpage mode_table_page
  • diff --git a/fldigi_doxygen/user_src_docs/fldigi_operating.txt b/fldigi_doxygen/user_src_docs/fldigi_operating.txt index 2e53909e..4effd73e 100644 --- a/fldigi_doxygen/user_src_docs/fldigi_operating.txt +++ b/fldigi_doxygen/user_src_docs/fldigi_operating.txt @@ -10,6 +10,7 @@
  • \subpage fft_scan_page
  • \subpage frequency_analyzer_page
  • \subpage keyboard_operation_page
  • +
  • \subpage xchar_page
  • \subpage kml_page
  • \subpage menus_page
  • \subpage mouse_and_keyboard_shortcuts_page
  • diff --git a/fldigi_doxygen/user_src_docs/index.txt b/fldigi_doxygen/user_src_docs/index.txt index 514b6151..f7d5c7dd 100644 --- a/fldigi_doxygen/user_src_docs/index.txt +++ b/fldigi_doxygen/user_src_docs/index.txt @@ -18,7 +18,7 @@ /*! -\mainpage FLDIGI Users Manual - Version 3.22 +\mainpage FLDIGI Users Manual - Version 3.23.10 \anchor main_page
    diff --git a/fldigi_doxygen/user_src_docs/index_order.txt b/fldigi_doxygen/user_src_docs/index_order.txt index ba5ca7a3..44afdbbd 100644 --- a/fldigi_doxygen/user_src_docs/index_order.txt +++ b/fldigi_doxygen/user_src_docs/index_order.txt @@ -1,8 +1,10 @@ fldigi_configuration.txt fldigi_developer.txt fldigi_logging.txt \ fldigi_macros.txt fldigi_modems.txt fldigi_operating.txt \ New-Install.txt thumb_drive.txt colorsandfonts.txt \ +audio-adjust.txt \ configcallsigndb.txt configContestia.txt configCW.txt \ -configDomEX.txt configFSQ.txt configFH.txt ConfigID.txt ConfigMisc.txt \ +configDomEX.txt configFSQ.txt configFH.txt ConfigID.txt \ +configIFKP.txt ConfigMisc.txt \ configMT63.txt configOlivia.txt ConfigOperator.txt configPSK.txt \ configRTTY.txt configThor.txt ConfigUI-browser.txt \ ConfigUI-contest.txt ConfigUI-general.txt ConfigUI-logging.txt \ @@ -10,14 +12,15 @@ ConfigUI-macros.txt ConfigUI-WF-controls.txt ConfigWaterfall.txt \ SoundCardSetup.txt Contest-How-To.txt cabrilloreporter.txt \ Logbook.txt LogExports.txt working_logs.txt Macros.txt \ InlineMacroTags.txt atMacroTags.txt advanced_qsy.txt execmacro.txt CW.txt \ -DominoEX.txt hell.txt Contestia.txt MFSK.txt MT63.txt FSQ.txt \ +DominoEX.txt hell.txt Contestia.txt MFSK.txt MT63.txt \ +FSQ.txt IFKP.txt \ Navtex.txt psk.txt Olivia.txt RTTYFSK.txt Thor.txt \ -throb.txt tune.txt WEFAX.txt WWV-xmt.txt FrequencyAnalysis.txt \ +throb.txt WEFAX.txt WWV-xmt.txt FrequencyAnalysis.txt \ DigiscopeDisplay.txt DigiWWV.txt map.txt MousingKeyboardShortcuts.txt \ Multiples.txt Notifier.txt OperatingControls.txt RST-RSQ.txt \ Spotter.txt Synop.txt TransceiverControl.txt UTF8.txt \ pskmail_config.txt PskViewer.txt DXCC_list.txt \ -KeyboardAndKeys.txt KML.txt Installing.txt WindowsOS.txt \ +KeyboardAndKeys.txt xchar.txt KML.txt Installing.txt WindowsOS.txt \ Wizard.txt Menus.txt ModeTable.txt CWkeying.txt PseudoFSK.txt \ w5zit-interface.txt rigxml.txt commandline.txt \ buildinfo.txt xmlrpc-control.txt parseUALR.txt ualr-telnet.txt \ diff --git a/fldigi_doxygen/user_src_docs/kiss_host_prgs.txt b/fldigi_doxygen/user_src_docs/kiss_host_prgs.txt new file mode 100644 index 00000000..573f30dc --- /dev/null +++ b/fldigi_doxygen/user_src_docs/kiss_host_prgs.txt @@ -0,0 +1,70 @@ +/** +\page kiss_host_prgs_page Using KISS compatible programs with FLDIGI + +\tableofcontents + +The below listed host programs make use of FLDIGI extended KISS TNC hardware +commands. While any KISS over IP compatible program should work, only the +following have been tested by the developers of FLDIGI. + +Setting up FLDIGI to use KISS require the use of the KISS I/O port. +see \ref config_io_page page for instructions. + + +\section sGeneralInfoBpq32 BPQ32 + +BPQ32 is beyond the scope of this document. The following links are available +for detailed information about the program and it's use with FLDIGI. + +Documentation:
    +BPQ32 Documents +
    +and for a specific reference to FLDIGI (search for keyword FLDigi) +
    +BPQ32 Documents (FLDIGI) +
    +Installation files:
    +Program and Support Data +
    +\par Note: + The Macintosh Binary located on John's website are for PowerPC systems. + Binaries for Intel systems are available on request by contacting + Robert, KK5VD kk5vd(at)yahoo(dot)com or via John's email listed below. + +Any inquires about the software can be directed to: + +John Wiseman, G8BPQ +john(dot)wiseman(at)cantab(dot)net + +\section sGeneralInfoUIChat UIChat + +For those who have used FLDIGI's FSQ interface, Mitch Winkle AB4MW has created +a Java application that mimics FSQ interface while allowing the operator to +use any of FLDIGI 8 bit KISS compatible modems. + +Mitch's Blog: +https://plus.google.com/communities/110418910579764092090 + +Program and Source code: +https://sourceforge.net/projects/uichat/ + + +\section sGeneralInfoYAAC YAAC - "Yet Another APRS Client" + +Andrew Pavlin, KA2DDO has created a APRS client and Internet gateway +package. Details about this software can be found in the following links. + +YAAC website: +http://www.ka2ddo.org/ka2ddo/YAAC.html + +YAAC source code: +https://sourceforge.net/projects/yetanotheraprsc/ + + +
    +\ref kiss_host_prgs_page "Return to Top of Page" +
    +\ref main_page "Return to Main Page" + +*/ + diff --git a/fldigi_doxygen/user_src_docs/kiss_io_command.txt b/fldigi_doxygen/user_src_docs/kiss_io_command.txt index ea562bbe..fdd4d3ea 100644 --- a/fldigi_doxygen/user_src_docs/kiss_io_command.txt +++ b/fldigi_doxygen/user_src_docs/kiss_io_command.txt @@ -60,6 +60,7 @@ Command | Use SQLS:\<0-100\> | Set SQL Level (percent) TRXSBCAST:\ | Enable/disable TX/RX state change broadcast (default: OFF) TXBEBCAST:\ | Enable/disable TX buffer empty broadcast (default: OFF) +TXLOCK:\ | Enable/disable TX waterfall position lock. WFF:\ | Move TXRX cursor to frequency on waterfall. \verbatim @@ -105,8 +106,9 @@ Command / Return Status | Use SQLP: FLDIGI returns SQLP:\<0-100\> | Current Symbol Quality Level (Currently Not returning valid data) SQLS: FLDIGI returns SQLS:\<0-100\> | Set SQL Level Query (percent) TNC: FLDIGI returns TNC:FLDIGI \ | Returns the version number of FLDIGI -TRXS: FLDIGI returns TRXS:\ | Returns the current RX/TX state of FLDIGI +TRXS: FLDIGI returns TRXS:\ | Return the current RX/TX state of FLDIGI TXBUF: FLDIGI returns TXBUF:\ | Return the number of byte in the transmit queue +TXLOCK: FLDIGI returns TXLOCK:\ | Return TX waterfall position lock state. WFBW: FLDIGI returns WFBW:\,\ | Return the active waterfall bandwidth WFF: FLDIGI returns WFF:\ | Current modem position on waterfall (center) diff --git a/fldigi_doxygen/user_src_docs/psk.txt b/fldigi_doxygen/user_src_docs/psk.txt index 23751225..66d6ce64 100644 --- a/fldigi_doxygen/user_src_docs/psk.txt +++ b/fldigi_doxygen/user_src_docs/psk.txt @@ -183,7 +183,7 @@ better decoding than CW. Setting up for a good clean on air signal that will receive the accolades of your QSO partners is easy. Follow the instructions on using the -\ref tune_page "Tune" button and you will have a clean on signal. +\ref audio_adjust_page "Tune" button and you will have a clean on signal.
    Good reception of PSK signals requires that the demodulator be phase locked diff --git a/fldigi_doxygen/user_src_docs/rigxml.txt b/fldigi_doxygen/user_src_docs/rigxml.txt index 9c9bd075..441c342a 100644 --- a/fldigi_doxygen/user_src_docs/rigxml.txt +++ b/fldigi_doxygen/user_src_docs/rigxml.txt @@ -8,283 +8,368 @@ This document describes the contents of the rig definition file \"rig.xml\". A number of transceivers have rig definition files written and tested which you may use. These are found in the xmls directory on this -site: xml archives. +site: xml archives. You will find subdirectories by manufacturer which contain files named by rig type, ie: TS-850.xml. If you create, test and verify the proper operation for a transceiver not yet posted please share that with -others by sending it as an attachment to w1hkj@w1hkj.com and I will +others by sending it as an attachment to feedback [at] w1hkj [dot] com and I will post it on the web site. You are encouraged to study the various rig definition files to learn more about how they are organized. Comments are contained within the tag pair: - -\ --\> -
    - +
    +\
    + 0,0; 255,100 
    +
    +
    +
    +  0,0; 16,1; 32,4; 48,7;
    +  64,12; 80,18; 96,24; 112,32;
    +  128,40; 144,50; 160,61; 176,73; 
    +  192,85; 208,100
    +
    +
    +
    + 0,0; 255,100 
    +
    + +The query and respective responses are coded as any other command/reply pair: + +For the FT-950: + +
    +
    +  SMETER
    +  7
    +  RM1
    +  
    +    DECIMAL
    +    3
    +  
    +  ;
    +
    +
    +
    +  GET_SMETER
    +  4
    +  RM1;
    +  SMETER
    +
    +
    +
    +  PWRMETER
    +  7
    +  RM5
    +  
    +    DECIMAL
    +    3
    +  
    +  ;
    +
    +
    +
    +  GET_PWRMETER
    +  4
    +  RM5;
    +  PWRMETER
    +
    +
    + +and for the IC-706MkIIG: + +
    +
    +    SMETER
    +    10
    +    FE FE E0 58 15 02
    +    
    +        BCD
    +         3 
    +         255 
    +         0 
    +         1 
    +     
    +    FD
    +
    +
    +
    +    GET SMETER
    +    7
    +    FE FE 58 E0 15 02 FD
    +    SMETER
    +
    +
    + +\section notch_control Notch Control + +The transceiver manual notch can be both read and controlled using rigCAT. + +There are a few requirements that may not be met by all transceivers. +
    +
      +
    • it must support a CAT manual notch on/off string
    • +
    • it must support a CAT manual notch value string
    • +
    • the conversion between notch audio frequency and the CAT value must +be bilateral.
    • +
    +
    +Here is an example for the FT-950: + +
    +
    +  1,10; 300,3000;
    +
    +
    +
    +    SET_NOTCH_ON
    +    8
    +    BP00001;
    +
    +
    +
    +    SET_NOTCH_OFF
    +    8
    +    BP00000;
    +
    +
    +
    +    SET_NOTCH_VAL
    +    8
    +    BP01
    +    
    +        DECIMAL
    +        3
    +    
    +    ;
    +
    +
    +
    +  NOTCH_ON
    +  8
    +  BP00001;
    +
    +
    +
    +  GET_NOTCH_ON
    +  5
    +  BP00;
    +  NOTCH_ON
    +
    +
    +
    +  NOTCH
    +  8
    +  BP01
    +  
    +    DECIMAL
    +    3
    +  
    +  ;
    +
    +
    +
    +  GET_NOTCH
    +  5
    +  BP01;
    +  NOTCH
    +
    +
    + +The notch is controlled from fldigi using the alt-ctl-left-click on the waterfall. +The same keyboard-mouse combination is used to both set and clear the notch. Point +the cursor to an offending signal, and then use the keyboard-mouse combination to +set the manual notch at that frequency. Repeat the keyboard-mouse combination anywhere +in the waterfall to clear the notch. The SET notch is indicated by a dashed vertical +line on the waterfall display at the audio frequency being notched. You should also +see a pronounced reduction in signal at that point. fldigi will also annunciate any +transceiver changes made to the manual notch. + +\section power_level Power Level Control + +rigCAT can control the power level of the transceiver if that is a supported CAT command. +The definitions for the power level are similar to the notch in that the conversion +should be bilateral. + +Another example using the FT-950 transceiver: + +
    +
    +  0,0; 100,100;
    +
    +
    +
    +  PWRLEVEL
    +  6
    +  PC
    +  
    +    DECIMAL
    +    3
    +  
    +  ;
    +
    +
    +
    +  GET_PWRLEVEL
    +  3
    +  PC;
    +  PWRLEVEL
    +
    +
    +
    +  SET_PWRLEVEL
    +    6
    +    PC
    +    
    +        DECIMAL
    +        3
    +    
    +    ;
    +
    +
    + +The rigCAT controls for +
      +
    • Transceiver-Mode
    • +
    • Transceiver-Bandwidth
    • +
    • Smeter
    • +
    • Power-Meter and
    • +
    • Power-Level
    • +
    +all share a common space on the main fldigi display. +
    +\image html rigcat-1.png "Mode/Bandwidth controls" +\image latex rigcat-1.png "Mode/Bandwidth controls" width=2.0in +
    +\image html rigcat-2.png "S-meter" +\image latex rigcat-2.png "S-meter" width=2.0in +
    +\image html rigcat-3.png "Power-meter" +\image latex rigcat-3.png "Power-meter" width=2.0in +
    +\image html rigcat-4.png "Power Level" +\image latex rigcat-4.png "Power Level" width=2.0in +
    +
    +The transition between Mode/Bandwidth and the other control/displays is +made using the button just to the right of the bandwidth control. + +The transition from either S-meter or Power-meter to the Power Level is +make by left clicking on the S-meter or Power-meter. + +\section debugging Debugging + +To assist in debugging an xml file you may place the following statement +within the body of the ... pair. + +true + +fldigi will then record critical events as they occur during the execution +of the rigCAT loop. Remove the debug statement from the xml when the +file has been proven and before publishing. + +You can test an xml to observe the CAT send sequences by inhibiting the +actual connection to the serial port. + +true/false - default false + +The serial i/o events are normally recorded as a sequence of HEX values. This +behavior can be changed to record the events as a string of ASCII characters. + +true/false - default false + +You can use the xml remarks brackets +
    +\ no ':' after field name
    +	if (!p1 || !p2 || p2 < p1) {
    +		return 0; // bad ADIF specifier ---> no ':' after field name
    +	}
     
     	p1++;
     	int fldsize = 0;
    @@ -195,70 +205,45 @@ void cAdifIO::fillfield (int fieldnum, char *buff)
     		}
     		p1++;
     	}
    -	if ((fieldnum == TIME_ON || fieldnum == TIME_OFF) && fldsize < 6) {
    -		string tmp = "";
    -		tmp.assign(p2+1, fldsize);
    -		while (tmp.length() < 6) tmp += '0';
    -		adifqso->putField(fieldnum, tmp.c_str(), 6);
    -	} else
    -		adifqso->putField (fieldnum, p2+1, fldsize);
    -}
     
    -static void write_rxtext(const char *s)
    -{
    -	ReceiveText->addstr(s);
    +	string tmp = "";
    +	tmp.assign(p2+1, fldsize);
    +
    +// added to disallow very large corrupted adif fields
    +	if (fldsize > fields[fieldnum].fsize) {
    +		string bfr = buff;
    +		tmp.erase(fields[fieldnum].fsize);
    +		static char szmsg[1000];
    +		snprintf(szmsg, sizeof(szmsg), 
    +			"In record # %d, <%s, too large, saving first %d characters\n", 
    +			recnbr+1,
    +			bfr.substr(0, (int)(p2+1 - buff)).c_str(),
    +			fields[fieldnum].fsize );
    +		read_errors.append(szmsg);
    +		num_read_errors++;
    +	}
    +
    +	if ((fieldnum == TIME_ON || fieldnum == TIME_OFF) && fldsize < 6)
    +		while (tmp.length() < 6) tmp += '0';
    +
    +	adifqso->putField( fieldnum, tmp.c_str(), tmp.length() );
    +
    +	return p2 + fldsize + 1;
     }
     
     void cAdifIO::do_readfile(const char *fname, cQsoDb *db)
     {
    -	long filesize = 0;
    -	char *buff;
     	int found;
     	static char szmsg[200];
     
    +	read_errors.clear();
    +	num_read_errors = 0;
    +
     // open the adif file
    -	FILE *adiFile = fopen (fname, "r");
    +	FILE *adiFile = fopen (fname, "rb");
     
    -	if (adiFile == NULL)
    -		return;
    -// determine its size for buffer creation
    -	fseek (adiFile, 0, SEEK_END);
    -	filesize = ftell (adiFile);
    -
    -	if (filesize == 0) {
    -		snprintf(szmsg, sizeof(szmsg), _("Empty ADIF logbook file %s"), fname);
    -		REQ(write_rxtext, "\n");
    -		REQ(write_rxtext, szmsg);
    -		REQ(write_rxtext, "\n");
    -		LOG_ERROR("%s", szmsg);
    -		return;
    -	}
    -
    -	buff = new char[filesize + 1];
    -
    -// read the entire file into the buffer
    -
    -	fseek (adiFile, 0, SEEK_SET);
    -	int retval = fread (buff, filesize, 1, adiFile);
    -	fclose (adiFile);
    -	if (retval != 1) {
    -		snprintf(szmsg, sizeof(szmsg), _("Error reading %s"), fname);
    -		REQ(write_rxtext, "\n");
    -		REQ(write_rxtext, szmsg);
    -		REQ(write_rxtext, "\n");
    -		LOG_ERROR("%s", szmsg);
    -		return;
    -	}
    -
    -// relaxed file integrity test to all importing from non conforming log programs
    -	if (strcasestr(buff, "clearDatabase();
    +	if (adiFile == NULL) {
    +		LOG_ERROR("Could not open %s", fname);
     		return;
     	}
     
    @@ -269,40 +254,73 @@ void cAdifIO::do_readfile(const char *fname, cQsoDb *db)
     	clock_gettime(CLOCK_REALTIME, &t0);
     #endif
     
    -	char *p1 = buff, *p2;
    -	if (*p1 != '<') { // yes, skip over header to start of records
    -		p1 = strchr(buff, '<');
    -		while (strncasecmp (p1+1,"EOH>", 4) != 0) {
    -			p1 = strchr(p1+1, '<'); // find next <> field
    -		}
    -		if (!p1) {
    -			delete [] buff;
    -			snprintf(szmsg, sizeof(szmsg), "Corrupt logbook file: %s", fname);
    -			REQ(write_rxtext, "\n");
    -			REQ(write_rxtext, szmsg);
    -			REQ(write_rxtext, "\n");
    -			LOG_ERROR("%s", szmsg);
    -			return;	 // must not be an ADIF compliant file
    -		}
    -		p1 += 1;
    +	char buff[16384];
    +	string sbuff;
    +	memset(buff, 0, 16384);
    +	int retnbr = fread(buff, 1, 16384, adiFile);
    +	if (retnbr) sbuff.assign(buff, retnbr);
    +
    +	size_t p = sbuff.find("");
    +	if (p == std::string::npos) p = sbuff.find("");
    +	if (p == std::string::npos) {
    +		return;
     	}
     
    -	p2 = strchr(p1,'<'); // find first ADIF specifier
    -//	adifqso.clearRec();
    +	sbuff.erase(0, p + 5);
    +// skip over cr/lf pairs
    +	while (sbuff.length() && (sbuff[0] == '\r' || sbuff[0] == '\n'))
    +		sbuff.erase(0,1);
     
    -	adifqso = 0;
    -	while (p2) {
    -		found = findfield(p2+1);
    -		if (found > -1) {
    -			if (!adifqso) adifqso = db->newrec(); // need new record in db
    -			fillfield (found, p2+1);
    -		} else if (found == -1) { //  reached;
    -			adifqso = 0;
    -		}
    -		p1 = p2 + 1;
    -		p2 = strchr(p1,'<');
    +	p = sbuff.find("");
    +	if (p == std::string::npos) p = sbuff.find("");
    +
    +	while (!feof(adiFile) && (p == std::string::npos)) {
    +		retnbr = fread(buff, 1, 16384, adiFile);
    +		if (retnbr) sbuff.append(buff, retnbr);
    +		p = sbuff.find("");
    +		if (p == std::string::npos) p = sbuff.find("");
    +	}
    +	if (p == std::string::npos) return;
    +
    +	char *ptr = 0, *ptr2 = 0;
    +	int recnbr = 0;
    +
    +	while (p != std::string::npos) {
    +
    +		ptr = strchr((char *)sbuff.c_str(),'<');
    +
    +		adifqso = 0;
    +		while (ptr) {
    +			found = findfield(ptr+1);
    +			if (found > -1) {
    +				if (!adifqso) adifqso = db->newrec(); // need new record in db
    +				ptr2 = fillfield (recnbr, found, ptr+1);
    +			} else if (found == -1) { //  reached;
    +				break;
    +			} else {
    +				ptr2 = ptr + 1;
    +			}
    +			if ((ptr2) > 0 && (unsigned)(ptr2 - ptr) <= p)
    +				ptr = strchr(ptr2,'<');
    +			else
    +				break; // corrupt record
    +		}
    +		recnbr++;
    +
    +		sbuff.erase(0, p + 5);
    +		while (sbuff.length() && (sbuff[0] == '\r' || sbuff[0] == '\n'))
    +			sbuff.erase(0,1);
    +
    +		p = sbuff.find("");
    +		if (p == std::string::npos) p = sbuff.find("");
    +
    +		while (!feof(adiFile) && (p == std::string::npos)) {
    +			retnbr = fread(buff, 1, 16384, adiFile);
    +			if (retnbr) sbuff.append(buff, retnbr);
    +			p = sbuff.find("");
    +			if (p == std::string::npos) p = sbuff.find("");
    +		}
     	}
    -	delete [] buff;
     
     #ifdef _POSIX_MONOTONIC_CLOCK
     	clock_gettime(CLOCK_MONOTONIC, &t1);
    @@ -313,17 +331,30 @@ void cAdifIO::do_readfile(const char *fname, cQsoDb *db)
     	t0 = t1 - t0;
     	float t = (t0.tv_sec + t0.tv_nsec/1e9);
     
    -	snprintf(szmsg, sizeof(szmsg), "\
    -Loaded logbook: %s\n\
    -                %d records in %4.2f seconds",
    -fname, db->nbrRecs(), t);
    -	REQ(write_rxtext, "\n");
    -	REQ(write_rxtext, szmsg);
    -	REQ(write_rxtext, "\n");
    -	LOG_INFO("%s", szmsg);
    +	if (!feof(adiFile))
    +		snprintf(szmsg, sizeof(szmsg), "\
    +ERROR reading logbook %s\n\
    +      read %d records in %4.2f seconds", fname, db->nbrRecs(), t);
    +	else {
    +		snprintf(szmsg, sizeof(szmsg), "\
    +Loaded logbook %s\n\
    +       read %d records in %4.2f seconds\n", fname, db->nbrRecs(), t);
    +		LOG_INFO("%s", szmsg);
    +		if (num_read_errors) {
    +			read_errors.insert(0, szmsg);
    +			snprintf(szmsg, sizeof(szmsg),
    +				"Corrected %d errors\nSave logbook and then reload",
    +				num_read_errors);
    +			read_errors.append(szmsg);
    +			REQ(write_rxtext, read_errors.c_str());
    +		} else
    +			REQ(write_rxtext, szmsg);
    +	}
     
     	if (db == &qsodb)
     		REQ(adif_read_OK);
    +
    +	fclose(adiFile);
     }
     
     static const char *adifmt = "<%s:%d>";
    @@ -346,7 +377,7 @@ int cAdifIO::writeFile (const char *fname, cQsoDb *db)
     // open the adif file
     	cQsoRec *rec;
     	string sFld;
    -	adiFile = fopen (fname, "w");
    +	adiFile = fopen (fname, "wb");
     	if (!adiFile)
     		return 1;
     
    @@ -410,7 +441,7 @@ static cQsoDb *adif_db;
     
     static cAdifIO *adifIO = 0;
     
    -void cAdifIO::readFile (const char *fname, cQsoDb *db) 
    +void cAdifIO::readFile (const char *fname, cQsoDb *db)
     {
     	ENSURE_THREAD(FLMAIN_TID);
     
    @@ -483,7 +514,7 @@ void cAdifIO::do_writelog()
     	Ccrc16 checksum;
     	string s_checksum;
     
    -	adiFile = fopen (adif_file_name.c_str(), "w");
    +	adiFile = fopen (adif_file_name.c_str(), "wb");
     
     	if (!adiFile) {
     		LOG_ERROR("Cannot write to %s", adif_file_name.c_str());
    @@ -591,12 +622,14 @@ void ADIF_RW_close(void)
     
     	pthread_mutex_lock(&ADIF_RW_mutex);
     	ADIF_RW_EXIT = true;
    +	LOG_INFO("%s", "Exiting ADIF_RW_thread");
     	pthread_cond_signal(&ADIF_RW_cond);
     	pthread_mutex_unlock(&ADIF_RW_mutex);
     
     	pthread_join(*ADIF_RW_thread, NULL);
     	delete ADIF_RW_thread;
     	ADIF_RW_thread = 0;
    +	LOG_INFO("%s", "ADIF_RW_thread closed");
     }
     
     static void ADIF_RW_init()
    diff --git a/src/logbook/logsupport.cxx b/src/logbook/logsupport.cxx
    index 0134168c..e014bcc5 100644
    --- a/src/logbook/logsupport.cxx
    +++ b/src/logbook/logsupport.cxx
    @@ -144,8 +144,9 @@ void Export_CSV()
     	filters.append("\n");
     #endif
     	const char* p = FSEL::saveas( title.c_str(), filters.c_str(), "export.csv");
    -	if (!p)
    -		return;
    +
    +	if (!p) return;
    +	if (!*p) return;
     
     	for (int i = 0; i < chkExportBrowser->FLTK_nitems(); i++) {
     		if (chkExportBrowser->checked(i + 1)) {
    @@ -170,8 +171,9 @@ void Export_TXT()
     	filters.append("\n");
     #endif
     	const char* p = FSEL::saveas( title.c_str(), filters.c_str(), "export.txt");
    -	if (!p)
    -		return;
    +
    +	if (!p) return;
    +	if (!*p) return;
     
     	for (int i = 0; i < chkExportBrowser->FLTK_nitems(); i++) {
     		if (chkExportBrowser->checked(i + 1)) {
    @@ -201,8 +203,8 @@ void Export_ADIF()
     	defname.assign("export.").append(ADIF_SUFFIX);
     	const char* p = FSEL::saveas( title.c_str(), filters.c_str(), defname.c_str());
     
    -	if (!p)
    -		return;
    +	if (!p) return;
    +	if (!*p) return;
     
     	for (int i = 0; i < chkExportBrowser->FLTK_nitems(); i++) {
     		if (chkExportBrowser->checked(i + 1)) {
    @@ -276,7 +278,7 @@ void cb_mnuOpenLogbook(Fl_Menu_* m, void* d)
     {
     	string title = _("Open logbook file");
     	string filter;
    -	filter.assign("ADIF file\t*.").append(ADIF_SUFFIX);
    +	filter.assign("ADIF file\t*.{adi,adif}");
     #ifdef __APPLE__
     	filter.append("\n");
     #endif
    @@ -285,19 +287,20 @@ void cb_mnuOpenLogbook(Fl_Menu_* m, void* d)
     	deffilename.append(fl_filename_name(logbook_filename.c_str()));
     
     	const char* p = FSEL::select( title.c_str(), filter.c_str(), deffilename.c_str());
    +	if (!p) return;
    +	if (!*p) return;
     
    -	if (p) {
    -		saveLogbook();
    -		qsodb.deleteRecs();
    +	saveLogbook();
    +	qsodb.deleteRecs();
     
    -		logbook_filename = p;
    -		progdefaults.logbookfilename = logbook_filename;
    -		progdefaults.changed = true;
    +	logbook_filename = p;
    +	progdefaults.logbookfilename = logbook_filename;
    +	progdefaults.changed = true;
    +
    +	adifFile.readFile (logbook_filename.c_str(), &qsodb);
    +	dlgLogbook->label(fl_filename_name(logbook_filename.c_str()));
    +	qsodb.isdirty(0);
     
    -		adifFile.readFile (logbook_filename.c_str(), &qsodb);
    -		dlgLogbook->label(fl_filename_name(logbook_filename.c_str()));
    -		qsodb.isdirty(0);
    -	}
     }
     
     void cb_mnuSaveLogbook(Fl_Menu_*m, void* d) {
    @@ -310,25 +313,27 @@ void cb_mnuSaveLogbook(Fl_Menu_*m, void* d) {
     	std::string deffilename = LogsDir;
     	deffilename.append(fl_filename_name(logbook_filename.c_str()));
     
    -	const char* p = FSEL::select( title.c_str(), filter.c_str(), deffilename.c_str());
    +	const char* p = FSEL::saveas( title.c_str(), filter.c_str(), deffilename.c_str());
     
    -	if (p) {
    -		logbook_filename = p;
    -		if (logbook_filename.find("." ADIF_SUFFIX) == string::npos)
    -			logbook_filename.append("." ADIF_SUFFIX);
    +	if (!p) return;
    +	if (!*p) return;
     
    -		progdefaults.logbookfilename = logbook_filename;
    -		progdefaults.changed = true;
    +	logbook_filename = p;
    +	if (logbook_filename.find("." ADIF_SUFFIX) == string::npos)
    +		logbook_filename.append("." ADIF_SUFFIX);
     
    -		dlgLogbook->label(fl_filename_name(logbook_filename.c_str()));
    +	progdefaults.logbookfilename = logbook_filename;
    +	progdefaults.changed = true;
     
    -		cQsoDb::reverse = false;
    -		qsodb.SortByDate(progdefaults.sort_date_time_off);
    +	dlgLogbook->label(fl_filename_name(logbook_filename.c_str()));
    +
    +	cQsoDb::reverse = false;
    +	qsodb.SortByDate(progdefaults.sort_date_time_off);
    +
    +	qsodb.isdirty(0);
    +	restore_sort();
    +	adifFile.writeLog (logbook_filename.c_str(), &qsodb);
     
    -		qsodb.isdirty(0);
    -		restore_sort();
    -		adifFile.writeLog (logbook_filename.c_str(), &qsodb);
    -	}
     }
     
     int comparerecs (const void *rp1, const void *rp2) { // rp1 needle, rp2 haystack
    @@ -503,16 +508,18 @@ void merge_recs( cQsoDb *db, cQsoDb *mrgdb ) // (haystack, needle)
     }
     
     void cb_mnuMergeADIF_log(Fl_Menu_* m, void* d) {
    -	const char* p = FSEL::select(_("Merge ADIF file"), "ADIF\t*." ADIF_SUFFIX, LogsDir.c_str());
    +	const char* p = FSEL::select(_("Merge ADIF file"), "ADIF\t*.{adi,adif}", LogsDir.c_str());
     	Fl::wait();
     	fl_digi_main->redraw();
     	Fl::awake();
    -	if (p) {
    -		cQsoDb *mrgdb = new cQsoDb;
    -		adifFile.do_readfile (p, mrgdb);
    -		merge_recs(&qsodb, mrgdb);
    -		delete mrgdb;
    -	}
    +	if (!p) return;
    +	if (!*p) return;
    +
    +	cQsoDb *mrgdb = new cQsoDb;
    +	adifFile.do_readfile (p, mrgdb);
    +	merge_recs(&qsodb, mrgdb);
    +	delete mrgdb;
    +
     }
     
     void cb_export_date_select() {
    @@ -1479,8 +1486,9 @@ void WriteCabrillo()
     	string strContest = "";
     
     	const char* p = FSEL::saveas( title.c_str(), filters.c_str(), "contest.txt");
    -	if (!p)
    -		return;
    +
    +	if (!p) return;
    +	if (!*p) return;
     
     	for (int i = 0; i < chkCabBrowser->FLTK_nitems(); i++) {
     		if (chkCabBrowser->checked(i + 1)) {
    diff --git a/src/logbook/lookupcall.cxx b/src/logbook/lookupcall.cxx
    index 96b1b72e..b4c220de 100644
    --- a/src/logbook/lookupcall.cxx
    +++ b/src/logbook/lookupcall.cxx
    @@ -440,7 +440,9 @@ void QRZ_CD_query()
     		srch[i] = toupper(srch[i]);
     
     	string notes;
    -	notes.assign(inpNotes->value());
    +	if (!progdefaults.clear_notes) notes.assign(inpNotes->value());
    +	else notes.clear();
    +
     	if( qCall->FindRecord( srch ) == 1) {
     		lookup_fname = qCall->GetFname();
     		camel_case(lookup_fname);
    @@ -530,7 +532,9 @@ void QRZAlert()
     		qrzerror.clear();
     	}
     	string notes;
    -	notes.assign(inpNotes->value());
    +	if (!progdefaults.clear_notes) notes.assign(inpNotes->value());
    +	else notes.clear();
    +
     	if (!qrznote.empty()) notes.append("\n").append(qrznote);
     	inpNotes->value(notes.c_str());
     }
    @@ -580,7 +584,9 @@ void QRZquery()
     			}
     
     			string notes;
    -			notes.assign(inpNotes->value());
    +			if (!progdefaults.clear_notes) notes.assign(inpNotes->value());
    +			else notes.clear();
    +
     			if (progdefaults.notes_address) {
     				if (!notes.empty()) notes.append("\n");
     				notes.append(lookup_fname).append(" ").append(lookup_name).append("\n");
    @@ -653,7 +659,9 @@ void parse_callook(string& xmlpage)
     	}
     
     	string notes;
    -	notes.assign(inpNotes->value());
    +	if (!progdefaults.clear_notes) notes.assign(inpNotes->value());
    +	else notes.clear();
    +
     	if (progdefaults.notes_address) {
     		if (!notes.empty()) notes.append("\n");
     		notes.append(lookup_name).append("\n");
    @@ -675,7 +683,8 @@ void parse_callook(string& xmlpage)
     
     bool CALLOOKGetXML(string& xmlpage)
     {
    -	string url = string("http://callook.info/").append(callsign).append("/xml");
    +	string url = progdefaults.callookurl;
    +	url.append(callsign).append("/xml");
     	bool res = fetch_http(url, xmlpage, 5.0);
     	LOG_VERBOSE("result = %d", res);
     	return res;
    @@ -761,7 +770,14 @@ bool HAMCALLget(string& htmlpage)
     
     	print_query("hamcall", url_detail);
     
    -	return request_reply("www.hamcall.net", "http", url_detail, htmlpage, 5.0);
    +	string url = progdefaults.hamcallurl;
    +	size_t p = url.find("//");
    +	string service = url.substr(0, p);
    +	url.erase(0, p+2);
    +	size_t len = url.length();
    +	if (url[len-1]=='/') url.erase(len-1, 1);
    +	return request_reply(url, service, url_detail, htmlpage, 5.0);
    +//	return request_reply("www.hamcall.net", "http", url_detail, htmlpage, 5.0);
     }
     
     void HAMCALLquery()
    @@ -789,18 +805,21 @@ static string HAMQTH_reply = "";
     
     bool HAMQTH_get_session_id()
     {
    -	string url = "";
    +	string url = progdefaults.hamqthurl;
     	string retstr = "";
     	size_t p1 = string::npos;
     	size_t p2 = string::npos;
     
    -	url.append("http://www.hamqth.com/xml.php?u=").append(progdefaults.QRZusername);
    +	if (url.find("https") == 0) url.erase(4,1); // change to http
    +	url.append("xml.php?u=").append(progdefaults.QRZusername);
     	url.append("&p=").append(progdefaults.QRZuserpassword);
     
     	HAMQTH_session_id.clear();
     	if (!fetch_http(url, retstr, 5.0)) {
    +printf("fetch_http( %s, retstr, 5.0) failed\n", url.c_str());
     		return false;
     	}
    +printf("%s\n", retstr.c_str());
     	p1 = retstr.find("");
     	if (p1 != string::npos) {
     		p2 = retstr.find("");
    @@ -942,7 +961,7 @@ void parse_HAMQTH_html(const string& htmlpage)
     
     bool HAMQTHget(string& htmlpage)
     {
    -	string url = "";
    +	string url = progdefaults.hamqthurl;
     	bool ret;
     	if (HAMQTH_session_id.empty()) {
     		if (!HAMQTH_get_session_id()) {
    @@ -951,7 +970,8 @@ bool HAMQTHget(string& htmlpage)
     			return false;
     		}
     	}
    -	url.append("http://www.hamqth.com/xml.php?id=").append(HAMQTH_session_id);
    +	if (url.find("https") == 0) url.erase(4,1); // change to http
    +	url.append("xml.php?id=").append(HAMQTH_session_id);
     	url.append("&callsign=").append(callsign);
     	url.append("&prg=FLDIGI");
     
    @@ -1009,26 +1029,23 @@ void HAMQTHquery()
     
     void QRZ_DETAILS_query()
     {
    -	string qrzurl = "http://www.qrz.com/db/";
    -	qrzurl.append(callsign);
    -
    -	cb_mnuVisitURL(0, (void*)qrzurl.c_str());
    +	string qrz = progdefaults.qrzurl;
    +	qrz.append("db/").append(callsign);
    +	cb_mnuVisitURL(0, (void*)qrz.c_str());
     }
     
     void HAMCALL_DETAILS_query()
     {
    -	string hamcallurl = "http://www.hamcall.net/call?callsign=";
    -	hamcallurl.append(callsign);
    -
    -	cb_mnuVisitURL(0, (void*)hamcallurl.c_str());
    +	string hamcall = progdefaults.hamcallurl;
    +	hamcall.append("call?callsign=").append(callsign);
    +	cb_mnuVisitURL(0, (void*)hamcall.c_str());
     }
     
     void HAMQTH_DETAILS_query()
     {
    -	string hamqthurl = "http://www.hamQTH.com/";
    -	hamqthurl.append(callsign);
    -
    -	cb_mnuVisitURL(0, (void*)hamqthurl.c_str());
    +	string hamqth = progdefaults.hamqthurl;
    +	hamqth.append(callsign);
    +	cb_mnuVisitURL(0, (void*)hamqth.c_str());
     }
     
     
    @@ -1134,10 +1151,10 @@ void CALLSIGNquery()
     		}
     		break;
     	case CALLOOK:
    -		LOG_INFO("%s","Request sent to\nhttp://callook.info...");
    +		LOG_INFO("Request sent to %s", progdefaults.hamcallurl.c_str());
     		break;
     	case HAMQTH:
    -		LOG_INFO("%s","Request sent to \nhttp://hamqth.com...");
    +		LOG_INFO("Request sent to %s", progdefaults.hamqthurl.c_str());
     		break;
     	case QRZXMLNONE:
     		break;
    @@ -1188,7 +1205,7 @@ static void *EQSL_loop(void *args)
     			return NULL;
     
     		size_t p;
    -		if (fetch_http(EQSL_url, EQSL_xmlpage, 5.0) == -1)
    +		if (fetch_http(EQSL_url, EQSL_xmlpage, 5.0) == false)
     			LOG_ERROR("%s", "eQSL not available");
     
     		else if ((p = EQSL_xmlpage.find("Error:")) != std::string::npos) {
    diff --git a/src/logbook/maclogger.cxx b/src/logbook/maclogger.cxx
    new file mode 100644
    index 00000000..1242e61c
    --- /dev/null
    +++ b/src/logbook/maclogger.cxx
    @@ -0,0 +1,441 @@
    +// =====================================================================
    +//
    +// maclogger.cxx
    +//
    +// receive log data from maclogger udp broadcast message
    +//
    +// Copyright (C) 2016
    +//		Dave Freese, W1HKJ
    +//
    +// This file is part of fldigi.
    +//
    +// Fldigi 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.
    +//
    +// Fldigi 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 fldigi.  If not, see .
    +// =====================================================================
    +
    +#include 
    +#include 
    +#include 
    +#include 
    +#include 
    +#include 
    +
    +#include 
    +#include 
    +
    +#include "rigsupport.h"
    +#include "modem.h"
    +#include "trx.h"
    +#include "fl_digi.h"
    +#include "configuration.h"
    +#include "main.h"
    +#include "waterfall.h"
    +#include "macros.h"
    +#include "qrunner.h"
    +#include "debug.h"
    +#include "status.h"
    +#include "icons.h"
    +
    +#include "maclogger.h"
    +
    +#include "confdialog.h"
    +
    +LOG_FILE_SOURCE(debug::LOG_MACLOGGER);
    +
    +using namespace std;
    +
    +//======================================================================
    +// Socket MACLOGGER i/o used on all platforms
    +//======================================================================
    +
    +pthread_t maclogger_thread;
    +pthread_t maclogger_rx_socket_thread;
    +pthread_mutex_t mclg_str_mutex     = PTHREAD_MUTEX_INITIALIZER;
    +Socket *maclogger_socket = 0;
    +
    +bool maclogger_enabled = false;
    +bool maclogger_exit = false;
    +
    +string maclogger_ip_address= "";;
    +string maclogger_ip_port= "";;
    +
    +string mclg_str = "";
    +int    mclg_rxhz;
    +int    mclg_txhz;
    +string mclg_band;
    +string mclg_mode;
    +string mclg_power;
    +string mclg_call;
    +string mclg_dxccnum;
    +string mclg_dxccstr;
    +string mclg_city;
    +string mclg_state;
    +string mclg_firstname;
    +string mclg_lastname;
    +string mclg_comment;
    +string mclg_bearing;
    +string mclg_longpath;
    +string mclg_distance;
    +
    +//======================================================================
    +// MacLogger UDP string parsing
    +//======================================================================
    +
    +static string get_str(string s)
    +{
    +	size_t p = s.find(":");
    +	if (p == string::npos) return "";
    +	s.erase(0, p+1);
    +	p = s.find(",");
    +	if (p == string::npos) p = s.find("]");
    +	if (p == string::npos) return "";
    +	string s2 = s.substr(0, p);
    +	if (s2 == "(null)") return "";
    +	return s2;
    +}
    +
    +static int get_freq(string s)
    +{
    +	string s2 = get_str(s);
    +	float mhz;
    +	sscanf(s2.c_str(), "%f", &mhz);
    +	int hz = mhz * 1e6;
    +	return hz;
    +}
    +
    +void maclogger_set_qsy()
    +{
    +	int hz = mclg_txhz;
    +	if (hz <= 0) hz = mclg_rxhz;
    +	if (hz <= 0) return;
    +	wf->rfcarrier(hz);
    +	wf->movetocenter();
    +	show_frequency(hz);
    +}
    +
    +void maclogger_set_call()
    +{
    +	inpCall->value(mclg_call.c_str());
    +	inpCall->do_callback();
    +}
    +
    +void maclogger_set_name()
    +{
    +	inpName->value(mclg_firstname.c_str());
    +	inpName->do_callback();
    +}
    +
    +void maclogger_set_mode()
    +{
    +//	inpMode->value(mclg_mode.c_str());
    +//	inpMode->do_callback();
    +}
    +
    +void maclogger_set_qth()
    +{
    +	inpQth->value(mclg_city.c_str());
    +	inpQth->do_callback();
    +}
    +
    +void maclogger_set_state()
    +{
    +	inpState->value(mclg_state.c_str());
    +	inpState->do_callback();
    +}
    +
    +void maclogger_disp_report(const char * s)
    +{
    +	txt_UDP_data->insert(s);
    +	txt_UDP_data->redraw();
    +}
    +
    +void show_mac_strings()
    +{
    +	SET_THREAD_ID(MACLOGGER_TID);
    +
    +	if (mclg_txhz > 0) REQ(maclogger_set_qsy);
    +	else if (mclg_rxhz > 0) REQ(maclogger_set_qsy);
    +	if (!mclg_mode.empty()) REQ(maclogger_set_mode);
    +	if (!mclg_call.empty()) REQ(maclogger_set_call);
    +	if (!mclg_city.empty()) REQ(maclogger_set_qth);
    +	if (!mclg_state.empty()) REQ(maclogger_set_state);
    +	if (!mclg_firstname.empty()) REQ(maclogger_set_name);
    +
    +//	if (!mclg_power.empty())
    +//	if (!mclg_band.empty())
    +//	if (!mclg_lastname.empty())
    +//	if (!mclg_comment.empty())
    +//	if (!mclg_bearing.empty())
    +//	if (!mclg_longpath.empty())
    +//	if (!mclg_distance.empty())
    +//	if (!mclg_dxccnum.empty())
    +//	if (!mclg_dxccstr.empty())
    +
    +}
    +
    +void parse_report(string str)
    +{
    +	size_t p;
    +	mclg_rxhz = 0;
    +	mclg_txhz = 0;
    +	mclg_band.clear();
    +	mclg_mode.clear();
    +	mclg_power.clear();
    +	mclg_call.clear();
    +	mclg_dxccnum.clear();
    +	mclg_dxccstr.clear();
    +	mclg_city.clear();
    +	mclg_state.clear();
    +	mclg_firstname.clear();
    +	mclg_lastname.clear();
    +	mclg_comment.clear();
    +	mclg_bearing.clear();
    +	mclg_longpath.clear();
    +	mclg_distance.clear();
    +
    +	if ((p = str.find("RxMHz:")) != string::npos)
    +		mclg_rxhz = get_freq(str.substr(p));
    +	if ((p = str.find("TxMHz:")) != string::npos)
    +		mclg_txhz = get_freq(str.substr(p));
    +	if ((p = str.find("Mode:"))  != string::npos)
    +		mclg_mode = get_str(str.substr(p));
    +	if ((p = str.find("Call:"))  != string::npos)
    +		mclg_call = get_str(str.substr(p));
    +	if ((p = str.find("city:")) != string::npos)
    +		mclg_city = get_str(str.substr(p));
    +	if ((p = str.find("state:")) != string::npos)
    +		mclg_state = get_str(str.substr(p));
    +	if ((p = str.find("first_name:")) != string::npos)
    +		mclg_firstname = get_str(str.substr(p));
    +
    +//	if ((p = mclg_str.find("dxcc_num:")) != string::npos)
    +//		mclg_dxccnum = get_str(mclg_str.substr(p));
    +//	if ((p = mclg_str.find("dxcc_string:")) != string::npos)
    +//		mclg_dxccstr = get_str(mclg_str.substr(p));
    +//	if ((p = mclg_str.find("Power:")) != string::npos)
    +//		mclg_power = get_str(mclg_str.substr(p));
    +//	if ((p = mclg_str.find("Band:"))  != string::npos)
    +//		mclg_band = get_str(mclg_str.substr(p));
    +//	if ((p = mclg_str.find("last_name:")) != string::npos)
    +//		mclg_lastname = get_str(mclg_str.substr(p));
    +//	if ((p = mclg_str.find("Comment:")) != string::npos)
    +//		mclg_comment = get_str(mclg_str.substr(p));
    +//	if ((p = mclg_str.find("Bearing:")) != string::npos)
    +//		mclg_bearing = get_str(mclg_str.substr(p));
    +//	if ((p = mclg_str.find("LongPath:")) != string::npos)
    +//		mclg_longpath = get_str(mclg_str.substr(p));
    +//	if ((p = mclg_str.find("Distance:")) != string::npos)
    +//		mclg_distance = get_str(mclg_str.substr(p));
    +
    +	show_mac_strings();
    +}
    +
    +void parse_maclog()
    +{
    +	size_t p1, p2;
    +	string str, srep;
    +	static string sreport[20];
    +	int repnbr = 0;
    +	while (!mclg_str.empty()) {
    +		p1 = mclg_str.find("[");
    +		if (p1 == string::npos) return;
    +		if (p1 != 0) mclg_str.erase(0, p1);
    +		p2 = mclg_str.find("]");
    +		if (p2 == string::npos) return;
    +
    +		str = mclg_str.substr(0, p2 + 1);
    +		srep = str;
    +		srep.append("\n");
    +		if (repnbr < 20) {
    +			sreport[repnbr] = srep;
    +			REQ(maclogger_disp_report, sreport[repnbr].c_str());
    +			repnbr++;
    +		}
    +
    +		if (progdefaults.enable_maclogger_log) {
    +			std::string pathname = TempDir;
    +			pathname.append("maclogger_udp_strings.txt");
    +			FILE *maclog = fopen(pathname.c_str(), "a");
    +			fprintf(maclog, "%s", srep.c_str());
    +			fclose(maclog);
    +		}
    +
    +		if (progdefaults.capture_maclogger_radio &&
    +			(mclg_str.find("[Radio Report:") == 0)) parse_report(str);
    +
    +		else if (progdefaults.capture_maclogger_spot_tune &&
    +			(mclg_str.find("[SpotTune:") == 0)) parse_report(str);
    +
    +		else if (progdefaults.capture_maclogger_spot_report &&
    +			(mclg_str.find("[Spot Report:") == 0)) parse_report(str);
    +
    +		else if (progdefaults.capture_maclogger_log &&
    +			(mclg_str.find("[Log Report:") == 0)) parse_report(str);
    +
    +		else if (progdefaults.capture_maclogger_lookup &&
    +			(mclg_str.find("[Lookup Report") == 0)) parse_report(str);
    +
    +		mclg_str.erase(0, p2 + 1);
    +
    +	}
    +}
    +
    +//======================================================================
    +// uncomment to use UDP test strings
    +//
    +// #define TESTSTRINGS 1
    +//
    +//======================================================================
    +
    +#ifdef TESTSTRINGS
    +string tstring[6] = {
    +	"[Radio Report:RxMHz:24.96400, TxMHz:24.96400, Band:12M, Mode:USB, Power:5]",
    +	"[SpotTune:RxMHz:28.49500, TxMHz:28.49600, Band:10M, Mode:USB]",
    +	"[Log Report: Call:N2BJ, RxMHz:21.08580, TxMHz:21.08580, Band:15M, Mode:FSK, Power:5, dxcc_num:291, dxcc_string:United States, city:NEW LENOX, state:IL, first_name:Barry, last_name:COHEN]",
    +	"[Spot Report: RxMHz:3.50300, TxMHz:3.50300, Band:80M, Mode:CW, Call:EP6T, dxcc_string:Iran, Comment:UP , TNX CARLO , GL]",
    +	"[Rotor Report: Bearing:304.7, LongPath:0, Distance:0.0]",
    +	"[Lookup Report:Call:YC8RBI, RxMHz:21.32500, Band:15M, Mode:USB, dxcc_num:327, dxcc_string:Indonesia, Bearing:328.1, city:SANGIHE ISLAND NORTH SULAWESI, state:(null), first_name:RICHARD, last_name:BYL ( ICHA )]"
    +};
    +int tnbr = 0;
    +#endif
    +
    +void get_maclogger_udp()
    +{
    +	if(!maclogger_socket) return;
    +	if (!progdefaults.connect_to_maclogger) return;
    +
    +#ifdef TESTSTRINGS
    +	if (tnbr == 0) {
    +		mclg_str = "bogus start chars dkoe13.chfff ";
    +		for (int n = 0; n < 6; n++) mclg_str.append(tstring[n]);
    +		mclg_str.append(" and garbage at the end");
    +		parse_maclog();
    +		tnbr = 1;
    +	}
    +#else
    +	char buffer[MACLOGGER_BUFFER_SIZE];
    +	size_t count = 0;
    +
    +	memset(buffer, 0, sizeof(buffer));
    +
    +	try {
    +		count = maclogger_socket->recvFrom(
    +			(void *) buffer,
    +			sizeof(buffer) - 1);
    +	} catch (...) {
    +		LOG_WARN("MAC_logger socket error");
    +		count = 0;
    +	}
    +
    +	if (count) {
    +		mclg_str.append(buffer, count);
    +		parse_maclog();
    +	}
    +#endif
    +}
    +
    +//======================================================================
    +//
    +//======================================================================
    +void *maclogger_loop(void *args)
    +{
    +	SET_THREAD_ID(MACLOGGER_TID);
    +
    +	LOG_INFO("%s", "MAC_logger loop started. ");
    +
    +	while(1) {
    +		for (int i = 0; i < 100; i++) {
    +			MilliSleep(10);
    +			if (maclogger_exit) break;
    +		}
    +		if (maclogger_exit) break;
    +		get_maclogger_udp();
    +	}
    +	// exit the maclogger thread
    +	SET_THREAD_CANCEL();
    +	return NULL;
    +}
    +
    +//======================================================================
    +//
    +//======================================================================
    +bool maclogger_start(void)
    +{
    +	maclogger_ip_address = "255.255.255.255";
    +	maclogger_ip_port = "9932";
    +
    +	try {
    +		maclogger_socket = new Socket(
    +				Address( maclogger_ip_address.c_str(),
    +						 maclogger_ip_port.c_str(),
    +						 "udp") );
    +		maclogger_socket->set_autoclose(true);
    +		maclogger_socket->set_nonblocking(false);
    +		maclogger_socket->bindUDP();
    +	}
    +	catch (const SocketException& e) {
    +		LOG_ERROR(
    +			"Could not resolve %s: %s",
    +			maclogger_ip_address.c_str(),
    +			e.what() );
    +		return false;
    +	}
    +
    +	return true;
    +}
    +
    +//======================================================================
    +//
    +//======================================================================
    +void maclogger_init(void)
    +{
    +	maclogger_enabled = false;
    +	maclogger_exit = false;
    +
    +	if(!maclogger_start()) return;
    +
    +	LOG_INFO("%s", "UDP Init - OK");
    +
    +	if (pthread_create(&maclogger_thread, NULL, maclogger_loop, NULL) < 0) {
    +		LOG_ERROR("MACLOGGER maclogger_thread: pthread_create failed");
    +		return;
    +	}
    +
    +	LOG_INFO("MACLOGGER thread started");
    +
    +	maclogger_enabled = true;
    +}
    +
    +//======================================================================
    +//
    +//======================================================================
    +void maclogger_close(void)
    +{
    +	if (!maclogger_enabled) return;
    +
    +	if(maclogger_socket) {
    +		maclogger_socket->shut_down();
    +		maclogger_socket->close();
    +	}
    +
    +	maclogger_exit = true;
    +	pthread_join(maclogger_thread, NULL);
    +
    +	LOG_INFO("%s", "MAC_logger loop terminated. ");
    +
    +	maclogger_enabled = false;
    +#ifdef TESTSTRINGS
    +	tnbr = 0;
    +#endif
    +}
    +
    diff --git a/src/logbook/qso_db.cxx b/src/logbook/qso_db.cxx
    index 20f0e8a6..5641799a 100644
    --- a/src/logbook/qso_db.cxx
    +++ b/src/logbook/qso_db.cxx
    @@ -42,16 +42,20 @@ static bool date_off = true;
     bool cQsoDb::reverse = false;
     
     cQsoRec::cQsoRec() {
    -	for (int i=0;i < NUMFIELDS; i++)
    -		qsofield[i] = "";
    +	for (int i=0;i < NUMFIELDS; i++) {
    +		qsofield[i] = new string;
    +		qsofield[i]->clear();
    +	}
     }
     
     cQsoRec::~cQsoRec () {
    +	for (int i = 0; i < NUMFIELDS; i++)
    +		delete qsofield[i];
     }
     
     void cQsoRec::clearRec () {
     	for (int i = 0; i < NUMFIELDS; i++)
    -		qsofield[i].clear();
    +		qsofield[i]->clear();
     }
     
     int cQsoRec::validRec() {
    @@ -59,27 +63,27 @@ int cQsoRec::validRec() {
     }
     
     void cQsoRec::checkBand() {
    -	size_t flen = qsofield[FREQ].length(), blen = qsofield[BAND].length();
    +	size_t flen = qsofield[FREQ]->length(), blen = qsofield[BAND]->length();
     	if (flen == 0 && blen != 0) {
     		for (size_t n = 0; n < blen; n++)
    -			qsofield[BAND][n] = tolower(qsofield[BAND][n]);
    -		qsofield[FREQ] =  band_freq(qsofield[BAND].c_str());
    +			(*qsofield[BAND])[n] = tolower((*qsofield[BAND])[n]);
    +		*qsofield[FREQ] =  band_freq((*qsofield[BAND]).c_str());
     	} else if (blen == 0 && flen != 0)
    -		qsofield[BAND] =  band_name(qsofield[FREQ].c_str());
    +		*qsofield[BAND] =  band_name((*qsofield[FREQ]).c_str());
     }
     
     void cQsoRec::checkDateTimes() {
    -	size_t len1 = qsofield[TIME_ON].length(), len2 = qsofield[TIME_OFF].length();
    +	size_t len1 = qsofield[TIME_ON]->length(), len2 = qsofield[TIME_OFF]->length();
     	if (len1 == 0 && len2 != 0)
    -		qsofield[TIME_ON] = qsofield[TIME_OFF];
    +		*qsofield[TIME_ON] = *qsofield[TIME_OFF];
     	else if (len1 != 0 && len2 == 0)
    -		qsofield[TIME_OFF] = qsofield[TIME_ON];
    -	len1 = qsofield[QSO_DATE].length();
    -	len2 = qsofield[QSO_DATE_OFF].length();
    +		*qsofield[TIME_OFF] = *qsofield[TIME_ON];
    +	len1 = qsofield[QSO_DATE]->length();
    +	len2 = qsofield[QSO_DATE_OFF]->length();
     	if (len1 == 0 && len2 != 0)
    -		qsofield[QSO_DATE] = qsofield[QSO_DATE_OFF];
    +		*qsofield[QSO_DATE] = *qsofield[QSO_DATE_OFF];
     	else if (len1 != 0 && len2 == 0)
    -		qsofield[QSO_DATE_OFF] = qsofield[QSO_DATE];
    +		*qsofield[QSO_DATE_OFF] = *qsofield[QSO_DATE];
     }
     
     // Sets the current time, with the right format.
    @@ -122,24 +126,24 @@ void cQsoRec::setFrequency(long long freq) {
     
     void cQsoRec::putField (int n, const char *s){
     	if (n < 0 || n >= NUMFIELDS) return;
    -	qsofield[n] = s;
    +	qsofield[n]->assign(s);// = s;
     }
     
     void cQsoRec::putField (int n, const char *s, int len) {
     	if (n < 0 || n >= NUMFIELDS) return;
    -	qsofield[n].assign(s, len);
    +	qsofield[n]->assign(s, len);
     }
     
     void cQsoRec::addtoField (int n, const char *s){
     	if (n < 0 || n >= NUMFIELDS) return;
    -	qsofield[n].append(s);
    +	qsofield[n]->append(s);
     }
     
     void cQsoRec::trimFields () {
     	size_t p;
     	string s;
     	for (int i = 0; i < NUMFIELDS; i++) {
    -		s = qsofield[i];
    +		s = *qsofield[i];
     //right trim string
     		p = s.length();
     		while (p && s[p-1] == ' ') {
    @@ -157,39 +161,41 @@ void cQsoRec::trimFields () {
     			for (p = 0; p < s.length(); p++)
     				s[p] = toupper(s[p]);
     		}
    -		qsofield[i] = s;
    +		*qsofield[i] = s;
     	}
     }
     
    +static const char *empty_field = "";
    +
     const char * cQsoRec::getField (int n) const {
    -	if (n < 0 || n >= NUMFIELDS) return 0;
    -	return (qsofield[n].c_str());
    +	if (n < 0 || n >= NUMFIELDS) return empty_field;
    +	return (qsofield[n]->c_str());
     }
     
     const cQsoRec &cQsoRec::operator=(const cQsoRec &right) {
     	if (this != &right) {
     		for (int i = 0; i < NUMFIELDS; i++)
    -			this->qsofield[i] = right.qsofield[i];
    +			(this->qsofield[i])->assign(*(right.qsofield[i]));
     	}
     	return *this;
     }
     
     int compareTimes (const cQsoRec &r1, const cQsoRec &r2) {
     	if (date_off)
    -		return r1.qsofield[TIME_OFF].compare( r2.qsofield[TIME_OFF] );
    -	return r1.qsofield[TIME_ON].compare( r2.qsofield[TIME_ON] );
    +		return (*r1.qsofield[TIME_OFF]).compare( (*r2.qsofield[TIME_OFF]) );
    +	return (*r1.qsofield[TIME_ON]).compare( (*r2.qsofield[TIME_ON]) );
     }
     
     int compareDates (const cQsoRec &r1, const cQsoRec &r2) {
     	if (date_off)
    -		return r1.qsofield[QSO_DATE_OFF].compare( r2.qsofield[QSO_DATE_OFF] );
    -	return r1.qsofield[QSO_DATE].compare( r2.qsofield[QSO_DATE] );
    +		return (*r1.qsofield[QSO_DATE_OFF]).compare( (*r2.qsofield[QSO_DATE_OFF]) );
    +	return (*r1.qsofield[QSO_DATE]).compare( (*r2.qsofield[QSO_DATE]) );
     }
     
     int compareCalls (const cQsoRec &r1, const cQsoRec &r2) {
     	int cmp = 0;
    -	const char * s1 = r1.qsofield[CALL].c_str();
    -	const char * s2 = r2.qsofield[CALL].c_str();
    +	const char * s1 = (*r1.qsofield[CALL]).c_str();
    +	const char * s2 = (*r2.qsofield[CALL]).c_str();
     	const char * p1 = strpbrk (s1+1, "0123456789");
     	const char * p2 = strpbrk (s2+1, "0123456789");
     
    @@ -206,13 +212,13 @@ int compareCalls (const cQsoRec &r1, const cQsoRec &r2) {
     }
     
     int compareModes (const cQsoRec &r1, const cQsoRec &r2) {
    -	return r1.qsofield[MODE].compare( r2.qsofield[MODE] );
    +	return (r1.qsofield[MODE])->compare( *r2.qsofield[MODE] );
     }
     
     int compareFreqs (const cQsoRec &r1, const cQsoRec &r2) {
     	double f1, f2;
    -	f1 = atof(r1.qsofield[FREQ].c_str());
    -	f2 = atof(r2.qsofield[FREQ].c_str());
    +	f1 = atof(r1.qsofield[FREQ]->c_str());
    +	f2 = atof(r2.qsofield[FREQ]->c_str());
     	return (f1 == f2 ? 0 : f1 < f2 ? -1 : 1);
     }
     
    @@ -278,7 +284,7 @@ static bool isVer3 = false;
     
     ostream &operator<< (ostream &output, const cQsoRec &rec) {
     	for (int i = 0; i < EXPORT; i++)
    -		output << rec.qsofield[i].c_str() << delim_out;
    +		output << rec.qsofield[i]->c_str() << delim_out;
     	return output;
     }
     
    @@ -286,7 +292,7 @@ istream &operator>> (istream &input, cQsoRec &rec ) {
     	static char buf[1024]; // Must be big enough for a field.
     	for (int i = 0; i < NUMFIELDS; i++) {
     		input.getline( buf, sizeof(buf), delim_in );
    -		rec.qsofield[i] = buf ;
    +		*rec.qsofield[i] = buf ;
     	}
     	return input;
     }
    @@ -294,8 +300,8 @@ istream &operator>> (istream &input, cQsoRec &rec ) {
     //======================================================================
     // class cQsoDb
     
    -#define MAXRECS 32768
    -#define INCRRECS 8192
    +#define MAXRECS 100000
    +#define INCRRECS 10000
     
     cQsoDb::cQsoDb() {
       nbrrecs = 0;
    diff --git a/src/logbook/table.cxx b/src/logbook/table.cxx
    index 744b43c5..31b755de 100644
    --- a/src/logbook/table.cxx
    +++ b/src/logbook/table.cxx
    @@ -1654,9 +1654,9 @@ void Table::calcDimensions() {
       hideV = (tableHeight <= iH),
       hideH = (tableWidth <= iW);
     
    -  if (!hideH & hideV)
    +  if (!hideH && hideV)
         hideV = (tableHeight - iH - scrollbarSize) <= 0;
    -  if (!hideV & hideH)
    +  if (!hideV && hideH)
         hideH = (tableWidth - iW + scrollbarSize) <= 0;
     
       if (Vscroll == always) {
    diff --git a/src/logger/logger.cxx b/src/logger/logger.cxx
    index 9c271a92..7f49a381 100644
    --- a/src/logger/logger.cxx
    +++ b/src/logger/logger.cxx
    @@ -61,8 +61,6 @@ static string notes;
     
     //=============================================================================
     
    -//#if defined(__WOE32__) || defined(__APPLE__)
    -
     static string adif;
     
     void writeADIF () {
    @@ -131,8 +129,6 @@ void submit_ADIF(cQsoRec &rec)
     	writeADIF();
     }
     
    -//#endif
    -
     //---------------------------------------------------------------------
     // the following IPC message is compatible with xlog remote data spec.
     //---------------------------------------------------------------------
    diff --git a/src/logger/rx_extract.cxx b/src/logger/rx_extract.cxx
    index 3df47820..767914f3 100644
    --- a/src/logger/rx_extract.cxx
    +++ b/src/logger/rx_extract.cxx
    @@ -40,6 +40,7 @@
     #include "icons.h"
     #include "qrunner.h"
     #include "timeops.h"
    +#include "xmlrpc.h"
     
     using namespace std;
     
    @@ -62,13 +63,14 @@ Save tags and all enclosed text to date-time stamped file, ie:\n\
         ~/.nbems/WRAP/recv/extract-20090127-092515.wrap");
     #endif
     
    -#define   bufsize  16
    +#define   bufsize  64
     char  rx_extract_buff[bufsize + 1];
     string rx_buff;
     string rx_extract_msg;
     
     bool extract_wrap = false;
     bool extract_flamp = false;
    +bool extract_arq = false;
     
     bool bInit = false;
     
    @@ -81,6 +83,7 @@ void rx_extract_reset()
     	rx_extract_buff[bufsize] = 0;
     	extract_wrap = false;
     	extract_flamp = false;
    +	extract_arq = false;
     	put_status("");
     }
     
    @@ -125,6 +128,12 @@ void invoke_flmsg()
     	rx_extract_msg.append(FLMSG_WRAP_recv_dir);
     	put_status(rx_extract_msg.c_str(), 20, STATUS_CLEAR);
     
    +	if (flmsg_online && progdefaults.flmsg_transfer_direct) {
    +		guard_lock autolock(server_mutex);
    +		flmsg_data.append(rx_buff);
    +		return;
    +	}
    +
     	if (progdefaults.open_nbems_folder)
     		open_recv_folder(FLMSG_WRAP_recv_dir.c_str());
     
    @@ -272,6 +281,36 @@ void invoke_flmsg()
     	}
     }
     
    +void start_flmsg()
    +{
    +	string cmd = progdefaults.flmsg_pathname;
    +
    +#ifdef __MINGW32__
    +	char *cmdstr = strdup(cmd.c_str());
    +	STARTUPINFO si;
    +	PROCESS_INFORMATION pi;
    +	memset(&si, 0, sizeof(si));
    +	si.cb = sizeof(si);
    +	memset(&pi, 0, sizeof(pi));
    +	if (!CreateProcess( NULL, cmdstr,
    +		NULL, NULL, FALSE,
    +		CREATE_NO_WINDOW, NULL, NULL, &si, &pi))
    +		LOG_ERROR("CreateProcess failed with error code %ld", GetLastError());
    +	CloseHandle(pi.hProcess);
    +	CloseHandle(pi.hThread);
    +	free (cmdstr);
    +#else
    +	switch (fork()) {
    +	case 0:
    +		execlp((char*)cmd.c_str(), (char*)cmd.c_str(), (char*)0, (char*)0);
    +		exit(EXIT_FAILURE);
    +	case -1:
    +		fl_alert2(_("Could not start flmsg"));
    +	default: ;
    +	}
    +#endif
    +}
    +
     void rx_extract_add(int c)
     {
     	if (!c) return;
    @@ -286,16 +325,45 @@ void rx_extract_add(int c)
     	memmove(rx_extract_buff, &rx_extract_buff[1], bufsize - 1);
     	rx_extract_buff[bufsize - 1] = ch;
     
    -	if ( strstr(rx_extract_buff, wrap_beg) && !extract_flamp) {
    +	if (strstr(rx_extract_buff, "~1") && strstr(rx_extract_buff, "~4")) {
    +		if (!flmsg_online) start_flmsg();
    +		memset(rx_extract_buff, ' ', bufsize);
    +		return;
    +	}
    +	if (!extract_arq && strstr(rx_extract_buff, "ARQ:FILE::FLMSG_XFR")) {
    +		extract_arq = true;
    +		REQ(rx_remove_timer);
    +		REQ(rx_add_timer);
    +		memset(rx_extract_buff, ' ', bufsize);
    +		rx_extract_msg = "Extracting ARQ msg";
    +		put_status(rx_extract_msg.c_str());
    +		return;
    +	} else if (extract_arq) {
    +		REQ(rx_remove_timer);
    +		REQ(rx_add_timer);
    +		if (strstr(rx_extract_buff, "ARQ::ETX"))
    +			rx_extract_reset();
    +		return;
    +	} else if (!extract_flamp && strstr(rx_extract_buff, flamp_beg)) {
    +		extract_flamp = true;
    +		memset(rx_extract_buff, ' ', bufsize);
    +		rx_extract_msg = "Extracting FLAMP";
    +		put_status(rx_extract_msg.c_str());
    +		return;
    +	} else if (extract_flamp) {
    +		REQ(rx_remove_timer);
    +		REQ(rx_add_timer);
    +		if (strstr(rx_extract_buff, flamp_end) != NULL)
    +			rx_extract_reset();
    +		return;
    +	} else if (!extract_wrap && strstr(rx_extract_buff, wrap_beg)) {
     		rx_buff.assign(wrap_beg);
     		rx_extract_msg = "Extracting WRAP/FLMSG";
    -
     		put_status(rx_extract_msg.c_str());
    -
    -		memset(rx_extract_buff, ' ', bufsize);
     		extract_wrap = true;
     		REQ(rx_remove_timer);
     		REQ(rx_add_timer);
    +		return;
     	} else if (extract_wrap) {
     		rx_buff += ch;
     		REQ(rx_remove_timer);
    @@ -304,16 +372,6 @@ void rx_extract_add(int c)
     			invoke_flmsg();
     			rx_extract_reset();
     		}
    -	} else if (strstr(rx_extract_buff, flamp_beg) && ! extract_wrap) {
    -		extract_flamp = true;
    -		rx_extract_msg = "Extracting FLAMP";
    -		put_status(rx_extract_msg.c_str());
    -	} else if (extract_flamp == true) {
    -		REQ(rx_remove_timer);
    -		REQ(rx_add_timer);
    -		if (strstr(rx_extract_buff, flamp_end) != NULL) {
    -			rx_extract_reset();
    -		}
     	}
     }
     
    @@ -335,11 +393,13 @@ void select_flmsg_pathname()
     		deffilename = "/usr/local/bin/";
     		const char *p = FSEL::select(_("Locate flmsg executable"), _("flmsg\t*"), deffilename.c_str());
     # endif
    -	if (p) {
    -		progdefaults.flmsg_pathname = p;
    -		progdefaults.changed = true;
    -		txt_flmsg_pathname->value(p);
    -	}
    +	if (!p) return;
    +	if (!*p) return;
    +
    +	progdefaults.flmsg_pathname = p;
    +	progdefaults.changed = true;
    +	txt_flmsg_pathname->value(p);
    +
     #endif
     }
     
    @@ -411,7 +471,7 @@ string select_binary_pathname(string deffilename)
     	const char *p = FSEL::select(_("Locate binary"), _("*"), deffilename.c_str());
     # endif
     	string executable = "";
    -	if (p) executable = p;
    +	if (p && *p) executable = p;
     // do not allow recursion !!
     	if (executable.find("fldigi") != string::npos) return "";
     	return executable;
    diff --git a/src/main.cxx b/src/main.cxx
    index 44676b64..5b18cc4b 100644
    --- a/src/main.cxx
    +++ b/src/main.cxx
    @@ -97,6 +97,7 @@
     #include "Viewer.h"
     #include "kmlserver.h"
     #include "data_io.h"
    +#include "maclogger.h"
     
     #if USE_HAMLIB
     	#include "rigclass.h"
    @@ -132,6 +133,7 @@ string ScriptsDir = "";
     string PalettesDir = "";
     string LogsDir = "";
     string PicsDir = "";
    +string AvatarDir = "";
     string HelpDir = "";
     string MacrosDir = "";
     string WrapDir = "";
    @@ -181,6 +183,7 @@ FILE	*client;
     bool	mailserver = false, mailclient = false, arqmode = false;
     static bool show_cpucheck = false;
     static bool iconified = false;
    +bool	bMOREINFO = false;
     
     string option_help, version_text, build_text;
     
    @@ -223,6 +226,16 @@ void start_process(string executable)
     		CloseHandle(pi.hThread);
     		free(cmd);
     #else
    +#ifdef __APPLE__
    +	if (executable.find(".app") == (executable.length() - 4)) {
    +		std::string progname = executable;
    +		size_t p = progname.find("/", 1);
    +		if (p != std::string::npos) progname.erase(0,p+1);
    +		p = progname.find("-");
    +		if (p != std::string::npos) progname.erase(p);
    +		executable.append("/Contents/MacOS/").append(progname);
    +	}
    +#endif
     		switch (fork()) {
     			case -1:
     				LOG_PERROR("fork");
    @@ -241,16 +254,27 @@ void start_process(string executable)
     
     void toggle_io_port_selection(int io_mode)
     {
    +
     	switch(io_mode) {
     		case ARQ_IO:
    -			btnEnable_kiss->do_callback();
    -			btnEnable_arq->do_callback();
    -			progdefaults.changed = false;
    -			break;
    +            enable_arq();
    +            progdefaults.changed = false;
    +        break;
     
     		case KISS_IO:
    -			btnEnable_arq->do_callback();
    -			btnEnable_kiss->do_callback();
    +
    +            enable_kiss();
    +
    +            if(progdefaults.tcp_udp_auto_connect) {
    +                btn_connect_kiss_io->value(1);
    +                btn_connect_kiss_io->do_callback();
    +            }
    +
    +            if(progdefaults.kpsql_enabled) {
    +                btnPSQL->value(progdefaults.kpsql_enabled);
    +                btnPSQL->do_callback();
    +            }
    +
     			progdefaults.changed = false;
     			break;
     
    @@ -310,7 +334,7 @@ static void auto_start()
     // reset those default values that have been overriden by a command line parameter
     void check_overrides()
     {
    -	if (xmlrpc_address_override_flag) 
    +	if (xmlrpc_address_override_flag)
     		progdefaults.xmlrpc_address = override_xmlrpc_address;
     	if (xmlrpc_port_override_flag)
     		progdefaults.xmlrpc_port = override_xmlrpc_port;
    @@ -336,11 +360,14 @@ void delayed_startup(void *)
     	FLRIG_start_flrig_thread();
     
     	data_io_enabled = DISABLED_IO;
    +
     	arq_init();
    -	kiss_init();
    +
    +	if (progdefaults.connect_to_maclogger) maclogger_init();
     	data_io_enabled = progStatus.data_io_enabled;
     
     	toggle_io_port_selection(data_io_enabled);
    +    disable_config_p2p_io_widgets();
     
     	notify_start();
     
    @@ -353,6 +380,9 @@ void delayed_startup(void *)
     	if (progdefaults.check_for_updates)
     		cb_mnuCheckUpdate((Fl_Widget *)0, NULL);
     
    +#if USE_PORTAUDIO
    +	LOG_INFO("%s", str_pa_devices.c_str());
    +#endif
     }
     
     int main(int argc, char ** argv)
    @@ -360,6 +390,9 @@ int main(int argc, char ** argv)
     	// for KISS_IO status information
     	program_start_time = time(0);
     
    +	// ztimer must be run by FLTK's timeout handler
    +	ztimer((void*)true);
    +
     	active_modem = new NULLMODEM;
     
     	string appdir = appname = argv[0];
    @@ -488,6 +521,10 @@ int main(int argc, char ** argv)
     				cbq[i]->attach(i, "KISSSOCKET_TID");
     				break;
     
    +			case MACLOGGER_TID:
    +				cbq[i]->attach(i, "MACLOGGER_TID");
    +				break;
    +
     			case FLMAIN_TID:
     				cbq[i]->attach(i, "FLMAIN_TID");
     				break;
    @@ -750,21 +787,24 @@ int main(int argc, char ** argv)
     
     void exit_process() {
     
    -	KmlServer::Exit();
    +	if (progdefaults.kml_enabled)
    +		KmlServer::Exit();
     	arq_close();
    -	kiss_close();
    +	kiss_close(false);
    +	maclogger_close();
     	XML_RPC_Server::stop();
     
     	if (progdefaults.usepskrep)
     		pskrep_stop();
     
    +LOG_INFO("Detach/delete qrunner threads");
     	for (int i = 0; i < NUM_QRUNNER_THREADS; i++) {
    +LOG_INFO("thread %d", i);
     		cbq[i]->detach();
     		delete cbq[i];
     	}
    -
    +LOG_INFO("FSEL::destroy()");
     	FSEL::destroy();
    -
     }
     
     void generate_option_help(void) {
    @@ -823,10 +863,10 @@ void generate_option_help(void) {
              << "    The default is: " << progdefaults.data_io_enabled << "\n\n"
     
              << "  --kiss-server-address HOSTNAME\n"
    -         << "    Set the KISS UDP server address\n"
    +         << "    Set the KISS TCP/UDP server address\n"
              << "    The default is: " << progdefaults.kiss_address << "\n\n"
              << "  --kiss-server-port-io I/O PORT\n"
    -         << "    Set the KISS UDP server I/O port\n"
    +         << "    Set the KISS TCP/UDP server I/O port\n"
              << "    The default is: " << progdefaults.kiss_io_port << "\n\n"
              << "  --kiss-server-port-o Output PORT\n"
              << "    Set the KISS UDP server output port\n"
    @@ -1031,6 +1071,7 @@ int parse_args(int argc, char **argv, int& idx)
     #if USE_PORTAUDIO
                    OPT_FRAMES_PER_BUFFER,
     #endif
    +           OPT_MORE_INFO,
     	       OPT_NOISE, OPT_DEBUG_LEVEL, OPT_DEBUG_PSKMAIL, OPT_DEBUG_AUDIO,
                    OPT_EXIT_AFTER,
                    OPT_DEPRECATED, OPT_HELP, OPT_VERSION, OPT_BUILD_INFO };
    @@ -1090,6 +1131,7 @@ int parse_args(int argc, char **argv, int& idx)
     #if USE_PORTAUDIO
     		{ "frames-per-buffer",1, 0, OPT_FRAMES_PER_BUFFER },
     #endif
    +		{ "more-info",     1, 0, OPT_MORE_INFO },
     		{ "exit-after",    1, 0, OPT_EXIT_AFTER },
     
     		{ "noise", 0, 0, OPT_NOISE },
    @@ -1307,6 +1349,10 @@ int parse_args(int argc, char **argv, int& idx)
     			break;
     #endif // USE_PORTAUDIO
     
    +		case OPT_MORE_INFO:
    +			bMOREINFO = true;
    +			break;
    +
     		case OPT_EXIT_AFTER:
     			Fl::add_timeout(strtod(optarg, 0), exit_cb);
     			break;
    @@ -1592,6 +1638,7 @@ static void checkdirectories(void)
     		{ PalettesDir, "palettes", create_new_palettes },
     		{ LogsDir, "logs", 0 },
     		{ PicsDir, "images", 0 },
    +		{ AvatarDir, "avatars", 0},
     		{ HelpDir, "help", 0 },
     		{ MacrosDir, "macros", create_new_macros },
     		{ WrapDir, "wrap", 0 },
    @@ -1715,6 +1762,8 @@ static void arg_error(const char* name, const char* arg, bool missing)
     /// Sets or resets the KML parameters, and loads existing files.
     void kml_init(bool load_files)
     {
    +	if (progdefaults.kml_enabled == false) return; // disabled kml service
    +
     	KmlServer::GetInstance()->InitParams(
     			progdefaults.kml_command,
     			progdefaults.kml_save_dir,
    @@ -1750,7 +1799,8 @@ void kml_init(bool load_files)
     			custData );
     	}
     	catch( const std::exception & exc ) {
    -		LOG_WARN("Cannot publish user position:%s", exc.what() );
    +
    +;//		LOG_WARN("Cannot publish user position:%s", exc.what() );
     	}
     }
     
    diff --git a/src/mfsk/mfsk-pic.cxx b/src/mfsk/mfsk-pic.cxx
    index 342be0d1..9c46c86e 100644
    --- a/src/mfsk/mfsk-pic.cxx
    +++ b/src/mfsk/mfsk-pic.cxx
    @@ -181,8 +181,9 @@ void cb_picTxLoad(Fl_Widget *, void *)
     		FSEL::select(_("Load image file"), "Portable Network Graphics\t*.png\n"
     			    "Independent JPEG Group\t*.{jpg,jif,jpeg,jpe}\n"
     			    "Graphics Interchange Format\t*.gif", PicsDir.c_str());
    -	if (fn)
    -		load_image(fn);
    +	if (!fn) return;
    +	if (!*fn) return;
    +	load_image(fn);
     }
     
     void cb_picTxClose( Fl_Widget *w, void *)
    diff --git a/src/mfsk/mfsk.cxx b/src/mfsk/mfsk.cxx
    index aef3116f..6a009cf7 100644
    --- a/src/mfsk/mfsk.cxx
    +++ b/src/mfsk/mfsk.cxx
    @@ -65,7 +65,9 @@ struct TRACEPAIR {
     
     TRACEPAIR tracepair(45, 352);
     
    -bool xmt_filter = true;
    +// enable to limit within band signal sidebands
    +// not really needed
    +static bool xmt_filter = false;
     
     //=============================================================================
     char mfskmsg[80];
    @@ -79,11 +81,14 @@ void  mfsk::tx_init(SoundBase *sc)
     	txstate = TX_STATE_PREAMBLE;
     	bitstate = 0;
     
    -	double bw2 = (numtones + 1) * samplerate / symlen / 2.0;
    -	double flo = (get_txfreq_woffset() - bw2) / samplerate;
    -	if (flo <= 0) flo = 0;
    -	double fhi = (get_txfreq_woffset() + bw2) / samplerate;
    -	xmtfilt->init_bandpass (127, 1, flo, fhi);
    +	double factor = 1.5;
    +	double bw2 = factor*(numtones + 1) * samplerate / symlen / 2.0;
    +	double flo = (get_txfreq_woffset() - bw2);// / samplerate;
    +	if (flo <= 100) flo = 100;
    +	double fhi = (get_txfreq_woffset() + bw2);// / samplerate;
    +	if (fhi >= samplerate/2 - 100) fhi = samplerate/2 - 100;
    +
    +	xmtfilt->init_bandpass (255, 1, flo/samplerate, fhi/samplerate);
     
     	videoText();
     }
    @@ -1022,6 +1027,8 @@ void mfsk::send_epilogue()
     	flush_xmt_filter(64);
     }
     
    +static bool close_after_transmit = false;
    +
     void mfsk::clearbits()
     {
     	int data = enc->encode(0);
    @@ -1039,9 +1046,29 @@ void mfsk::clearbits()
     	}
     }
     
    -
     int mfsk::tx_process()
     {
    +	// filter test set to 1
    +#if 0
    +	double *ptr;
    +	double f;
    +	char msg[100];
    +	for (int i = 100; i < 3900; i++) {
    +		ptr = outbuf;
    +		f = 1.0 * i;
    +		snprintf(msg, sizeof(msg), "freq: %.0f", f);
    +		put_status(msg);
    +		for (int j = 0; j < 32; j++) {
    +			*ptr++ = cos(phaseacc);
    +			phaseacc += TWOPI * f / samplerate;
    +			if (phaseacc > TWOPI) phaseacc -= TWOPI;
    +		}
    +		transmit (outbuf, 32);
    +
    +	}
    +	return -1;
    +#endif
    +
     	int xmtbyte;
     
     	switch (txstate) {
    @@ -1137,6 +1164,8 @@ int mfsk::tx_process()
     			btnpicTxSendGrey->show();
     			btnpicTxLoad->show();
     			btnpicTxClose->show();
    +			if (close_after_transmit) picTxWin->hide();
    +			close_after_transmit = false;
     			abortxmt = false;
     			rxstate = RX_STATE_DATA;
     			memset(picheader, ' ', PICHEADER - 1);
    @@ -1151,6 +1180,7 @@ int mfsk::tx_process()
     void mfsk::send_color_image(std::string s)
     {
     	if (load_image(s.c_str())) {
    +		close_after_transmit = true;
     		pic_TxSendColor();
     	}
     }
    @@ -1158,6 +1188,7 @@ void mfsk::send_color_image(std::string s)
     void mfsk::send_Grey_image(std::string s)
     {
     	if (load_image(s.c_str())) {
    +		close_after_transmit = true;
     		pic_TxSendGrey();
     	}
     }
    diff --git a/src/misc/arq_io.cxx b/src/misc/arq_io.cxx
    index a8386f99..fb5f1de2 100644
    --- a/src/misc/arq_io.cxx
    +++ b/src/misc/arq_io.cxx
    @@ -528,12 +528,10 @@ bool ARQ_SOCKET_Server::start(const char* node, const char* service)
     
     void ARQ_SOCKET_Server::stop(void)
     {
    -	// FILEME - uncomment when we have an ARQ_SOCKET_Server than can be
    -	// interrupted
    -	//	if (!inst)
    -	//		return;
    -	//	delete inst;
    -	//	inst = 0;
    +	if (!inst)
    +		return;
    +	delete inst;
    +	inst = 0;
     }
     
     void* ARQ_SOCKET_Server::thread_func(void*)
    @@ -872,6 +870,7 @@ void arq_close(void)
     	// and then wait for it to die
     	pthread_join(arq_thread, NULL);
     	arq_enabled = false;
    +	LOG_INFO("ARQ closed");
     	if(data_io_enabled == ARQ_IO)
     		data_io_enabled = DISABLED_IO ;
     	arq_exit = false;
    diff --git a/src/misc/ascii.cxx b/src/misc/ascii.cxx
    index 24d4a578..36eda487 100644
    --- a/src/misc/ascii.cxx
    +++ b/src/misc/ascii.cxx
    @@ -117,7 +117,7 @@ const char *ascii2[256] = {
     
     const char *ascii3[256] = {
     	"", "", "", "", "", "", "", "",
    -	"",  "", "",  "", "",  "",  "",  "",
    +	"",  "", "\n",    "", "",  "",  "",  "",
     	"", "", "", "", "", "", "", "",
     	"", "",  "", "", "",  "",  "",  "",
     	" ",     "!",     "\"",    "#",     "$",     "%",     "&",     "\'",
    diff --git a/src/misc/configuration.cxx b/src/misc/configuration.cxx
    index 0092a9f5..e959933e 100644
    --- a/src/misc/configuration.cxx
    +++ b/src/misc/configuration.cxx
    @@ -207,26 +207,29 @@ public:
     	void write(ostream& out) const
             {
     		out << "\n" << '<' << tag << '>';
    -		for (size_t i = 0; i < modes.size(); i++)
    +		for (size_t i = 0; i < modes.size(); i++) {
     			if (!modes.test(i))
     				out << mode_info[i].name << ',';
    +		}
     		out << ",\n\n";
     	}
     	void read(const char* data)
     	{
    +		string sdata = data, smode, tstmode;
     		modes.set();
    -		for( ; data ; )
    -		{
    -			const char * comma = strchr( data, ',' );
    -			size_t tok_len = comma ? comma - data : strlen(data);
    +		size_t p = sdata.find(",");
    +		while ((p != string::npos) && (p != 0)) {
    +			smode = sdata.substr(0, p);
     
     			for (size_t i = 0; i < modes.size(); i++) {
    -				if (!strncmp(mode_info[i].name, data, tok_len )) {
    -					modes.set(i, 0);
    +				tstmode = mode_info[i].name;
    +				if (smode == tstmode) {
    +					modes.set(i,0);
     					break;
     				}
     			}
    -			data = comma ? comma + 1 : NULL ;
    +			sdata.erase(0, p+1);
    +			p = sdata.find(",");
     		}
     	}
     	mode_set_t& modes;
    @@ -526,6 +529,8 @@ int configuration::setDefaults()
     
     	inpTTYdev->value(PTTdev.c_str());
     
    +	inpGPIOPort->value(GPIOPort);
    +
     	chkUSEHAMLIB->value(0);
     	chkUSERIGCAT->value(0);
     	chkUSEXMLRPC->value(0);
    @@ -729,6 +734,8 @@ void configuration::initInterface()
     
     	PTTdev = inpTTYdev->value();
     
    +	GPIOPort = static_cast(inpGPIOPort->value());
    +
     #if USE_HAMLIB
     	chkUSEHAMLIBis = chkUSEHAMLIB->value();
          HamlibCMDptt = btnHamlibCMDptt->value();
    @@ -748,38 +755,46 @@ void configuration::initInterface()
     	listbox_baudrate->hide();
     #endif
     
    -	bool riginitOK = false;
    -
    -	if (chkUSERIGCATis) { // start the rigCAT thread
    -		if (rigCAT_init(true)) {
    +	if (connected_to_flrig) {
    +		LOG_INFO("%s", "using flrig xcvr control");
    +		wf->setQSY(1);
    +	} else if (chkUSERIGCATis) { // start the rigCAT thread
    +		if (rigCAT_init()) {
    +			LOG_INFO("%s", "using rigCAT xcvr control");
     			wf->USB(true);
     			wf->setQSY(1);
    -			riginitOK = true;
    +			rigCAT_get_pwrlevel();
    +		} else {
    +			LOG_INFO("%s", "defaulting to no xcvr control");
    +			noCAT_init();
    +			wf->USB(true);
    +			wf->setQSY(0);
    +			chkUSERIGCATis = false;
     		}
     #if USE_HAMLIB
     	} else if (chkUSEHAMLIBis) { // start the hamlib thread
     		if (hamlib_init(HamlibCMDptt)) {
    +			LOG_INFO("%s", "using HAMLIB xcvr control");
     			wf->USB(true);
     			wf->setQSY(1);
    -			riginitOK = true;
    +		} else {
    +			LOG_INFO("%s", "defaulting to no xcvr control");
    +			noCAT_init();
    +			wf->USB(true);
    +			wf->setQSY(0);
     		}
     #endif
     	} else if (chkUSEXMLRPCis) {
    -		if (rigCAT_init(false)) {
    -			LOG_VERBOSE("%s", "using XMLRPC");
    -			wf->USB(true);
    -			wf->setQSY(0);
    -			riginitOK = true;
    -		}
    -	}
    -
    -	if (riginitOK == false) {
    -		rigCAT_init(false);
    +		LOG_INFO("%s", "using XMLRPC");
    +		wf->USB(true);
    +		wf->setQSY(0);
    +	} else {
    +		LOG_INFO("%s", "No xcvr control selected");
    +		noCAT_init();
     		wf->USB(true);
     		wf->setQSY(0);
     	}
    -
    -	if (connected_to_flrig) wf->setQSY(1);
    +	build_frequencies2_list();
     
     	if (HamlibCMDptt && chkUSEHAMLIBis)
     		push2talk->reset(PTT::PTT_HAMLIB);
    @@ -789,6 +804,8 @@ void configuration::initInterface()
     		push2talk->reset(PTT::PTT_TTY);
     	else if (UsePPortPTT)
     		push2talk->reset(PTT::PTT_PARPORT);
    +	else if (UseGPIOPTT)
    +		push2talk->reset(PTT::PTT_GPIO);
     	else if (UseUHrouterPTT)
     		push2talk->reset(PTT::PTT_UHROUTER);
     	else
    @@ -929,11 +946,19 @@ void configuration::testCommPorts()
     		glob_t gbuf;
     		glob(tty_fmt[i], 0, NULL, &gbuf);
     		for (size_t j = 0; j < gbuf.gl_pathc; j++) {
    -			if ( !(stat(gbuf.gl_pathv[j], &st) == 0 && S_ISCHR(st.st_mode)) ||
    -			     strstr(gbuf.gl_pathv[j], "modem") )
    +			int ret1 = !stat(gbuf.gl_pathv[j], &st);
    +			int ret2 = S_ISCHR(st.st_mode);
    +			if (ret1) {
    +				LOG_INFO("Serial port %s", gbuf.gl_pathv[j]);
    +				LOG_INFO("  device mode:     %X", st.st_mode);
    +				LOG_INFO("  char device?     %s", ret2 ? "Y" : "N");
    +			} else
    +				LOG_INFO("%s does not return stat query", gbuf.gl_pathv[j]);
    +
    +			if ( (ret1 && ret2 ) || strstr(gbuf.gl_pathv[j], "modem") )
    +				inpTTYdev->add(gbuf.gl_pathv[j]);
    +			else
     				continue;
    -			LOG_VERBOSE("Found serial port %s", gbuf.gl_pathv[j]);
    -			inpTTYdev->add(gbuf.gl_pathv[j]);
     #  if USE_HAMLIB
     			inpRIGdev->add(gbuf.gl_pathv[j]);
     #  endif
    diff --git a/src/misc/debug.cxx b/src/misc/debug.cxx
    index 3020b604..29fecfab 100644
    --- a/src/misc/debug.cxx
    +++ b/src/misc/debug.cxx
    @@ -70,14 +70,12 @@ using namespace std;
     
     static FILE* wfile = 0;
     static FILE* rfile = 0;
    -static size_t nlines = 0;
     static int rfd;
     static bool tty;
     
     static Fl_Double_Window* window;
    +static Fl_Browser*  btext;
     
    -static Fl_Browser*			btext;
    -static string dbg_buffer;
     static string linebuf;
     
     debug* debug::inst = 0;
    @@ -101,9 +99,11 @@ Fl_Menu_Item src_menu[] = {
     	{ _("Audio"), 0, 0, 0, FL_MENU_TOGGLE | FL_MENU_VALUE },
     	{ _("Modem"), 0, 0, 0, FL_MENU_TOGGLE | FL_MENU_VALUE },
     	{ _("Rig control"), 0, 0, 0, FL_MENU_TOGGLE | FL_MENU_VALUE },
    +	{ _("Flrig I/O"), 0, 0, 0, FL_MENU_TOGGLE | FL_MENU_VALUE },
     	{ _("RPC"), 0, 0, 0, FL_MENU_TOGGLE | FL_MENU_VALUE },
     	{ _("Spotter"), 0, 0, 0, FL_MENU_TOGGLE | FL_MENU_VALUE },
    -	{ _("KISS control"), 0, 0, 0, FL_MENU_TOGGLE | FL_MENU_VALUE | FL_MENU_DIVIDER  },
    +	{ _("KISS control"), 0, 0, 0, FL_MENU_TOGGLE | FL_MENU_VALUE },
    +	{ _("Mac Logger"), 0, 0, 0, FL_MENU_TOGGLE | FL_MENU_VALUE | FL_MENU_DIVIDER },
     	{ _("Other"), 0, 0, 0, FL_MENU_TOGGLE | FL_MENU_VALUE },
     	{ 0 }
     };
    @@ -135,15 +135,15 @@ void debug::start(const char* filename)
     	rotate_log(filename);
     	inst = new debug(filename);
     
    -	window = new Fl_Double_Window(600, 200, _("Event log"));
    +	window = new Fl_Double_Window(800, 400, _("Event log"));
     	window->xclass(PACKAGE_TARNAME);
     
     	int pad = 2;
    -	Fl_Menu_Button* button = new Fl_Menu_Button(pad, pad, 128, 20, _("Log sources"));
    +	Fl_Menu_Button* button = new Fl_Menu_Button(pad, pad, 128, 22, _("Log sources"));
     	button->menu(src_menu);
     	button->callback(src_menu_cb);
     
    -	Fl_Slider* slider = new Fl_Slider(button->x() + button->w() + pad, pad, 128, 20, prefix[level]);
    +	Fl_Slider* slider = new Fl_Slider(button->x() + button->w() + pad, pad, 128, 22, prefix[level]);
     	slider->tooltip(_("Change log level"));
     	slider->align(FL_ALIGN_RIGHT);
     	slider->type(FL_HOR_NICE_SLIDER);
    @@ -152,14 +152,13 @@ void debug::start(const char* filename)
     	slider->value(level);
     	slider->callback(slider_cb);
     
    -	Fl_Button* clearbtn = new Fl_Button(window->w() - 64, pad, 60, 20, "clear");
    +	Fl_Button* clearbtn = new Fl_Button(window->w() - 64, pad, 60, 22, "clear");
     	clearbtn->callback(clear_cb);
     
     	btext = new Fl_Browser(pad,  slider->h()+pad, window->w()-2*pad, window->h()-slider->h()-2*pad, 0);
     	btext->textfont(FL_HELVETICA);
     	btext->textsize(14);
     	window->resizable(btext);
    -	dbg_buffer.clear();
     
     	window->end();
     }
    @@ -170,6 +169,7 @@ void debug::stop(void)
     	if (window) {
     		window->hide();
     		delete window;
    +		window = 0;
     	}
     	if (inst) {
     		delete inst;
    @@ -178,6 +178,7 @@ void debug::stop(void)
     }
     
     static char fmt[1024];
    +static char dtext[16384];
     
     void debug::log(level_e level, const char* func, const char* srcf, int line, const char* format, ...)
     {
    @@ -185,7 +186,8 @@ void debug::log(level_e level, const char* func, const char* srcf, int line, con
     
     	if (!inst)
     		return;
    -	if (unlikely(debug::level == DEBUG_LEVEL) || debug_pskmail || debug_audio) {
    +	if (unlikely(debug::level == DEBUG_LEVEL) || 
    +		debug_pskmail || debug_audio) {
     		time_t t = time(NULL);
     		struct tm stm;
     		(void)localtime_r(&t, &stm);
    @@ -196,13 +198,13 @@ void debug::log(level_e level, const char* func, const char* srcf, int line, con
     		snprintf(fmt, sizeof(fmt), "%c: %s: %s\n", *prefix[level], func, format);
     	va_list args;
     	va_start(args, format);
    -	intptr_t nw = vfprintf(wfile, fmt, args);
    +	intptr_t nt = vsnprintf(dtext, sizeof(dtext), fmt, args);
     	va_end(args);
    +
    +	fprintf(wfile, "%s", dtext);
     	if (tty) {
     		if (level <= DEBUG_LEVEL && level > QUIET_LEVEL) {
    -			va_start(args, format);
    -			vfprintf(stderr, fmt, args);
    -			va_end(args);
    +			fprintf(stderr, "%s", dtext);
     		}
     	}
     
    @@ -210,7 +212,8 @@ void debug::log(level_e level, const char* func, const char* srcf, int line, con
     	fflush(wfile);
     #endif
     
    -	Fl::awake(sync_text, (void*)nw);
    +	linebuf.append(dtext);
    +	Fl::awake(sync_text, (void*)nt);
     }
     
     void debug::hex_dump(const char* func, const char * data, int length)
    @@ -266,37 +269,24 @@ void debug::elog(const char* func, const char* srcf, int line, const char* text)
     
     void debug::show(void)
     {
    +	btext->bottomline(btext->size());
     	window->show();
     }
     
    -static char buf[BUFSIZ+1];
    -
     void debug::sync_text(void* arg)
     {
    -	intptr_t toread = (intptr_t)arg;
    -	size_t block = MIN((size_t)toread, sizeof(buf) - 1);
    -	ssize_t n;
    +	guard_lock debug_lock(&debug_mutex);
     
    -	while (toread > 0) {
    -		if ((n = read(rfd, buf, block)) <= 0)
    -			break;
    -		if (unlikely(++nlines > MAX_LINES)) {
    -			btext->clear();
    -			nlines = 0;
    -		}
    -		buf[n] = '\0';
    -		linebuf = buf;
    -		if (linebuf[linebuf.length() - 1] != '\n')
    -			linebuf += '\n';
    -		size_t p1 = 0, p2 = linebuf.find("\n");
    -		while( p2 != string::npos) {
    -			btext->insert(1, linebuf.substr(p1, p2 - p1).c_str());
    -			dbg_buffer.append(linebuf.substr(p1, p2 - p1)).append("\n");
    -			p1 = p2 + 1;
    -			p2 = linebuf.find("\n", p1);
    -		}
    -		toread -= n;
    +	size_t p1 = 0, p2 = linebuf.find("\n");
    +	while (p2 != string::npos) {
    +		btext->add(linebuf.substr(p1, p2 - p1).c_str());
    +		p1 = p2 + 1;
    +		p2 = linebuf.find("\n", p1);
     	}
    +	btext->redraw();
    +	btext->bottomline(btext->size());
    +	linebuf.clear();
    +	return;
     }
     
     debug::debug(const char* filename)
    @@ -318,6 +308,7 @@ debug::debug(const char* filename)
     		throw strerror(errno);
     #endif
     	tty = isatty(fileno(stderr));
    +	linebuf.clear();
     }
     
     debug::~debug()
    @@ -340,7 +331,8 @@ static void src_menu_cb(Fl_Widget* w, void*)
     
     static void clear_cb(Fl_Widget* w, void*)
     {
    +	guard_lock debug_lock(&debug_mutex);
     	btext->clear();
    -	dbg_buffer.clear();
    +	linebuf.clear();
     }
     
    diff --git a/src/misc/dxcc.cxx b/src/misc/dxcc.cxx
    index f80956fd..486b7c13 100644
    --- a/src/misc/dxcc.cxx
    +++ b/src/misc/dxcc.cxx
    @@ -85,9 +85,16 @@ bool dxcc_open(const char* filename)
     
     	cmap = new dxcc_map_t;
     	cnames = new vector;
    -	cnames->reserve(345); // approximate number of dxcc entities
    +
    +// this MUST be greater than the actual number of dcxx entities or
    +// the Windows gcc string library will move all of the strings and
    +// destroy the integrity of the cmap c_str() pointer to the country
    +// string in cnames
    +
    +	cnames->reserve(500); // approximate number of dxcc entities
    +	
     	clist = new dxcc_list_t;
    -	clist->reserve(345);
    +	clist->reserve(500);
     
     	dxcc* entry;
     	string record;
    @@ -175,9 +182,9 @@ const dxcc* dxcc_lookup(const char* callsign)
     	// first look for a full callsign (prefixed with '=')
     	sstr[0] = '=';
     	dxcc_map_t::const_iterator entry = cmap->find(sstr);
    -	if (entry != cmap->end())
    +	if (entry != cmap->end()) {
     		return entry->second;
    -
    +}
     	// erase the '=' and do a longest prefix search
     	sstr.erase(0, 1);
     	size_t len = sstr.length();
    @@ -192,8 +199,9 @@ const dxcc* dxcc_lookup(const char* callsign)
     	}
     	do {
     		sstr.resize(len--);
    -		if ((entry = cmap->find(sstr)) != cmap->end())
    +		if ((entry = cmap->find(sstr)) != cmap->end()) {
     			return entry->second;
    +		}
     	} while (len);
     
     	return NULL;
    diff --git a/src/misc/kiss_io.cxx b/src/misc/kiss_io.cxx
    index 5a02f852..d6c52e24 100644
    --- a/src/misc/kiss_io.cxx
    +++ b/src/misc/kiss_io.cxx
    @@ -91,14 +91,16 @@ static pthread_mutex_t to_host_arq_mutex   = PTHREAD_MUTEX_INITIALIZER;
     static pthread_mutex_t to_host_mutex       = PTHREAD_MUTEX_INITIALIZER;
     static pthread_mutex_t to_radio_mutex      = PTHREAD_MUTEX_INITIALIZER;
     static pthread_mutex_t external_mutex      = PTHREAD_MUTEX_INITIALIZER;
    +static pthread_mutex_t restart_mutex       = PTHREAD_MUTEX_INITIALIZER;
     
     bool kiss_enabled = false;
     bool kiss_exit = false;
     bool kiss_rx_exit = false;
    +bool allow_kiss_socket_io = false;
     
     static bool smack_crc_enabled  = false;
     static int crc_mode            = CRC16_CCITT;
    -static std::string default_kiss_modem = "PSK63RC5";
    +static std::string default_kiss_modem = "BPSK250";
     static std::string kiss_modem = "";
     static unsigned int transmit_buffer_flush_timeout = 0;
     
    @@ -129,6 +131,7 @@ bool kiss_bcast_rsid_reception  = false;
     bool kiss_bcast_trx_toggle      = false;
     bool kiss_text_available        = false;
     static bool kiss_reset_flag     = false;
    +static int  retry_count         = KISS_CONNECT_RETRY_COUNT;
     
     #define HISTO_COUNT 256
     #define HISTO_THRESH_HOLD 48
    @@ -147,6 +150,7 @@ static double kpsql_threshold = 0.0;
     extern int IMAGE_WIDTH;
     Socket *kiss_socket = 0;
     int data_io_enabled = DISABLED_IO;
    +int data_io_type    = DATA_IO_UDP;
     //static bool host_responded = false;
     
     // Used to scale the sensitivity of KPSQL
    @@ -165,6 +169,8 @@ extern void abort_tx();
     static std::vector availabe_kiss_modems;
     
     extern void ax25_decode(unsigned char *buffer, size_t count, bool pad, bool tx_flag);
    +static void kiss_main_thread_close(void *ptr);
    +static void kiss_main_thread_retry_open(void *ptr);
     
     static int kiss_raw_enabled = KISS_RAW_DISABLED;
     
    @@ -174,95 +180,96 @@ static int kiss_raw_enabled = KISS_RAW_DISABLED;
      * between real values and translated values.
      **********************************************************************************/
     static int not_allowed[256] = {
    -	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, //  16
    -	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //  32
    -	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //  48
    -	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //  64
    -	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //  80
    -	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //  96
    -	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 112
    -	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, // 128
    -	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 144
    -	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 160
    -	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 176
    -	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 192
    -	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 208
    -	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 224
    -	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 240
    -	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1  // 256
    +    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, //  16
    +    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //  32
    +    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //  48
    +    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //  64
    +    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //  80
    +    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //  96
    +    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 112
    +    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, // 128
    +    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 144
    +    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 160
    +    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 176
    +    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 192
    +    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 208
    +    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 224
    +    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 240
    +    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1  // 256
     };
     
     /**********************************************************************************
      * KISS hardware frame commands strings and calling functions
      **********************************************************************************/
     EXEC_HARDWARE_CMD_MATCH exec_match[] = {
    -	{ (char *) "BCHN",      set_busy_channel_on_off },
    -	{ (char *) "BCHNS",     set_busy_channel_duration },
    -	{ (char *) "BUSY",      reply_busy_state },
    -	{ (char *) "CSMA",      set_csma_mode },
    -	{ (char *) "FLSTAT",    reply_fldigi_stat },
    -	{ (char *) "IBCHN",     set_busy_channel_inhibit },
    -	{ (char *) "KISSCRCM",  set_crc_mode },
    -	{ (char *) "KISSRAW",   set_kiss_raw_mode },
    -	{ (char *) "KPSQL",     set_kpsql_on_off },
    -	{ (char *) "KPSATT",    set_kpsql_fraction_gain },
    -	{ (char *) "KPSQLP",    reply_kpsql_pwr_level },
    -	{ (char *) "KPSQLS",    set_kpsql_squelch_level },
    -	{ (char *) "MODEM",     set_kiss_modem },
    -	{ (char *) "MODEMBW",   reply_active_modem_bw },
    -	{ (char *) "MODEML",    reply_modem_list },
    -	{ (char *) "RSIDBCAST", set_rsid_bc_mode },
    -	{ (char *) "RSIDM",     set_rsid_mode },
    -	{ (char *) "RSIDRX",    set_rsid_rx },
    -	{ (char *) "RSIDTX",    set_rsid_tx },
    -	{ (char *) "SQL",       set_sql_on_off },
    -	{ (char *) "SQLP",      reply_sql_pwr_level },
    -	{ (char *) "SQLS",      set_sql_level },
    -	{ (char *) "TNC",       reply_tnc_name },
    -	{ (char *) "TRXSBCAST", set_trxs_bc_mode },
    -	{ (char *) "TRXS",      reply_trx_state },
    -	{ (char *) "TXBEBCAST", set_txbe_bc_mode },
    -	{ (char *) "TXBUF",     reply_tx_buffer_count },
    -	{ (char *) "WFBW",      reply_waterfall_bw },
    -	{ (char *) "WFF",       set_wf_cursor_pos },
    -	{ (char *) 0,           0 }
    +    { (char *) "BCHN",      set_busy_channel_on_off },
    +    { (char *) "BCHNS",     set_busy_channel_duration },
    +    { (char *) "BUSY",      reply_busy_state },
    +    { (char *) "CSMA",      set_csma_mode },
    +    { (char *) "FLSTAT",    reply_fldigi_stat },
    +    { (char *) "IBCHN",     set_busy_channel_inhibit },
    +    { (char *) "KISSCRCM",  set_crc_mode },
    +    { (char *) "KISSRAW",   set_kiss_raw_mode },
    +    { (char *) "KPSQL",     set_kpsql_on_off },
    +    { (char *) "KPSATT",    set_kpsql_fraction_gain },
    +    { (char *) "KPSQLP",    reply_kpsql_pwr_level },
    +    { (char *) "KPSQLS",    set_kpsql_squelch_level },
    +    { (char *) "MODEM",     set_kiss_modem },
    +    { (char *) "MODEMBW",   reply_active_modem_bw },
    +    { (char *) "MODEML",    reply_modem_list },
    +    { (char *) "RSIDBCAST", set_rsid_bc_mode },
    +    { (char *) "RSIDM",     set_rsid_mode },
    +    { (char *) "RSIDRX",    set_rsid_rx },
    +    { (char *) "RSIDTX",    set_rsid_tx },
    +    { (char *) "SQL",       set_sql_on_off },
    +    { (char *) "SQLP",      reply_sql_pwr_level },
    +    { (char *) "SQLS",      set_sql_level },
    +    { (char *) "TNC",       reply_tnc_name },
    +    { (char *) "TRXSBCAST", set_trxs_bc_mode },
    +    { (char *) "TRXS",      reply_trx_state },
    +    { (char *) "TXBEBCAST", set_txbe_bc_mode },
    +    { (char *) "TXBUF",     reply_tx_buffer_count },
    +    { (char *) "TXLOCK",    set_reply_tx_lock },
    +    { (char *) "WFBW",      reply_waterfall_bw },
    +    { (char *) "WFF",       set_wf_cursor_pos },
    +    { (char *) 0,           0 }
     };
     
     
     #ifdef USE_NOCTRL
     static const char *asc[128] = {
    -	"", "", "", "",
    -	"", "", "", "",
    -	"",  "", "\n",    "",
    -	"",  "",      "",  "",
    -	"", "", "", "",
    -	"", "", "", "",
    -	"", "",  "", "",
    -	"",  "",  "",  "",
    -	" ",     "!",     "\"",    "#",
    -	"$",     "%",     "&",     "\'",
    -	"(",     ")",     "*",     "+",
    -	",",     "-",     ".",     "/",
    -	"0",     "1",     "2",     "3",
    -	"4",     "5",     "6",     "7",
    -	"8",     "9",     ":",     ";",
    -	"<",     "=",     ">",     "?",
    -	"@",     "A",     "B",     "C",
    -	"D",     "E",     "F",     "G",
    -	"H",     "I",     "J",     "K",
    -	"L",     "M",     "N",     "O",
    -	"P",     "Q",     "R",     "S",
    -	"T",     "U",     "V",     "W",
    -	"X",     "Y",     "Z",     "[",
    -	"\\",    "]",     "^",     "_",
    -	"`",     "a",     "b",     "c",
    -	"d",     "e",     "f",     "g",
    -	"h",     "i",     "j",     "k",
    -	"l",     "m",     "n",     "o",
    -	"p",     "q",     "r",     "s",
    -	"t",     "u",     "v",     "w",
    -	"x",     "y",     "z",     "{",
    -	"|",     "}",     "~",     ""
    +    "", "", "", "",
    +    "", "", "", "",
    +    "",  "", "\n",    "",
    +    "",  "",      "",  "",
    +    "", "", "", "",
    +    "", "", "", "",
    +    "", "",  "", "",
    +    "",  "",  "",  "",
    +    " ",     "!",     "\"",    "#",
    +    "$",     "%",     "&",     "\'",
    +    "(",     ")",     "*",     "+",
    +    ",",     "-",     ".",     "/",
    +    "0",     "1",     "2",     "3",
    +    "4",     "5",     "6",     "7",
    +    "8",     "9",     ":",     ";",
    +    "<",     "=",     ">",     "?",
    +    "@",     "A",     "B",     "C",
    +    "D",     "E",     "F",     "G",
    +    "H",     "I",     "J",     "K",
    +    "L",     "M",     "N",     "O",
    +    "P",     "Q",     "R",     "S",
    +    "T",     "U",     "V",     "W",
    +    "X",     "Y",     "Z",     "[",
    +    "\\",    "]",     "^",     "_",
    +    "`",     "a",     "b",     "c",
    +    "d",     "e",     "f",     "g",
    +    "h",     "i",     "j",     "k",
    +    "l",     "m",     "n",     "o",
    +    "p",     "q",     "r",     "s",
    +    "t",     "u",     "v",     "w",
    +    "x",     "y",     "z",     "{",
    +    "|",     "}",     "~",     ""
     };
     
     /**********************************************************************************
    @@ -270,20 +277,20 @@ static const char *asc[128] = {
      **********************************************************************************/
     static string noctrl(string src)
     {
    -	static string retstr;
    -	retstr.clear();
    -	char hexstr[10];
    -	int c;
    -	for (size_t i = 0; i < src.length(); i++)  {
    -		c = src[i];
    -		if ( c > 0 && c < 128)
    -			retstr.append(asc[c]);
    -		else {
    -			snprintf(hexstr, sizeof(hexstr), "<%0X>", c & 0xFF);
    -			retstr.append(hexstr);
    -		}
    -	}
    -	return retstr;
    +    static string retstr;
    +    retstr.clear();
    +    char hexstr[10];
    +    int c;
    +    for (size_t i = 0; i < src.length(); i++)  {
    +        c = src[i];
    +        if ( c > 0 && c < 128)
    +            retstr.append(asc[c]);
    +        else {
    +            snprintf(hexstr, sizeof(hexstr), "<%0X>", c & 0xFF);
    +            retstr.append(hexstr);
    +        }
    +    }
    +    return retstr;
     }
     #endif // USE_NOCTRL
     
    @@ -292,46 +299,46 @@ static string noctrl(string src)
      **********************************************************************************/
     static int  calc_ccitt_crc(char *buf, int n)
     {
    -	static int  crc_table[] = {
    -		0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241,
    -		0xc601, 0x06c0, 0x0780, 0xc741, 0x0500, 0xc5c1, 0xc481, 0x0440,
    -		0xcc01, 0xcc0,  0x0d80, 0xcd41, 0x0f00, 0xcfc1, 0xce81, 0x0e40,
    -		0x0a00, 0xcac1, 0xcb81, 0x0b40, 0xc901, 0x09c0, 0x0880, 0xc841,
    -		0xd801, 0x18c0, 0x1980, 0xd941, 0x1b00, 0xdbc1, 0xda81, 0x1a40,
    -		0x1e00, 0xdec1, 0xdf81, 0x1f40, 0xdd01, 0x1dc0, 0x1c80, 0xdc41,
    -		0x1400, 0xd4c1, 0xd581, 0x1540, 0xd701, 0x17c0, 0x1680, 0xd641,
    -		0xd201, 0x12c0, 0x1380, 0xd341, 0x1100, 0xd1c1, 0xd081, 0x1040,
    -		0xf001, 0x30c0, 0x3180, 0xf141, 0x3300, 0xf3c1, 0xf281, 0x3240,
    -		0x3600, 0xf6c1, 0xf781, 0x3740, 0xf501, 0x35c0, 0x3480, 0xf441,
    -		0x3c00, 0xfcc1, 0xfd81, 0x3d40, 0xff01, 0x3fc0, 0x3e80, 0xfe41,
    -		0xfa01, 0x3ac0, 0x3b80, 0xfb41, 0x3900, 0xf9c1, 0xf881, 0x3840,
    -		0x2800, 0xe8c1, 0xe981, 0x2940, 0xeb01, 0x2bc0, 0x2a80, 0xea41,
    -		0xee01, 0x2ec0, 0x2f80, 0xef41, 0x2d00, 0xedc1, 0xec81, 0x2c40,
    -		0xe401, 0x24c0, 0x2580, 0xe541, 0x2700, 0xe7c1, 0xe681, 0x2640,
    -		0x2200, 0xe2c1, 0xe381, 0x2340, 0xe101, 0x21c0, 0x2080, 0xe041,
    -		0xa001, 0x60c0, 0x6180, 0xa141, 0x6300, 0xa3c1, 0xa281, 0x6240,
    -		0x6600, 0xa6c1, 0xa781, 0x6740, 0xa501, 0x65c0, 0x6480, 0xa441,
    -		0x6c00, 0xacc1, 0xad81, 0x6d40, 0xaf01, 0x6fc0, 0x6e80, 0xae41,
    -		0xaa01, 0x6ac0, 0x6b80, 0xab41, 0x6900, 0xa9c1, 0xa881, 0x6840,
    -		0x7800, 0xb8c1, 0xb981, 0x7940, 0xbb01, 0x7bc0, 0x7a80, 0xba41,
    -		0xbe01, 0x7ec0, 0x7f80, 0xbf41, 0x7d00, 0xbdc1, 0xbc81, 0x7c40,
    -		0xb401, 0x74c0, 0x7580, 0xb541, 0x7700, 0xb7c1, 0xb681, 0x7640,
    -		0x7200, 0xb2c1, 0xb381, 0x7340, 0xb101, 0x71c0, 0x7080, 0xb041,
    -		0x5000, 0x90c1, 0x9181, 0x5140, 0x9301, 0x53c0, 0x5280, 0x9241,
    -		0x9601, 0x56c0, 0x5780, 0x9741, 0x5500, 0x95c1, 0x9481, 0x5440,
    -		0x9c01, 0x5cc0, 0x5d80, 0x9d41, 0x5f00, 0x9fc1, 0x9e81, 0x5e40,
    -		0x5a00, 0x9ac1, 0x9b81, 0x5b40, 0x9901, 0x59c0, 0x5880, 0x9841,
    -		0x8801, 0x48c0, 0x4980, 0x8941, 0x4b00, 0x8bc1, 0x8a81, 0x4a40,
    -		0x4e00, 0x8ec1, 0x8f81, 0x4f40, 0x8d01, 0x4dc0, 0x4c80, 0x8c41,
    -		0x4400, 0x84c1, 0x8581, 0x4540, 0x8701, 0x47c0, 0x4680, 0x8641,
    -		0x8201, 0x42c0, 0x4380, 0x8341, 0x4100, 0x81c1, 0x8081, 0x4040
    -	};
    +    static int  crc_table[] = {
    +        0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241,
    +        0xc601, 0x06c0, 0x0780, 0xc741, 0x0500, 0xc5c1, 0xc481, 0x0440,
    +        0xcc01, 0xcc0,  0x0d80, 0xcd41, 0x0f00, 0xcfc1, 0xce81, 0x0e40,
    +        0x0a00, 0xcac1, 0xcb81, 0x0b40, 0xc901, 0x09c0, 0x0880, 0xc841,
    +        0xd801, 0x18c0, 0x1980, 0xd941, 0x1b00, 0xdbc1, 0xda81, 0x1a40,
    +        0x1e00, 0xdec1, 0xdf81, 0x1f40, 0xdd01, 0x1dc0, 0x1c80, 0xdc41,
    +        0x1400, 0xd4c1, 0xd581, 0x1540, 0xd701, 0x17c0, 0x1680, 0xd641,
    +        0xd201, 0x12c0, 0x1380, 0xd341, 0x1100, 0xd1c1, 0xd081, 0x1040,
    +        0xf001, 0x30c0, 0x3180, 0xf141, 0x3300, 0xf3c1, 0xf281, 0x3240,
    +        0x3600, 0xf6c1, 0xf781, 0x3740, 0xf501, 0x35c0, 0x3480, 0xf441,
    +        0x3c00, 0xfcc1, 0xfd81, 0x3d40, 0xff01, 0x3fc0, 0x3e80, 0xfe41,
    +        0xfa01, 0x3ac0, 0x3b80, 0xfb41, 0x3900, 0xf9c1, 0xf881, 0x3840,
    +        0x2800, 0xe8c1, 0xe981, 0x2940, 0xeb01, 0x2bc0, 0x2a80, 0xea41,
    +        0xee01, 0x2ec0, 0x2f80, 0xef41, 0x2d00, 0xedc1, 0xec81, 0x2c40,
    +        0xe401, 0x24c0, 0x2580, 0xe541, 0x2700, 0xe7c1, 0xe681, 0x2640,
    +        0x2200, 0xe2c1, 0xe381, 0x2340, 0xe101, 0x21c0, 0x2080, 0xe041,
    +        0xa001, 0x60c0, 0x6180, 0xa141, 0x6300, 0xa3c1, 0xa281, 0x6240,
    +        0x6600, 0xa6c1, 0xa781, 0x6740, 0xa501, 0x65c0, 0x6480, 0xa441,
    +        0x6c00, 0xacc1, 0xad81, 0x6d40, 0xaf01, 0x6fc0, 0x6e80, 0xae41,
    +        0xaa01, 0x6ac0, 0x6b80, 0xab41, 0x6900, 0xa9c1, 0xa881, 0x6840,
    +        0x7800, 0xb8c1, 0xb981, 0x7940, 0xbb01, 0x7bc0, 0x7a80, 0xba41,
    +        0xbe01, 0x7ec0, 0x7f80, 0xbf41, 0x7d00, 0xbdc1, 0xbc81, 0x7c40,
    +        0xb401, 0x74c0, 0x7580, 0xb541, 0x7700, 0xb7c1, 0xb681, 0x7640,
    +        0x7200, 0xb2c1, 0xb381, 0x7340, 0xb101, 0x71c0, 0x7080, 0xb041,
    +        0x5000, 0x90c1, 0x9181, 0x5140, 0x9301, 0x53c0, 0x5280, 0x9241,
    +        0x9601, 0x56c0, 0x5780, 0x9741, 0x5500, 0x95c1, 0x9481, 0x5440,
    +        0x9c01, 0x5cc0, 0x5d80, 0x9d41, 0x5f00, 0x9fc1, 0x9e81, 0x5e40,
    +        0x5a00, 0x9ac1, 0x9b81, 0x5b40, 0x9901, 0x59c0, 0x5880, 0x9841,
    +        0x8801, 0x48c0, 0x4980, 0x8941, 0x4b00, 0x8bc1, 0x8a81, 0x4a40,
    +        0x4e00, 0x8ec1, 0x8f81, 0x4f40, 0x8d01, 0x4dc0, 0x4c80, 0x8c41,
    +        0x4400, 0x84c1, 0x8581, 0x4540, 0x8701, 0x47c0, 0x4680, 0x8641,
    +        0x8201, 0x42c0, 0x4380, 0x8341, 0x4100, 0x81c1, 0x8081, 0x4040
    +    };
     
    -	int crc;
    -	crc = 0;
    -	while (--n >= 0)
    -		crc = ((crc >> 8) & 0xff) ^ crc_table[(crc ^ *buf++) & 0xff];
    -	return crc;
    +    int crc;
    +    crc = 0;
    +    while (--n >= 0)
    +        crc = ((crc >> 8) & 0xff) ^ crc_table[(crc ^ *buf++) & 0xff];
    +    return crc;
     }
     
     /**********************************************************************************
    @@ -339,11 +346,11 @@ static int  calc_ccitt_crc(char *buf, int n)
      **********************************************************************************/
     static int  calc_xor_crc(char *buf, int n)
     {
    -	int crc;
    -	crc = 0;
    -	while (--n >= 0)
    -		crc ^= (*buf++ & 0xff);
    -	return crc;
    +    int crc;
    +    crc = 0;
    +    while (--n >= 0)
    +        crc ^= (*buf++ & 0xff);
    +    return crc;
     }
     
     /**********************************************************************************
    @@ -352,46 +359,46 @@ static int  calc_xor_crc(char *buf, int n)
     static int  calc_fcs_crc(char *buf, int n)
     {
     
    -	static int fcstab[256] = {
    -		0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
    -		0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
    -		0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
    -		0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
    -		0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
    -		0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
    -		0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
    -		0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
    -		0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
    -		0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
    -		0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
    -		0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
    -		0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
    -		0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
    -		0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
    -		0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
    -		0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
    -		0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
    -		0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
    -		0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
    -		0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
    -		0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
    -		0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
    -		0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
    -		0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
    -		0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
    -		0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
    -		0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
    -		0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
    -		0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
    -		0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
    -		0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
    -	};
    +    static int fcstab[256] = {
    +        0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
    +        0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
    +        0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
    +        0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
    +        0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
    +        0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
    +        0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
    +        0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
    +        0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
    +        0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
    +        0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
    +        0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
    +        0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
    +        0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
    +        0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
    +        0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
    +        0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
    +        0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
    +        0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
    +        0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
    +        0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
    +        0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
    +        0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
    +        0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
    +        0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
    +        0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
    +        0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
    +        0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
    +        0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
    +        0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
    +        0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
    +        0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
    +    };
     
    -	int crc;
    -	crc = 0xFFFF;
    -	while (--n >= 0)
    -		crc = ((crc >> 8) & 0xff) ^ fcstab[(crc ^ *buf++) & 0xff];
    -	return crc;
    +    int crc;
    +    crc = 0xFFFF;
    +    while (--n >= 0)
    +        crc = ((crc >> 8) & 0xff) ^ fcstab[(crc ^ *buf++) & 0xff];
    +    return crc;
     }
     
     /**********************************************************************************
    @@ -399,8 +406,8 @@ static int  calc_fcs_crc(char *buf, int n)
      **********************************************************************************/
     static void set_button(Fl_Button * button, bool value)
     {
    -	button->value(value);
    -	button->do_callback();
    +    button->value(value);
    +    button->do_callback();
     }
     
     
    @@ -409,8 +416,8 @@ static void set_button(Fl_Button * button, bool value)
      **********************************************************************************/
     static void set_counter(Fl_Counter * counter, int value)
     {
    -	counter->value(value);
    -	counter->do_callback();
    +    counter->value(value);
    +    counter->do_callback();
     }
     
     /**********************************************************************************
    @@ -418,45 +425,49 @@ static void set_counter(Fl_Counter * counter, int value)
      **********************************************************************************/
     static void set_slider2(Fl_Slider2 * sider, int value)
     {
    -	sider->value(value);
    -	sider->do_callback();
    +    sider->value(value);
    +    sider->do_callback();
     }
     
    -
     /**********************************************************************************
      *
      **********************************************************************************/
    -/*
    -static void set_valuator(Fl_Valuator* valuator, double value)
    +bool valid_kiss_modem(string _modem)
     {
    -	valuator->value(value);
    -	valuator->do_callback();
    -}
    -*/
    -/**********************************************************************************
    - *
    - **********************************************************************************/
    -static bool valid_kiss_modem(string _modem)
    -{
    -	if(_modem.empty()) return false;
    +    if(_modem.empty()) return false;
     
    -	int index = 0;
    -	int count = availabe_kiss_modems.size();
    +    int index = 0;
    +    int count = availabe_kiss_modems.size();
    +    std::string _tmp_str;
     
    -	std::string cmp_str = "";
    +    if(count < 1) {
     
    -	while(index < count) {
    -		cmp_str = uppercase_string(availabe_kiss_modems[index]);
    -		if(cmp_str.empty()) return false;
    +        for(index = 0; index < NUM_MODES; index++) {
    +            if(mode_info[index].iface_io & KISS_IO) {
    +                _tmp_str = uppercase_string(mode_info[index].sname);
    +                availabe_kiss_modems.push_back(_tmp_str);
    +            }
    +        }
    +        count = availabe_kiss_modems.size();
    +    }
     
    -		if(_modem.compare(cmp_str) == 0) {
    -			return true;
    -		}
    +    std::string cmp_str = "";
    +    index = 0;
     
    -		index++;
    -	}
    +    _modem = uppercase_string(_modem);
     
    -	return false;
    +    while(index < count) {
    +        cmp_str = availabe_kiss_modems[index];
    +        if(cmp_str.empty()) return false;
    +
    +        if(_modem.compare(cmp_str) == 0) {
    +            return true;
    +        }
    +
    +        index++;
    +    }
    +
    +    return false;
     }
     
     /**********************************************************************************
    @@ -464,13 +475,13 @@ static bool valid_kiss_modem(string _modem)
      **********************************************************************************/
     void check_kiss_modem(void)
     {
    -	int mode = active_modem->get_mode();
    -	std::string modem_name;
    -	modem_name.assign(mode_info[mode].sname);
    -	bool valid = valid_kiss_modem(modem_name);
    +    int mode = active_modem->get_mode();
    +    std::string modem_name;
    +    modem_name.assign(mode_info[mode].sname);
    +    bool valid = valid_kiss_modem(modem_name);
     
    -	if(!valid)
    -		set_default_kiss_modem();
    +    if(!valid)
    +        set_default_kiss_modem();
     }
     
     /**********************************************************************************
    @@ -478,7 +489,7 @@ void check_kiss_modem(void)
      **********************************************************************************/
     static void set_default_kiss_modem(void)
     {
    -	set_kiss_modem((char *) default_kiss_modem.c_str());
    +    set_kiss_modem((char *) default_kiss_modem.c_str());
     }
     
     
    @@ -487,19 +498,19 @@ static void set_default_kiss_modem(void)
      **********************************************************************************/
     inline std::string uppercase_string(std::string str)
     {
    -	int index = 0;
    -	int count = str.size();
    -	std::string ret_str = "";
    +    int index = 0;
    +    int count = str.size();
    +    std::string ret_str = "";
     
    -	if(!count) return ret_str;
    +    if(!count) return ret_str;
     
    -	ret_str.reserve(count + 1);
    -	ret_str.clear();
    +    ret_str.reserve(count + 1);
    +    ret_str.clear();
     
    -	for(index = 0; index < count; index++)
    -		ret_str += toupper(str[index]);
    +    for(index = 0; index < count; index++)
    +        ret_str += toupper(str[index]);
     
    -	return ret_str;
    +    return ret_str;
     }
     
     /**********************************************************************************
    @@ -507,35 +518,37 @@ inline std::string uppercase_string(std::string str)
      **********************************************************************************/
     static void set_kiss_modem(char * arg)
     {
    -	if(!arg) return;
    +    if(!arg) return;
     
    -	std::string _modem = "";
    -	std::string _cmp_modem = "";
    +    std::string _modem = "";
    +    std::string _cmp_modem = "";
     
    -	_modem.assign(arg);
    +    _modem.assign(arg);
     
    -	if(_modem.empty()) {
    -		return reply_active_modem(arg);
    -	}
    +    if(_modem.empty()) {
    +        return reply_active_modem(arg);
    +    }
     
    -	bool valid = valid_kiss_modem(_modem);
    +    bool valid = valid_kiss_modem(_modem);
     
    -	if(valid) {
    -		for (size_t i = 0; i < NUM_MODES; i++) {
    -			_cmp_modem = uppercase_string(mode_info[i].sname);
    -			if (_modem == _cmp_modem) {
    -				REQ_SYNC(init_modem_sync, i, 0);
    -				kiss_modem.assign(_modem);
    -				break;
    -			}
    -		}
    -		return;
    -	}
    +    _modem = uppercase_string(_modem);
     
    -	if(!valid)
    -		LOG_INFO("Modem %s invalid for KISS use. Must support 8bit.", _modem.c_str());
    +    if(valid) {
    +        for (size_t i = 0; i < NUM_MODES; i++) {
    +            _cmp_modem = uppercase_string(mode_info[i].sname);
    +            if (_modem == _cmp_modem) {
    +                REQ_SYNC(init_modem_sync, i, 0);
    +                kiss_modem.assign(_modem);
    +                break;
    +            }
    +        }
    +        return;
    +    }
     
    -	return;
    +    if(!valid)
    +        LOG_INFO("Modem %s invalid for KISS use. Must support 8bit.", _modem.c_str());
    +
    +    return;
     }
     
     /**********************************************************************************
    @@ -543,45 +556,45 @@ static void set_kiss_modem(char * arg)
      **********************************************************************************/
     static void reply_fldigi_stat(char *arg)
     {
    -	std::string package = "";
    -	std::string cmd = "FLSTAT:";
    +    std::string package = "";
    +    std::string cmd = "FLSTAT:";
     
    -	unsigned int hours = 0;
    -	unsigned int mins = 0;
    -	unsigned int secs = 0;
    +    unsigned int hours = 0;
    +    unsigned int mins = 0;
    +    unsigned int secs = 0;
     
    -	time_t current_time = time(0);
    -	time_t diff_time = 0;
    +    time_t current_time = time(0);
    +    time_t diff_time = 0;
     
    -	char buffer[64];
    +    char buffer[64];
     
    -	package.assign(cmd);
    +    package.assign(cmd);
     
    -	if(program_started_flag) {
    -		package.append("OK");
    -	} else {
    -		package.append("INIT");
    -		program_started_flag = true;
    -	}
    +    if(program_started_flag) {
    +        package.append("OK");
    +    } else {
    +        package.append("INIT");
    +        program_started_flag = true;
    +    }
     
    -	if(program_start_time == 0)
    -		program_start_time = time(0);
    +    if(program_start_time == 0)
    +        program_start_time = time(0);
     
    -	diff_time = current_time - program_start_time;
    +    diff_time = current_time - program_start_time;
     
    -	hours = (unsigned int) (diff_time / 3600);
    -	diff_time -= (time_t) (hours * 3600);
    +    hours = (unsigned int) (diff_time / 3600);
    +    diff_time -= (time_t) (hours * 3600);
     
    -	mins = (unsigned int)(diff_time / 60);
    -	diff_time -= (time_t) (mins * 60);
    +    mins = (unsigned int)(diff_time / 60);
    +    diff_time -= (time_t) (mins * 60);
     
    -	secs = (unsigned int) diff_time;
    +    secs = (unsigned int) diff_time;
     
    -	memset(buffer, 0, sizeof(buffer));
    -	snprintf(buffer, sizeof(buffer)-1, ",%02u:%02u:%02u", hours, mins, secs);
    -	package.append(buffer);
    +    memset(buffer, 0, sizeof(buffer));
    +    snprintf(buffer, sizeof(buffer)-1, ",%02u:%02u:%02u", hours, mins, secs);
    +    package.append(buffer);
     
    -	kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
    +    kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
     
     }
     
    @@ -591,26 +604,26 @@ static void reply_fldigi_stat(char *arg)
      **********************************************************************************/
     static void set_csma_mode(char * arg)
     {
    -	if(!arg)
    -		return;
    +    if(!arg)
    +        return;
     
    -	std::string rsid_tx_state = "";
    -	rsid_tx_state.assign(arg);
    +    std::string rsid_tx_state = "";
    +    rsid_tx_state.assign(arg);
     
    -	if(rsid_tx_state.empty())
    -		return reply_csma_mode(arg);
    +    if(rsid_tx_state.empty())
    +        return reply_csma_mode(arg);
     
    -	std::string state = uppercase_string(rsid_tx_state);
    +    std::string state = uppercase_string(rsid_tx_state);
     
    -	if(state.find("ON") != std::string::npos) {
    -		REQ(set_button, btnEnable_csma, 1);
    -		return;
    -	}
    +    if(state.find("ON") != std::string::npos) {
    +        REQ(set_button, btnEnable_csma, 1);
    +        return;
    +    }
     
    -	if(state.find("OFF") != std::string::npos) {
    -		REQ(set_button, btnEnable_csma, 0);
    -		return;
    -	}
    +    if(state.find("OFF") != std::string::npos) {
    +        REQ(set_button, btnEnable_csma, 0);
    +        return;
    +    }
     }
     
     /**********************************************************************************
    @@ -618,17 +631,17 @@ static void set_csma_mode(char * arg)
      **********************************************************************************/
     static void reply_csma_mode(char *arg)
     {
    -	std::string package = "";
    -	std::string cmd = "CSMA:";
    +    std::string package = "";
    +    std::string cmd = "CSMA:";
     
    -	package.assign(cmd);
    +    package.assign(cmd);
     
    -	if(progdefaults.csma_enabled)
    -		package.append("ON");
    -	else
    -		package.append("OFF");
    +    if(progdefaults.csma_enabled)
    +        package.append("ON");
    +    else
    +        package.append("OFF");
     
    -	kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
    +    kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
     
     }
     
    @@ -640,38 +653,38 @@ static void reply_csma_mode(char *arg)
      **********************************************************************************/
     static void set_busy_channel_inhibit(char *arg)
     {
    -	std::string argstr = "";
    -	time_t temp = 0;
    +    std::string argstr = "";
    +    time_t temp = 0;
     
    -	if(arg) {
    -		argstr.assign(arg);
    -		if(!argstr.empty()) {
    -			if(argstr[0] == 'I' || argstr[0] == 'i') {
    -				if(progdefaults.enableBusyChannel && inhibit_tx_seconds) {
    -					temp_disable_tx_inhibit = time(0) + temp_disable_tx_duration;
    -				}
    -			} else if(isdigit(argstr[0])) {
    -				sscanf(arg, "%lu", &temp);
    -				if(temp == 0)
    -					temp_disable_tx_duration = DISABLE_TX_INHIBIT_DURATION;
    -				else
    -					temp_disable_tx_duration = temp;
    -			}
    -			return;
    -		}
    -	}
    +    if(arg) {
    +        argstr.assign(arg);
    +        if(!argstr.empty()) {
    +            if(argstr[0] == 'I' || argstr[0] == 'i') {
    +                if(progdefaults.enableBusyChannel && inhibit_tx_seconds) {
    +                    temp_disable_tx_inhibit = time(0) + temp_disable_tx_duration;
    +                }
    +            } else if(isdigit(argstr[0])) {
    +                sscanf(arg, "%lu", &temp);
    +                if(temp == 0)
    +                    temp_disable_tx_duration = DISABLE_TX_INHIBIT_DURATION;
    +                else
    +                    temp_disable_tx_duration = temp;
    +            }
    +            return;
    +        }
    +    }
     
    -	std::string cmd = "IBCHN:";
    -	std::string package = "";
    -	char buff[32];
    +    std::string cmd = "IBCHN:";
    +    std::string package = "";
    +    char buff[32];
     
    -	package.assign(cmd);
    +    package.assign(cmd);
     
    -	memset(buff, 0, sizeof(buff));
    -	snprintf(buff, sizeof(buff)-1, "%lu", temp_disable_tx_duration);
    -	package.append(buff);
    +    memset(buff, 0, sizeof(buff));
    +    snprintf(buff, sizeof(buff)-1, "%lu", temp_disable_tx_duration);
    +    package.append(buff);
     
    -	kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
    +    kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
     }
     
     /**********************************************************************************
    @@ -679,21 +692,21 @@ static void set_busy_channel_inhibit(char *arg)
      **********************************************************************************/
     static void set_kpsql_fraction_gain(char *arg)
     {
    -	if(!arg) return;
    -	std::string args;
    +    if(!arg) return;
    +    std::string args;
     
    -	args.assign(arg);
    +    args.assign(arg);
     
    -	if(args.empty())
    -		return reply_kpsql_fraction_gain(arg);
    +    if(args.empty())
    +        return reply_kpsql_fraction_gain(arg);
     
    -	unsigned int value = 0;
    +    unsigned int value = 0;
     
    -	sscanf(args.c_str(), "%u", &value);
    +    sscanf(args.c_str(), "%u", &value);
     
    -	update_kpsql_fractional_gain(value);
    +    update_kpsql_fractional_gain(value);
     
    -	REQ(set_counter, cntKPSQLAttenuation, progdefaults.kpsql_attenuation);
    +    REQ(set_counter, cntKPSQLAttenuation, progdefaults.kpsql_attenuation);
     }
     
     /**********************************************************************************
    @@ -701,15 +714,15 @@ static void set_kpsql_fraction_gain(char *arg)
      **********************************************************************************/
     void update_kpsql_fractional_gain(int value)
     {
    -	guard_lock external_lock(&external_mutex);
    +    guard_lock external_lock(&external_mutex);
     
    -	if(value > 1) {
    -		progdefaults.kpsql_attenuation = value;
    -		fractional_gain = 1.0 / ((double) value);
    -	} else {
    -		progdefaults.kpsql_attenuation = FGD_DEFAULT;
    -		fractional_gain = 1.0 / ( 1.0 * FGD_DEFAULT);
    -	}
    +    if(value > 1) {
    +        progdefaults.kpsql_attenuation = value;
    +        fractional_gain = 1.0 / ((double) value);
    +    } else {
    +        progdefaults.kpsql_attenuation = FGD_DEFAULT;
    +        fractional_gain = 1.0 / ( 1.0 * FGD_DEFAULT);
    +    }
     }
     
     /**********************************************************************************
    @@ -717,17 +730,17 @@ void update_kpsql_fractional_gain(int value)
      **********************************************************************************/
     static void reply_kpsql_fraction_gain(char *arg)
     {
    -	std::string package = "";
    -	std::string cmd = "KPSATT:";
    -	char buffer[128];
    +    std::string package = "";
    +    std::string cmd = "KPSATT:";
    +    char buffer[128];
     
    -	package.assign(cmd);
    -	memset(buffer, 0, sizeof(buffer));
    +    package.assign(cmd);
    +    memset(buffer, 0, sizeof(buffer));
     
    -	snprintf(buffer, sizeof(buffer)-1, "%u", progdefaults.kpsql_attenuation);
    -	package.append(buffer);
    +    snprintf(buffer, sizeof(buffer)-1, "%u", progdefaults.kpsql_attenuation);
    +    package.append(buffer);
     
    -	kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
    +    kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
     
     }
     
    @@ -736,25 +749,25 @@ static void reply_kpsql_fraction_gain(char *arg)
      **********************************************************************************/
     static void set_wf_cursor_pos(char * arg)
     {
    -	if(!arg) return;
    +    if(!arg) return;
     
    -	std::string wf_cursor_pos = "";
    -	wf_cursor_pos.assign(arg);
    +    std::string wf_cursor_pos = "";
    +    wf_cursor_pos.assign(arg);
     
    -	if(wf_cursor_pos.empty())
    -		return reply_wf_freq_pos(arg);
    +    if(wf_cursor_pos.empty())
    +        return reply_wf_freq_pos(arg);
     
    -	int cursor = 0;
    -	int mode_bw = active_modem->get_bandwidth();
    +    int cursor = 0;
    +    int mode_bw = active_modem->get_bandwidth();
     
    -	sscanf(wf_cursor_pos.c_str(), "%d", &cursor);
    +    sscanf(wf_cursor_pos.c_str(), "%d", &cursor);
     
    -	mode_bw >>= 1;
    +    mode_bw >>= 1;
     
    -	if((cursor - mode_bw) < 0) cursor = mode_bw;
    -	if((cursor + mode_bw) >= IMAGE_WIDTH) cursor = IMAGE_WIDTH - mode_bw;
    +    if((cursor - mode_bw) < 0) cursor = mode_bw;
    +    if((cursor + mode_bw) >= IMAGE_WIDTH) cursor = IMAGE_WIDTH - mode_bw;
     
    -	active_modem->set_freq((double) cursor);
    +    active_modem->set_freq((double) cursor);
     
     }
     
    @@ -763,26 +776,26 @@ static void set_wf_cursor_pos(char * arg)
      **********************************************************************************/
     static void set_rsid_tx(char * arg)
     {
    -	if(!arg)
    -		return;
    +    if(!arg)
    +        return;
     
    -	std::string rsid_tx_state = "";
    -	rsid_tx_state.assign(arg);
    +    std::string rsid_tx_state = "";
    +    rsid_tx_state.assign(arg);
     
    -	if(rsid_tx_state.empty())
    -		return reply_rsid_tx_state(arg);
    +    if(rsid_tx_state.empty())
    +        return reply_rsid_tx_state(arg);
     
    -	std::string state = uppercase_string(rsid_tx_state);
    +    std::string state = uppercase_string(rsid_tx_state);
     
    -	if(state.find("ON") != std::string::npos) {
    -		REQ(set_button, btnTxRSID, 1);
    -		return;
    -	}
    +    if(state.find("ON") != std::string::npos) {
    +        REQ(set_button, btnTxRSID, 1);
    +        return;
    +    }
     
    -	if(state.find("OFF") != std::string::npos) {
    -		REQ(set_button, btnTxRSID, 0);
    -		return;
    -	}
    +    if(state.find("OFF") != std::string::npos) {
    +        REQ(set_button, btnTxRSID, 0);
    +        return;
    +    }
     }
     
     /**********************************************************************************
    @@ -790,27 +803,27 @@ static void set_rsid_tx(char * arg)
      **********************************************************************************/
     static void set_rsid_rx(char *arg)
     {
    -	if(!arg)
    -		return;
    +    if(!arg)
    +        return;
     
    -	std::string rsid_rx_state = "";
    +    std::string rsid_rx_state = "";
     
    -	rsid_rx_state.assign(arg);
    +    rsid_rx_state.assign(arg);
     
    -	if(rsid_rx_state.empty())
    -		return reply_rsid_rx_state(arg);
    +    if(rsid_rx_state.empty())
    +        return reply_rsid_rx_state(arg);
     
    -	std::string state = uppercase_string(rsid_rx_state);
    +    std::string state = uppercase_string(rsid_rx_state);
     
    -	if(state.find("ON") != std::string::npos) {
    -		REQ(set_button, btnRSID, 1);
    -		return;
    -	}
    +    if(state.find("ON") != std::string::npos) {
    +        REQ(set_button, btnRSID, 1);
    +        return;
    +    }
     
    -	if(state.find("OFF") != std::string::npos) {
    -		REQ(set_button, btnRSID, 0);
    -		return;
    -	}
    +    if(state.find("OFF") != std::string::npos) {
    +        REQ(set_button, btnRSID, 0);
    +        return;
    +    }
     }
     
     /**********************************************************************************
    @@ -818,33 +831,33 @@ static void set_rsid_rx(char *arg)
      **********************************************************************************/
     static void set_rsid_mode(char *arg)
     {
    -	if(!arg)
    -		return;
    +    if(!arg)
    +        return;
     
    -	std::string strarg = "";
    +    std::string strarg = "";
     
    -	strarg.assign(arg);
    +    strarg.assign(arg);
     
    -	if(strarg.empty())
    -		return reply_rsid_mode_state(arg);
    +    if(strarg.empty())
    +        return reply_rsid_mode_state(arg);
     
    -	std::string state = uppercase_string(strarg);
    +    std::string state = uppercase_string(strarg);
     
    -	if(state.find("BANDPASS") != std::string::npos) {
    -		REQ(set_button, chkRSidWideSearch, 1);
    -	}
    +    if(state.find("BANDPASS") != std::string::npos) {
    +        REQ(set_button, chkRSidWideSearch, 1);
    +    }
     
    -	if(state.find("MODEM") != std::string::npos) {
    -		REQ(set_button, chkRSidWideSearch, 0);
    -	}
    +    if(state.find("MODEM") != std::string::npos) {
    +        REQ(set_button, chkRSidWideSearch, 0);
    +    }
     
    -	if(state.find("NOTIFY") != std::string::npos) {
    -		REQ(set_button, chkRSidNotifyOnly, 1);
    -	}
    +    if(state.find("NOTIFY") != std::string::npos) {
    +        REQ(set_button, chkRSidNotifyOnly, 1);
    +    }
     
    -	if(state.find("ACTIVE") != std::string::npos) {
    -		REQ(set_button, chkRSidNotifyOnly, 0);
    -	}
    +    if(state.find("ACTIVE") != std::string::npos) {
    +        REQ(set_button, chkRSidNotifyOnly, 0);
    +    }
     }
     
     /**********************************************************************************
    @@ -852,27 +865,27 @@ static void set_rsid_mode(char *arg)
      **********************************************************************************/
     static void set_rsid_bc_mode(char * arg)
     {
    -	if(!arg)
    -		return;
    +    if(!arg)
    +        return;
     
    -	std::string strarg = "";
    +    std::string strarg = "";
     
    -	strarg.assign(arg);
    +    strarg.assign(arg);
     
    -	if(strarg.empty())
    -		return reply_rsid_bc_mode(arg);
    +    if(strarg.empty())
    +        return reply_rsid_bc_mode(arg);
     
    -	std::string state = uppercase_string(strarg);
    +    std::string state = uppercase_string(strarg);
     
    -	if(state.find("ON") != std::string::npos) {
    -		kiss_bcast_rsid_reception = true;
    -		return;
    -	}
    +    if(state.find("ON") != std::string::npos) {
    +        kiss_bcast_rsid_reception = true;
    +        return;
    +    }
     
    -	if(state.find("OFF") != std::string::npos) {
    -		kiss_bcast_rsid_reception = false;
    -		return;
    -	}
    +    if(state.find("OFF") != std::string::npos) {
    +        kiss_bcast_rsid_reception = false;
    +        return;
    +    }
     }
     
     /**********************************************************************************
    @@ -880,17 +893,17 @@ static void set_rsid_bc_mode(char * arg)
      **********************************************************************************/
     static void reply_rsid_bc_mode(char * arg)
     {
    -	std::string package = "";
    -	std::string cmd = "RSIDBCAST:";
    +    std::string package = "";
    +    std::string cmd = "RSIDBCAST:";
     
    -	package.assign(cmd);
    +    package.assign(cmd);
     
    -	if(kiss_bcast_rsid_reception)
    -		package.append("ON");
    -	else
    -		package.append("OFF");
    +    if(kiss_bcast_rsid_reception)
    +        package.append("ON");
    +    else
    +        package.append("OFF");
     
    -	kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
    +    kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
     }
     
     /**********************************************************************************
    @@ -898,27 +911,27 @@ static void reply_rsid_bc_mode(char * arg)
      **********************************************************************************/
     static void set_trxs_bc_mode(char * arg)
     {
    -	if(!arg)
    -		return;
    +    if(!arg)
    +        return;
     
    -	std::string strarg = "";
    +    std::string strarg = "";
     
    -	strarg.assign(arg);
    +    strarg.assign(arg);
     
    -	if(strarg.empty())
    -		return reply_trxs_bc_mode(arg);
    +    if(strarg.empty())
    +        return reply_trxs_bc_mode(arg);
     
    -	std::string state = uppercase_string(strarg);
    +    std::string state = uppercase_string(strarg);
     
    -	if(state.find("ON") != std::string::npos) {
    -		kiss_bcast_trx_toggle = true;
    -		return;
    -	}
    +    if(state.find("ON") != std::string::npos) {
    +        kiss_bcast_trx_toggle = true;
    +        return;
    +    }
     
    -	if(state.find("OFF") != std::string::npos) {
    -		kiss_bcast_trx_toggle = false;
    -		return;
    -	}
    +    if(state.find("OFF") != std::string::npos) {
    +        kiss_bcast_trx_toggle = false;
    +        return;
    +    }
     }
     
     /**********************************************************************************
    @@ -926,17 +939,17 @@ static void set_trxs_bc_mode(char * arg)
      **********************************************************************************/
     static void reply_trxs_bc_mode(char * arg)
     {
    -	std::string package = "";
    -	std::string cmd = "TRXSBCAST:";
    +    std::string package = "";
    +    std::string cmd = "TRXSBCAST:";
     
    -	package.assign(cmd);
    +    package.assign(cmd);
     
    -	if(kiss_bcast_trx_toggle)
    -		package.append("ON");
    -	else
    -		package.append("OFF");
    +    if(kiss_bcast_trx_toggle)
    +        package.append("ON");
    +    else
    +        package.append("OFF");
     
    -	kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
    +    kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
     }
     
     /**********************************************************************************
    @@ -944,27 +957,27 @@ static void reply_trxs_bc_mode(char * arg)
      **********************************************************************************/
     static void set_txbe_bc_mode(char * arg)
     {
    -	if(!arg)
    -		return;
    +    if(!arg)
    +        return;
     
    -	std::string strarg = "";
    +    std::string strarg = "";
     
    -	strarg.assign(arg);
    +    strarg.assign(arg);
     
    -	if(strarg.empty())
    -		return reply_txbe_bc_mode(arg);
    +    if(strarg.empty())
    +        return reply_txbe_bc_mode(arg);
     
    -	std::string state = uppercase_string(strarg);
    +    std::string state = uppercase_string(strarg);
     
    -	if(state.find("ON") != std::string::npos) {
    -		bcast_tx_buffer_empty_flag = true;
    -		return;
    -	}
    +    if(state.find("ON") != std::string::npos) {
    +        bcast_tx_buffer_empty_flag = true;
    +        return;
    +    }
     
    -	if(state.find("OFF") != std::string::npos) {
    -		bcast_tx_buffer_empty_flag = false;
    -		return;
    -	}
    +    if(state.find("OFF") != std::string::npos) {
    +        bcast_tx_buffer_empty_flag = false;
    +        return;
    +    }
     }
     
     /**********************************************************************************
    @@ -972,17 +985,17 @@ static void set_txbe_bc_mode(char * arg)
      **********************************************************************************/
     static void reply_txbe_bc_mode(char * arg)
     {
    -	std::string package = "";
    -	std::string cmd = "TXBEBCAST:";
    +    std::string package = "";
    +    std::string cmd = "TXBEBCAST:";
     
    -	package.assign(cmd);
    +    package.assign(cmd);
     
    -	if(bcast_tx_buffer_empty_flag)
    -		package.append("ON");
    -	else
    -		package.append("OFF");
    +    if(bcast_tx_buffer_empty_flag)
    +        package.append("ON");
    +    else
    +        package.append("OFF");
     
    -	kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
    +    kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
     }
     
     /**********************************************************************************
    @@ -990,12 +1003,12 @@ static void reply_txbe_bc_mode(char * arg)
      **********************************************************************************/
     static void reply_tnc_name(char * arg)
     {
    -	std::string package = "";
    -	std::string cmd = "TNC:";
    +    std::string package = "";
    +    std::string cmd = "TNC:";
     
    -	package.assign(cmd).append("FLDIGI ").append(PACKAGE_VERSION);
    +    package.assign(cmd).append("FLDIGI ").append(PACKAGE_VERSION);
     
    -	kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
    +    kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
     }
     
     /**********************************************************************************
    @@ -1003,17 +1016,17 @@ static void reply_tnc_name(char * arg)
      **********************************************************************************/
     static void reply_trx_state(char * arg)
     {
    -	std::string package = "";
    -	std::string cmd = "TRXS:";
    +    std::string package = "";
    +    std::string cmd = "TRXS:";
     
    -	package.assign(cmd);
    +    package.assign(cmd);
     
    -	if((trx_state == STATE_TX) || (trx_state == STATE_TUNE))
    -		package.append("TX");
    -	else
    -		package.append("RX");
    +    if((trx_state == STATE_TX) || (trx_state == STATE_TUNE))
    +        package.append("TX");
    +    else
    +        package.append("RX");
     
    -	kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
    +    kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
     }
     
     /**********************************************************************************
    @@ -1021,17 +1034,17 @@ static void reply_trx_state(char * arg)
      **********************************************************************************/
     static void reply_rsid_rx_state(char * arg)
     {
    -	std::string package = "";
    -	std::string cmd = "RSIDRX:";
    +    std::string package = "";
    +    std::string cmd = "RSIDRX:";
     
    -	package.assign(cmd);
    +    package.assign(cmd);
     
    -	if(progdefaults.rsid)
    -		package.append("ON");
    -	else
    -		package.append("OFF");
    +    if(progdefaults.rsid)
    +        package.append("ON");
    +    else
    +        package.append("OFF");
     
    -	kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
    +    kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
     }
     
     /**********************************************************************************
    @@ -1039,17 +1052,60 @@ static void reply_rsid_rx_state(char * arg)
      **********************************************************************************/
     static void reply_rsid_tx_state(char * arg)
     {
    -	std::string package = "";
    -	std::string cmd = "RSIDTX:";
    +    std::string package = "";
    +    std::string cmd = "RSIDTX:";
     
    -	package.assign(cmd);
    +    package.assign(cmd);
     
    -	if(progdefaults.TransmitRSid)
    -		package.append("ON");
    -	else
    -		package.append("OFF");
    +    if(progdefaults.TransmitRSid)
    +        package.append("ON");
    +    else
    +        package.append("OFF");
     
    -	kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
    +    kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
    +}
    +
    +/**********************************************************************************
    + *  TXLOCK:  FLDIGI TXLOCK: or without arg return lock state.
    + **********************************************************************************/
    +static void set_reply_tx_lock(char * arg)
    +{
    +    if(!arg) return;
    +
    +    std::string strarg = "";
    +    std::string package = "";
    +    std::string cmd = "TXLOCK:";
    +
    +    strarg.assign(arg);
    +
    +    if(strarg.empty()) {
    +        package.assign(cmd);
    +
    +        if (!active_modem)
    +            package.append("INOP");
    +        else if(active_modem->freqlocked())
    +            package.append("ON");
    +        else
    +            package.append("OFF");
    +
    +        kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
    +
    +        return;
    +    }
    +
    +    if (!active_modem) return;
    +
    +    if(strarg.find("ON") != std::string::npos) {
    +        active_modem->set_freqlock(true);
    +        REQ(set_button, (Fl_Button *) wf->xmtlock, 1);
    +        return;
    +    }
    +
    +    if(strarg.find("OFF") != std::string::npos) {
    +        active_modem->set_freqlock(false);
    +        REQ(set_button, (Fl_Button *) wf->xmtlock, 0);
    +        return;
    +    }
     }
     
     /**********************************************************************************
    @@ -1057,18 +1113,18 @@ static void reply_rsid_tx_state(char * arg)
      **********************************************************************************/
     static void reply_wf_freq_pos(char * arg)
     {
    -	std::string package = "";
    -	std::string cmd = "WFF:";
    -	char buff[32];
    +    std::string package = "";
    +    std::string cmd = "WFF:";
    +    char buff[32];
     
    -	package.assign(cmd);
    +    package.assign(cmd);
     
    -	memset(buff, 0, sizeof(buff));
    -	snprintf(buff, sizeof(buff) - 1, "%d", (int) active_modem->get_txfreq());
    +    memset(buff, 0, sizeof(buff));
    +    snprintf(buff, sizeof(buff) - 1, "%d", (int) active_modem->get_txfreq());
     
    -	package.append(buff);
    +    package.append(buff);
     
    -	kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
    +    kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
     }
     
     /**********************************************************************************
    @@ -1076,22 +1132,22 @@ static void reply_wf_freq_pos(char * arg)
      **********************************************************************************/
     static void reply_rsid_mode_state(char * arg)
     {
    -	std::string package = "";
    -	std::string cmd = "RSIDM:";
    +    std::string package = "";
    +    std::string cmd = "RSIDM:";
     
    -	package.assign(cmd);
    +    package.assign(cmd);
     
    -	if(progdefaults.rsidWideSearch)
    -		package.append("BANDPASS,");
    -	else
    -		package.append("MODEM,");
    +    if(progdefaults.rsidWideSearch)
    +        package.append("BANDPASS,");
    +    else
    +        package.append("MODEM,");
     
    -	if(progdefaults.rsid_notify_only)
    -		package.append("NOTIFY");
    -	else
    -		package.append("ACTIVE");
    +    if(progdefaults.rsid_notify_only)
    +        package.append("NOTIFY");
    +    else
    +        package.append("ACTIVE");
     
    -	kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
    +    kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
     }
     
     /**********************************************************************************
    @@ -1099,13 +1155,13 @@ static void reply_rsid_mode_state(char * arg)
      **********************************************************************************/
     static void reply_active_modem(char * arg)
     {
    -	std::string package = "";
    -	std::string cmd = "MODEM:";
    -	int mode = active_modem->get_mode();
    -	package.assign(cmd);
    -	package.append(mode_info[mode].sname);
    +    std::string package = "";
    +    std::string cmd = "MODEM:";
    +    int mode = active_modem->get_mode();
    +    package.assign(cmd);
    +    package.append(mode_info[mode].sname);
     
    -	kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
    +    kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
     }
     
     /**********************************************************************************
    @@ -1113,16 +1169,16 @@ static void reply_active_modem(char * arg)
      **********************************************************************************/
     static void reply_active_modem_bw(char * arg)
     {
    -	std::string package = "";
    -	std::string cmd = "MODEMBW:";
    -	char buff[32];
    +    std::string package = "";
    +    std::string cmd = "MODEMBW:";
    +    char buff[32];
     
    -	memset(buff, 0, sizeof(buff));
    -	snprintf(buff, sizeof(buff) - 1, "%d", (int) active_modem->get_bandwidth());
    +    memset(buff, 0, sizeof(buff));
    +    snprintf(buff, sizeof(buff) - 1, "%d", (int) active_modem->get_bandwidth());
     
    -	package.assign(cmd).append(buff);
    +    package.assign(cmd).append(buff);
     
    -	kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
    +    kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
     }
     
     /**********************************************************************************
    @@ -1130,17 +1186,17 @@ static void reply_active_modem_bw(char * arg)
      **********************************************************************************/
     static void reply_waterfall_bw(char * arg)
     {
    -	std::string package = "";
    -	std::string cmd = "WFBW:";
    -	char buff[32];
    +    std::string package = "";
    +    std::string cmd = "WFBW:";
    +    char buff[32];
     
    -	memset(buff, 0, sizeof(buff));
    -	snprintf(buff, sizeof(buff) - 1, "%d,%d", (int) progdefaults.LowFreqCutoff,
    -			 progdefaults.HighFreqCutoff );
    +    memset(buff, 0, sizeof(buff));
    +    snprintf(buff, sizeof(buff) - 1, "%d,%d", (int) progdefaults.LowFreqCutoff,
    +             progdefaults.HighFreqCutoff );
     
    -	package.assign(cmd).append(buff);
    +    package.assign(cmd).append(buff);
     
    -	kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
    +    kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
     }
     
     /**********************************************************************************
    @@ -1149,20 +1205,20 @@ static void reply_waterfall_bw(char * arg)
      **********************************************************************************/
     static void reply_modem_list(char * arg)
     {
    -	int index = 0;
    -	int count = 0;
    -	std::string package = "";
    -	std::string cmd = "MODEML:";
    +    int index = 0;
    +    int count = 0;
    +    std::string package = "";
    +    std::string cmd = "MODEML:";
     
    -	package.assign(cmd);
    +    package.assign(cmd);
     
    -	count = availabe_kiss_modems.size();
    +    count = availabe_kiss_modems.size();
     
    -	for(index = 0; index < count - 1; index++)
    -		package.append(availabe_kiss_modems[index]).append(",");
    -	package.append(availabe_kiss_modems[index]);
    +    for(index = 0; index < count - 1; index++)
    +        package.append(availabe_kiss_modems[index]).append(",");
    +    package.append(availabe_kiss_modems[index]);
     
    -	kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
    +    kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
     }
     
     /**********************************************************************************
    @@ -1170,32 +1226,32 @@ static void reply_modem_list(char * arg)
      **********************************************************************************/
     static void reply_tx_buffer_count(char * arg)
     {
    -	char *buffer = (char *)0;
    -	unsigned int buffer_size = 64;
    -	unsigned tx_buffer_count = 0;
    -	std::string package = "";
    -	std::string cmd = "TXBUF:";
    +    char *buffer = (char *)0;
    +    unsigned int buffer_size = 64;
    +    unsigned tx_buffer_count = 0;
    +    std::string package = "";
    +    std::string cmd = "TXBUF:";
     
    -	buffer = new char[buffer_size];
    +    buffer = new char[buffer_size];
     
    -	if(!buffer) {
    -		LOG_DEBUG("%s", "Buffer allocation Error");
    -		return;
    -	}
    +    if(!buffer) {
    +        LOG_DEBUG("%s", "Buffer allocation Error");
    +        return;
    +    }
     
    -	{
    -		guard_lock to_radio_lock(&to_radio_mutex);
    -		tx_buffer_count = to_radio.size();
    -	}
    +    {
    +        guard_lock to_radio_lock(&to_radio_mutex);
    +        tx_buffer_count = to_radio.size();
    +    }
     
    -	memset(buffer, 0, buffer_size);
    -	snprintf(buffer, buffer_size - 1, "%u", tx_buffer_count);
    +    memset(buffer, 0, buffer_size);
    +    snprintf(buffer, buffer_size - 1, "%u", tx_buffer_count);
     
    -	package.assign(cmd).append(buffer);
    +    package.assign(cmd).append(buffer);
     
    -	kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
    +    kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
     
    -	if(buffer) delete [] buffer;
    +    if(buffer) delete [] buffer;
     
     }
     
    @@ -1204,25 +1260,25 @@ static void reply_tx_buffer_count(char * arg)
      **********************************************************************************/
     static void set_sql_on_off(char * arg)
     {
    -	if(!arg)
    -		return;
    +    if(!arg)
    +        return;
     
    -	std::string strarg = "";
    +    std::string strarg = "";
     
    -	strarg.assign(arg);
    +    strarg.assign(arg);
     
    -	if(strarg.empty())
    -		return reply_sql_on_off(arg);
    +    if(strarg.empty())
    +        return reply_sql_on_off(arg);
     
    -	if(strarg.find("ON") != std::string::npos) {
    -		REQ(set_button, btnSQL, 1);
    -		return;
    -	}
    +    if(strarg.find("ON") != std::string::npos) {
    +        REQ(set_button, btnSQL, 1);
    +        return;
    +    }
     
    -	if(strarg.find("OFF") != std::string::npos) {
    -		REQ(set_button, btnSQL, 0);
    -		return;
    -	}
    +    if(strarg.find("OFF") != std::string::npos) {
    +        REQ(set_button, btnSQL, 0);
    +        return;
    +    }
     }
     
     /**********************************************************************************
    @@ -1230,17 +1286,17 @@ static void set_sql_on_off(char * arg)
      **********************************************************************************/
     static void reply_sql_on_off(char * arg)
     {
    -	std::string package = "";
    -	std::string cmd = "SQL:";
    +    std::string package = "";
    +    std::string cmd = "SQL:";
     
    -	package.assign(cmd);
    +    package.assign(cmd);
     
    -	if(progStatus.sqlonoff)
    -		package.append("ON");
    -	else
    -		package.append("OFF");
    +    if(progStatus.sqlonoff)
    +        package.append("ON");
    +    else
    +        package.append("OFF");
     
    -	kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
    +    kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
     }
     
     /**********************************************************************************
    @@ -1248,17 +1304,17 @@ static void reply_sql_on_off(char * arg)
      **********************************************************************************/
     static void reply_sql_pwr_level(char * arg)
     {
    -	std::string package = "";
    -	std::string cmd = "SQLP:";
    -	char buffer[64];
    +    std::string package = "";
    +    std::string cmd = "SQLP:";
    +    char buffer[64];
     
    -	package.assign(cmd);
    +    package.assign(cmd);
     
    -	memset(buffer, 0, sizeof(buffer));
    -	snprintf(buffer, sizeof(buffer)-1, "%u", (unsigned int) progStatus.squelch_value);
    -	package.append(buffer);
    +    memset(buffer, 0, sizeof(buffer));
    +    snprintf(buffer, sizeof(buffer)-1, "%u", (unsigned int) progStatus.squelch_value);
    +    package.append(buffer);
     
    -	kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
    +    kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
     
     }
     
    @@ -1267,25 +1323,25 @@ static void reply_sql_pwr_level(char * arg)
      **********************************************************************************/
     static void set_sql_level(char * arg)
     {
    -	if(!arg)
    -		return;
    -	int value = 0;
    +    if(!arg)
    +        return;
    +    int value = 0;
     
    -	std::string strarg = "";
    +    std::string strarg = "";
     
    -	strarg.assign(arg);
    +    strarg.assign(arg);
     
    -	if(strarg.empty())
    -		return reply_sql_level(arg);
    +    if(strarg.empty())
    +        return reply_sql_level(arg);
     
    -	sscanf(strarg.c_str(), "%d", &value);
    -	if(value < 1) value = 1;
    -	if(value > 100) value = 100;
    +    sscanf(strarg.c_str(), "%d", &value);
    +    if(value < 1) value = 1;
    +    if(value > 100) value = 100;
     
    -	progStatus.sldrSquelchValue = value;
    +    progStatus.sldrSquelchValue = value;
     
    -	if(!progStatus.pwrsqlonoff)
    -		REQ(set_slider2, sldrSquelch, value);
    +    if(!progStatus.kpsql_enabled)
    +        REQ(set_slider2, sldrSquelch, value);
     }
     
     /**********************************************************************************
    @@ -1293,17 +1349,17 @@ static void set_sql_level(char * arg)
      **********************************************************************************/
     static void reply_sql_level(char * arg)
     {
    -	std::string package = "";
    -	std::string cmd = "SQLS:";
    -	char buffer[64];
    +    std::string package = "";
    +    std::string cmd = "SQLS:";
    +    char buffer[64];
     
    -	package.assign(cmd);
    +    package.assign(cmd);
     
    -	memset(buffer, 0, sizeof(buffer));
    -	snprintf(buffer, sizeof(buffer)-1, "%u", (unsigned int) progStatus.sldrSquelchValue);
    -	package.append(buffer);
    +    memset(buffer, 0, sizeof(buffer));
    +    snprintf(buffer, sizeof(buffer)-1, "%u", (unsigned int) progStatus.sldrSquelchValue);
    +    package.append(buffer);
     
    -	kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
    +    kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
     }
     
     /**********************************************************************************
    @@ -1311,25 +1367,25 @@ static void reply_sql_level(char * arg)
      **********************************************************************************/
     static void set_busy_channel_on_off(char * arg)
     {
    -	if(!arg)
    -		return;
    +    if(!arg)
    +        return;
     
    -	std::string strarg = "";
    +    std::string strarg = "";
     
    -	strarg.assign(arg);
    +    strarg.assign(arg);
     
    -	if(strarg.empty())
    -		return reply_busy_channel_on_off(arg);
    +    if(strarg.empty())
    +        return reply_busy_channel_on_off(arg);
     
    -	if(strarg.find("ON") != std::string::npos) {
    -		REQ(set_button, btnEnableBusyChannel, 1);
    -		return;
    -	}
    +    if(strarg.find("ON") != std::string::npos) {
    +        REQ(set_button, btnEnableBusyChannel, 1);
    +        return;
    +    }
     
    -	if(strarg.find("OFF") != std::string::npos) {
    -		REQ(set_button, btnEnableBusyChannel, 0);
    -		return;
    -	}
    +    if(strarg.find("OFF") != std::string::npos) {
    +        REQ(set_button, btnEnableBusyChannel, 0);
    +        return;
    +    }
     
     }
     
    @@ -1338,17 +1394,17 @@ static void set_busy_channel_on_off(char * arg)
      **********************************************************************************/
     static void reply_busy_channel_on_off(char * arg)
     {
    -	std::string package = "";
    -	std::string cmd = "BCHN:";
    +    std::string package = "";
    +    std::string cmd = "BCHN:";
     
    -	package.assign(cmd);
    +    package.assign(cmd);
     
    -	if(progdefaults.enableBusyChannel)
    -		package.append("ON");
    -	else
    -		package.append("OFF");
    +    if(progdefaults.enableBusyChannel)
    +        package.append("ON");
    +    else
    +        package.append("OFF");
     
    -	kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
    +    kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
     }
     
     /**********************************************************************************
    @@ -1356,20 +1412,20 @@ static void reply_busy_channel_on_off(char * arg)
      **********************************************************************************/
     static void set_busy_channel_duration(char * arg)
     {
    -	if(!arg)
    -		return;
    -	int value = 0;
    -	std::string strarg = "";
    +    if(!arg)
    +        return;
    +    int value = 0;
    +    std::string strarg = "";
     
    -	strarg.assign(arg);
    +    strarg.assign(arg);
     
    -	if(strarg.empty())
    -		return reply_busy_channel_duration(arg);
    +    if(strarg.empty())
    +        return reply_busy_channel_duration(arg);
     
    -	sscanf(strarg.c_str(), "%d", &value);
    -	if(value < 1) value = 1;
    +    sscanf(strarg.c_str(), "%d", &value);
    +    if(value < 1) value = 1;
     
    -	REQ(set_counter, cntBusyChannelSeconds, value);
    +    REQ(set_counter, cntBusyChannelSeconds, value);
     }
     
     /**********************************************************************************
    @@ -1377,17 +1433,17 @@ static void set_busy_channel_duration(char * arg)
      **********************************************************************************/
     static void reply_busy_channel_duration(char * arg)
     {
    -	std::string package = "";
    -	std::string cmd = "BCHNS:";
    -	char buffer[64];
    +    std::string package = "";
    +    std::string cmd = "BCHNS:";
    +    char buffer[64];
     
    -	package.assign(cmd);
    +    package.assign(cmd);
     
    -	memset(buffer, 0, sizeof(buffer));
    -	snprintf(buffer, sizeof(buffer)-1, "%d", progdefaults.busyChannelSeconds);
    -	package.append(buffer);
    +    memset(buffer, 0, sizeof(buffer));
    +    snprintf(buffer, sizeof(buffer)-1, "%d", progdefaults.busyChannelSeconds);
    +    package.append(buffer);
     
    -	kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
    +    kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
     
     }
     
    @@ -1396,20 +1452,20 @@ static void reply_busy_channel_duration(char * arg)
      **********************************************************************************/
     static void reply_busy_state(char * arg)
     {
    -	std::string package = "";
    -	std::string cmd = "BUSY:";
    +    std::string package = "";
    +    std::string cmd = "BUSY:";
     
    -	package.assign(cmd);
    +    package.assign(cmd);
     
    -	if((trx_state == STATE_TX) || \
    -	   (kpsql_pl > kpsql_threshold) || \
    -	   (inhibit_tx_seconds)) {
    -		package.append("T");
    -	} else {
    -		package.append("F");
    -	}
    +    if((trx_state == STATE_TX) || \
    +       (kpsql_pl > kpsql_threshold) || \
    +       (inhibit_tx_seconds)) {
    +        package.append("T");
    +    } else {
    +        package.append("F");
    +    }
     
    -	kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
    +    kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
     }
     
     /**********************************************************************************
    @@ -1417,25 +1473,25 @@ static void reply_busy_state(char * arg)
      **********************************************************************************/
     static void set_kpsql_on_off(char * arg)
     {
    -	if(!arg)
    -		return;
    +    if(!arg)
    +        return;
     
    -	std::string strarg = "";
    +    std::string strarg = "";
     
    -	strarg.assign(arg);
    +    strarg.assign(arg);
     
    -	if(strarg.empty())
    -		return reply_kpsql_on_off(arg);
    +    if(strarg.empty())
    +        return reply_kpsql_on_off(arg);
     
    -	if(strarg.find("ON") != std::string::npos) {
    -		REQ(set_button, btnPSQL, 1);
    -		return;
    -	}
    +    if(strarg.find("ON") != std::string::npos) {
    +        REQ(set_button, btnPSQL, 1);
    +        return;
    +    }
     
    -	if(strarg.find("OFF") != std::string::npos) {
    -		REQ(set_button, btnPSQL, 0);
    -		return;
    -	}
    +    if(strarg.find("OFF") != std::string::npos) {
    +        REQ(set_button, btnPSQL, 0);
    +        return;
    +    }
     
     }
     
    @@ -1444,17 +1500,17 @@ static void set_kpsql_on_off(char * arg)
      **********************************************************************************/
     static void reply_kpsql_on_off(char * arg)
     {
    -	std::string package = "";
    -	std::string cmd = "KPSQL:";
    +    std::string package = "";
    +    std::string cmd = "KPSQL:";
     
    -	package.assign(cmd);
    +    package.assign(cmd);
     
    -	if(progStatus.pwrsqlonoff)
    -		package.append("ON");
    -	else
    -		package.append("OFF");
    +    if(progStatus.kpsql_enabled)
    +        package.append("ON");
    +    else
    +        package.append("OFF");
     
    -	kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
    +    kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
     }
     
     /**********************************************************************************
    @@ -1462,27 +1518,27 @@ static void reply_kpsql_on_off(char * arg)
      **********************************************************************************/
     static void reply_kpsql_pwr_level(char * arg)
     {
    -	std::string package = "";
    -	std::string cmd = "KPSQLP:";
    -	char buffer[64];
    -	float plevel = 0;
    -	float scale = 100.0 / ((float) HISTO_COUNT);
    +    std::string package = "";
    +    std::string cmd = "KPSQLP:";
    +    char buffer[64];
    +    float plevel = 0;
    +    float scale = 100.0 / ((float) HISTO_COUNT);
     
    -	package.assign(cmd);
    +    package.assign(cmd);
     
    -	if(kpsql_pl > (double) HISTO_COUNT) {
    -		plevel = HISTO_COUNT;
    -	} else {
    -		plevel = kpsql_pl;
    -	}
    +    if(kpsql_pl > (double) HISTO_COUNT) {
    +        plevel = HISTO_COUNT;
    +    } else {
    +        plevel = kpsql_pl;
    +    }
     
    -	plevel *= scale;
    +    plevel *= scale;
     
    -	memset(buffer, 0, sizeof(buffer));
    -	snprintf(buffer, sizeof(buffer)-1, "%u", (unsigned int) plevel);
    -	package.append(buffer);
    +    memset(buffer, 0, sizeof(buffer));
    +    snprintf(buffer, sizeof(buffer)-1, "%u", (unsigned int) plevel);
    +    package.append(buffer);
     
    -	kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
    +    kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
     }
     
     /**********************************************************************************
    @@ -1490,27 +1546,27 @@ static void reply_kpsql_pwr_level(char * arg)
      **********************************************************************************/
     static void set_kpsql_squelch_level(char * arg)
     {
    -	if(!arg)
    -		return;
    +    if(!arg)
    +        return;
     
    -	std::string strarg = "";
    +    std::string strarg = "";
     
    -	strarg.assign(arg);
    +    strarg.assign(arg);
     
    -	if(strarg.empty())
    -		return reply_kpsql_squelch_level(arg);
    +    if(strarg.empty())
    +        return reply_kpsql_squelch_level(arg);
     
    -	int value = 0;
    +    int value = 0;
     
    -	sscanf(strarg.c_str(), "%d", &value);
    +    sscanf(strarg.c_str(), "%d", &value);
     
    -	if(value < 1) value = 1;
    -	if(value > 100) value = 100;
    +    if(value < 1) value = 1;
    +    if(value > 100) value = 100;
     
    -	progStatus.sldrPwrSquelchValue = value;
    +    progStatus.sldrPwrSquelchValue = value;
     
    -	if(progStatus.pwrsqlonoff)
    -		REQ(set_slider2, sldrSquelch, value);
    +    if(progStatus.kpsql_enabled)
    +        REQ(set_slider2, sldrSquelch, value);
     
     }
     
    @@ -1519,17 +1575,17 @@ static void set_kpsql_squelch_level(char * arg)
      **********************************************************************************/
     static void reply_kpsql_squelch_level(char * arg)
     {
    -	std::string package = "";
    -	std::string cmd = "KPSQLS:";
    -	char buffer[64];
    +    std::string package = "";
    +    std::string cmd = "KPSQLS:";
    +    char buffer[64];
     
    -	package.assign(cmd);
    +    package.assign(cmd);
     
    -	memset(buffer, 0, sizeof(buffer));
    -	snprintf(buffer, sizeof(buffer)-1, "%u", (unsigned int) progStatus.sldrPwrSquelchValue);
    -	package.append(buffer);
    +    memset(buffer, 0, sizeof(buffer));
    +    snprintf(buffer, sizeof(buffer)-1, "%u", (unsigned int) progStatus.sldrPwrSquelchValue);
    +    package.append(buffer);
     
    -	kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
    +    kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
     }
     
     /**********************************************************************************
    @@ -1537,31 +1593,31 @@ static void reply_kpsql_squelch_level(char * arg)
      **********************************************************************************/
     static void set_kiss_raw_mode(char * arg)
     {
    -	if(!arg)
    -		return;
    +    if(!arg)
    +        return;
     
    -	std::string strarg = "";
    +    std::string strarg = "";
     
    -	strarg.assign(arg);
    +    strarg.assign(arg);
     
    -	if(strarg.empty())
    -		return reply_kiss_raw_mode(arg);
    +    if(strarg.empty())
    +        return reply_kiss_raw_mode(arg);
     
    -	// Longer compares first
    -	if(strarg.find("ONLY") != std::string::npos) {
    -		kiss_raw_enabled = KISS_RAW_ONLY;
    -		return;
    -	}
    +    // Longer compares first
    +    if(strarg.find("ONLY") != std::string::npos) {
    +        kiss_raw_enabled = KISS_RAW_ONLY;
    +        return;
    +    }
     
    -	if(strarg.find("ON") != std::string::npos) {
    -		kiss_raw_enabled = KISS_RAW_ON;
    -		return;
    -	}
    +    if(strarg.find("ON") != std::string::npos) {
    +        kiss_raw_enabled = KISS_RAW_ON;
    +        return;
    +    }
     
    -	if(strarg.find("OFF") != std::string::npos) {
    -		kiss_raw_enabled = KISS_RAW_DISABLED;
    -		return;
    -	}
    +    if(strarg.find("OFF") != std::string::npos) {
    +        kiss_raw_enabled = KISS_RAW_DISABLED;
    +        return;
    +    }
     
     }
     
    @@ -1570,29 +1626,29 @@ static void set_kiss_raw_mode(char * arg)
      **********************************************************************************/
     static void reply_kiss_raw_mode(char * arg)
     {
    -	std::string package = "";
    -	std::string cmd = "KISSRAW:";
    +    std::string package = "";
    +    std::string cmd = "KISSRAW:";
     
    -	package.assign(cmd);
    +    package.assign(cmd);
     
    -	switch(kiss_raw_enabled) {
    -		case KISS_RAW_ONLY:
    -			package.append("ONLY");
    -			break;
    +    switch(kiss_raw_enabled) {
    +        case KISS_RAW_ONLY:
    +            package.append("ONLY");
    +            break;
     
    -		case KISS_RAW_ON:
    -			package.append("ON");
    -			break;
    +        case KISS_RAW_ON:
    +            package.append("ON");
    +            break;
     
    -		case KISS_RAW_DISABLED:
    -			package.append("OFF");
    -			break;
    +        case KISS_RAW_DISABLED:
    +            package.append("OFF");
    +            break;
     
    -		default:
    -			return;
    -	}
    +        default:
    +            return;
    +    }
     
    -	kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
    +    kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
     }
     
     /**********************************************************************************
    @@ -1600,44 +1656,44 @@ static void reply_kiss_raw_mode(char * arg)
      **********************************************************************************/
     static void set_crc_mode(char * arg)
     {
    -	if(!arg)
    -		return;
    +    if(!arg)
    +        return;
     
    -	std::string strarg = "";
    +    std::string strarg = "";
     
    -	strarg.assign(arg);
    +    strarg.assign(arg);
     
    -	if(strarg.empty())
    -		return reply_crc_mode(arg);
    +    if(strarg.empty())
    +        return reply_crc_mode(arg);
     
    -	if(strarg.find("SMACK") != std::string::npos) {
    -		smack_crc_enabled = true;
    -		crc_mode = CRC16_CCITT;
    -		return;
    -	}
    +    if(strarg.find("SMACK") != std::string::npos) {
    +        smack_crc_enabled = true;
    +        crc_mode = CRC16_CCITT;
    +        return;
    +    }
     
    -	if(strarg.find("CCITT") != std::string::npos) {
    -		smack_crc_enabled = true;
    -		crc_mode = CRC16_CCITT;
    -		return;
    -	}
    +    if(strarg.find("CCITT") != std::string::npos) {
    +        smack_crc_enabled = true;
    +        crc_mode = CRC16_CCITT;
    +        return;
    +    }
     
    -	if(strarg.find("FCS") != std::string::npos) {
    -		smack_crc_enabled = true;
    -		crc_mode = CRC16_FCS;
    -		return;
    -	}
    +    if(strarg.find("FCS") != std::string::npos) {
    +        smack_crc_enabled = true;
    +        crc_mode = CRC16_FCS;
    +        return;
    +    }
     
    -	if(strarg.find("XOR") != std::string::npos) {
    -		smack_crc_enabled = true;
    -		crc_mode = CRC8_XOR;
    -		return;
    -	}
    +    if(strarg.find("XOR") != std::string::npos) {
    +        smack_crc_enabled = true;
    +        crc_mode = CRC8_XOR;
    +        return;
    +    }
     
    -	if(strarg.find("NONE") != std::string::npos) {
    -		smack_crc_enabled = false;
    -		return;
    -	}
    +    if(strarg.find("NONE") != std::string::npos) {
    +        smack_crc_enabled = false;
    +        return;
    +    }
     
     }
     
    @@ -1646,39 +1702,39 @@ static void set_crc_mode(char * arg)
      **********************************************************************************/
     static void reply_crc_mode(char *arg)
     {
    -	std::string package = "";
    -	std::string cmd = "KISSCRCM:";
    +    std::string package = "";
    +    std::string cmd = "KISSCRCM:";
     
    -	package.assign(cmd);
    +    package.assign(cmd);
     
    -	if(smack_crc_enabled)
    -		package.append("SMACK,");
    -	else
    -		package.append("NONE,");
    +    if(smack_crc_enabled)
    +        package.append("SMACK,");
    +    else
    +        package.append("NONE,");
     
    -	switch(crc_mode) {
    -		case CRC16_NONE:
    -			package.append("NONE");
    -			break;
    +    switch(crc_mode) {
    +        case CRC16_NONE:
    +            package.append("NONE");
    +            break;
     
    -		case CRC16_CCITT:
    -			package.append("CCITT");
    -			break;
    +        case CRC16_CCITT:
    +            package.append("CCITT");
    +            break;
     
    -		case CRC16_FCS:
    -			package.append("FCS");
    -			break;
    +        case CRC16_FCS:
    +            package.append("FCS");
    +            break;
     
    -		case CRC8_XOR:
    -			package.append("XOR");
    -			break;
    +        case CRC8_XOR:
    +            package.append("XOR");
    +            break;
     
    -		default:
    -			package.append("UNDEFINED");
    +        default:
    +            package.append("UNDEFINED");
     
    -	}
    +    }
     
    -	kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
    +    kiss_queue_frame(encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no), cmd);
     }
     
     /**********************************************************************************
    @@ -1686,70 +1742,94 @@ static void reply_crc_mode(char *arg)
      **********************************************************************************/
     bool bcast_rsid_kiss_frame(int new_wf_pos, int new_mode, int old_wf_pos, int old_mode, int notify)
     {
    -	guard_lock kiss_bc_frame_lock(&kiss_bc_frame_mutex);
    +    guard_lock kiss_bc_frame_lock(&kiss_bc_frame_mutex);
     
    -	static char buffer[256];
    -	char *notify_str = (char *) "";
    -	KISS_QUEUE_FRAME *frame = (KISS_QUEUE_FRAME *)0;
    -	std::string package = "";
    +    char buffer[256];
    +    char old_modem_name[64];
    +    char new_modem_name[64];
    +    char *notify_str = (char *) "";
    +    KISS_QUEUE_FRAME *frame = (KISS_QUEUE_FRAME *)0;
    +    std::string package = "";
     
    -	if(new_mode >= NUM_MODES || old_mode >= NUM_MODES)
    -		return false;
    +    if(new_mode >= NUM_MODES || old_mode >= NUM_MODES)
    +        return false;
     
    -	if(new_mode < 0 || old_mode < 0)
    -		return false;
    +    if(new_mode < 0 || old_mode < 0)
    +        return false;
     
    -	if(!(mode_info[new_mode].iface_io & KISS_IO))
    -		return false;
    +    if(!(mode_info[new_mode].iface_io & KISS_IO))
    +        return false;
     
    -	if(old_mode != new_mode || new_wf_pos != old_wf_pos) {
    -		reset_histogram();
    -	}
    +    if(old_mode != new_mode || new_wf_pos != old_wf_pos) {
    +        reset_histogram();
    +    }
     
    -	if(!kiss_bcast_rsid_reception) return true;
    +    if(!kiss_bcast_rsid_reception) return true;
     
    -	if(new_wf_pos == 0) {
    -		new_wf_pos = old_wf_pos;
    -		notify = RSID_KISS_USER;
    -	}
    +    if(new_wf_pos == 0) {
    +        new_wf_pos = old_wf_pos;
    +        notify = RSID_KISS_USER;
    +    }
     
    -	switch(notify) {
    -		case RSID_KISS_NOTIFY:
    -			notify_str = (char *) "NOTIFY";
    -			break;
    +    switch(notify) {
    +        case RSID_KISS_NOTIFY:
    +            notify_str = (char *) "NOTIFY";
    +            break;
     
    -		case RSID_KISS_ACTIVE:
    -			notify_str = (char *) "ACTIVE";
    -			break;
    +        case RSID_KISS_ACTIVE:
    +            notify_str = (char *) "ACTIVE";
    +            break;
     
    -		case RSID_KISS_USER:
    -			notify_str = (char *) "USER";
    -			break;
    +        case RSID_KISS_USER:
    +            notify_str = (char *) "USER";
    +            break;
     
    -		default:
    -			LOG_DEBUG("%s", "Unknown KISS frame RSID BC Source");
    -			return false;
    -	}
    +        default:
    +            LOG_DEBUG("%s", "Unknown KISS frame RSID BC Source");
    +            return false;
    +    }
     
    -	memset(buffer, 0, sizeof(buffer));
    -	snprintf(buffer, sizeof(buffer)-1, "RSIDN:%d,%s,%d,%s,%s", new_wf_pos, mode_info[new_mode].sname, \
    -			 old_wf_pos, mode_info[old_mode].sname, notify_str);
    +    // Send all modem names in capital letters
     
    -	package.assign(buffer);
    +    memset(old_modem_name, 0, sizeof(old_modem_name));
    +    strncpy(old_modem_name, mode_info[old_mode].sname, sizeof(old_modem_name) - 1);
     
    -	frame = encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no);
    +    for(size_t i = 0; i < sizeof(old_modem_name); i++) {
    +        if(old_modem_name[i])
    +            old_modem_name[i] = toupper(old_modem_name[i]);
    +        else
    +            break;
    +    }
     
    -	if(!frame) {
    -		LOG_DEBUG("%s", "Broadcast Hardware Frame Assembly Failure");
    -		return true;
    -	}
    +    memset(new_modem_name, 0, sizeof(new_modem_name));
    +    strncpy(new_modem_name, mode_info[new_mode].sname, sizeof(new_modem_name) - 1);
     
    -	kiss_bc_frame.append((const char *) frame->data, (size_t) frame->size);
    +    for(size_t i = 0; i < sizeof(new_modem_name); i++) {
    +        if(new_modem_name[i])
    +            new_modem_name[i] = toupper(new_modem_name[i]);
    +        else
    +            break;
    +    }
     
    -	if(frame->data)	delete [] frame->data;
    -	if(frame) delete frame;
    +    memset(buffer, 0, sizeof(buffer));
    +    snprintf(buffer, sizeof(buffer)-1, "RSIDN:%d,%s,%d,%s,%s", new_wf_pos, new_modem_name, \
    +             old_wf_pos, old_modem_name, notify_str);
     
    -	return true;
    +    package.assign(buffer);
    +
    +    frame = encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no);
    +
    +    if(!frame) {
    +        LOG_DEBUG("%s", "Broadcast Hardware Frame Assembly Failure");
    +        return true;
    +    }
    +
    +    kiss_bc_frame.append((const char *) frame->data, (size_t) frame->size);
    +
    +    if(frame->data)	delete [] frame->data;
    +    if(frame) delete frame;
    +
    +    return true;
     }
     
     /**********************************************************************************
    @@ -1757,40 +1837,40 @@ bool bcast_rsid_kiss_frame(int new_wf_pos, int new_mode, int old_wf_pos, int old
      **********************************************************************************/
     void bcast_trxs_kiss_frame(int state)
     {
    -	guard_lock kiss_bc_frame_lock(&kiss_bc_frame_mutex);
    +    guard_lock kiss_bc_frame_lock(&kiss_bc_frame_mutex);
     
    -	KISS_QUEUE_FRAME *frame = (KISS_QUEUE_FRAME *)0;
    -	std::string package;
    +    KISS_QUEUE_FRAME *frame = (KISS_QUEUE_FRAME *)0;
    +    std::string package;
     
    -	package.assign("TRXS:");
    +    package.assign("TRXS:");
     
    -	switch(state) {
    -		case STATE_RX:
    -			package.append("RX") ;
    -			break;
    +    switch(state) {
    +        case STATE_RX:
    +            package.append("RX") ;
    +            break;
     
    -		case STATE_TUNE:
    -		case STATE_TX:
    -			package.append("TX") ;
    -			break;
    +        case STATE_TUNE:
    +        case STATE_TX:
    +            package.append("TX") ;
    +            break;
     
    -		default:
    -			LOG_DEBUG("%s", "Unknown Transmit State");
    -			return;
    +        default:
    +            LOG_DEBUG("%s", "Unknown Transmit State");
    +            return;
     
    -	}
    +    }
     
    -	frame = encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no);
    +    frame = encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no);
     
    -	if(!frame) {
    -		LOG_DEBUG("%s", "Broadcast Hardware Frame Assembly Failure");
    -		return;
    -	}
    +    if(!frame) {
    +        LOG_DEBUG("%s", "Broadcast Hardware Frame Assembly Failure");
    +        return;
    +    }
     
    -	kiss_bc_frame.append((const char *) frame->data, (size_t) frame->size);
    +    kiss_bc_frame.append((const char *) frame->data, (size_t) frame->size);
     
    -	if(frame->data)	delete [] frame->data;
    -	if(frame) delete frame;
    +    if(frame->data)	delete [] frame->data;
    +    if(frame) delete frame;
     }
     
     /**********************************************************************************
    @@ -1798,26 +1878,26 @@ void bcast_trxs_kiss_frame(int state)
      **********************************************************************************/
     void bcast_tx_buffer_empty_kiss_frame(void)
     {
    -	if(!bcast_tx_buffer_empty_flag) return;
    +    if(!bcast_tx_buffer_empty_flag) return;
     
    -	guard_lock kiss_bc_frame_lock(&kiss_bc_frame_mutex);
    +    guard_lock kiss_bc_frame_lock(&kiss_bc_frame_mutex);
     
    -	KISS_QUEUE_FRAME *frame = (KISS_QUEUE_FRAME *)0;
    -	std::string package;
    +    KISS_QUEUE_FRAME *frame = (KISS_QUEUE_FRAME *)0;
    +    std::string package;
     
    -	package.assign("TXBE:");
    +    package.assign("TXBE:");
     
    -	frame = encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no);
    +    frame = encap_kiss_frame(package, KISS_HARDWARE, kiss_port_no);
     
    -	if(!frame) {
    -		LOG_DEBUG("%s", "Broadcast Hardware Frame Assembly Failure");
    -		return;
    -	}
    +    if(!frame) {
    +        LOG_DEBUG("%s", "Broadcast Hardware Frame Assembly Failure");
    +        return;
    +    }
     
    -	kiss_bc_frame.append((const char *) frame->data, (size_t) frame->size);
    +    kiss_bc_frame.append((const char *) frame->data, (size_t) frame->size);
     
    -	if(frame->data)	delete [] frame->data;
    -	if(frame) delete frame;
    +    if(frame->data)	delete [] frame->data;
    +    if(frame) delete frame;
     }
     
     /**********************************************************************************
    @@ -1825,35 +1905,35 @@ void bcast_tx_buffer_empty_kiss_frame(void)
      **********************************************************************************/
     static void exec_hardware_command(std::string cmd, std::string arg)
     {
    -	if(cmd.empty()) return;
    -	if(kiss_reset_flag) return;
    -	int pos = 0;
    -	int a = 0;
    -	int b = 0;
    -	int comp_size = 0;
    -	int index = 0;
    -	int count = sizeof(exec_match) / sizeof(EXEC_HARDWARE_CMD_MATCH);
    -	string cmp = "";
    +    if(cmd.empty()) return;
    +    if(kiss_reset_flag) return;
    +    int pos = 0;
    +    int a = 0;
    +    int b = 0;
    +    int comp_size = 0;
    +    int index = 0;
    +    int count = sizeof(exec_match) / sizeof(EXEC_HARDWARE_CMD_MATCH);
    +    string cmp = "";
     
    -	for(index = 0; index < count; index++) {
    -		if(exec_match[index].cmd == (char *)0) return;
    -		cmp.assign(exec_match[index].cmd);
    -		if((pos = cmp.find(cmd)) != (int)(string::npos)) {
    -			a = cmp.size();
    -			b = cmd.size();
    +    for(index = 0; index < count; index++) {
    +        if(exec_match[index].cmd == (char *)0) return;
    +        cmp.assign(exec_match[index].cmd);
    +        if((pos = cmp.find(cmd)) != (int)(string::npos)) {
    +            a = cmp.size();
    +            b = cmd.size();
     
    -			if(a > b)
    -				comp_size = a;
    -			else
    -				comp_size = b;
    +            if(a > b)
    +                comp_size = a;
    +            else
    +                comp_size = b;
     
    -			if(cmd.compare(pos, comp_size, cmp) == 0) {
    -				if(exec_match[index].cmd_func)
    -					(*exec_match[index].cmd_func)((char *) arg.c_str());
    -				return;
    -			}
    -		}
    -	}
    +            if(cmd.compare(pos, comp_size, cmp) == 0) {
    +                if(exec_match[index].cmd_func)
    +                    (*exec_match[index].cmd_func)((char *) arg.c_str());
    +                return;
    +            }
    +        }
    +    }
     }
     
     /**********************************************************************************
    @@ -1861,24 +1941,24 @@ static void exec_hardware_command(std::string cmd, std::string arg)
      **********************************************************************************/
     static bool kiss_queue_frame(KISS_QUEUE_FRAME * frame, std::string cmd)
     {
    -	if(!frame) {
    -		LOG_DEBUG("Null frame (%s)", cmd.c_str());
    -		return false;
    -	}
    +    if(!frame) {
    +        LOG_DEBUG("Null frame (%s)", cmd.c_str());
    +        return false;
    +    }
     
    -	if(frame->size == 0 || frame->data == (char *)0) {
    -		LOG_DEBUG("Frame null content (%s)", cmd.c_str());
    -		if(frame->data) delete[] frame->data;
    -		delete frame;
    -		return false;
    -	}
    +    if(frame->size == 0 || frame->data == (char *)0) {
    +        LOG_DEBUG("Frame null content (%s)", cmd.c_str());
    +        if(frame->data) delete[] frame->data;
    +        delete frame;
    +        return false;
    +    }
     
    -	WriteToHostBuffered((const char *) frame->data, (size_t) frame->size);
    +    WriteToHostBuffered((const char *) frame->data, (size_t) frame->size);
     
    -	delete[] frame->data;
    -	delete frame;
    +    delete[] frame->data;
    +    delete frame;
     
    -	return true;
    +    return true;
     }
     
     /**********************************************************************************
    @@ -1886,49 +1966,49 @@ static bool kiss_queue_frame(KISS_QUEUE_FRAME * frame, std::string cmd)
      **********************************************************************************/
     size_t kiss_encode(char *src, size_t src_size, char **dst)
     {
    -	if(!src || !dst || src_size < 1) return 0;
    +    if(!src || !dst || src_size < 1) return 0;
     
    -	size_t index = 0;
    -	int count = 0;
    -	int buffer_size = 0;
    -	int byte = 0;
    -	char *buffer = (char *)0;
    +    size_t index = 0;
    +    int count = 0;
    +    int buffer_size = 0;
    +    int byte = 0;
    +    char *buffer = (char *)0;
     
    -	buffer_size = (src_size * KISS_BUFFER_FACTOR) + BUFFER_PADDING;
    -	buffer = new char[buffer_size];
    +    buffer_size = (src_size * KISS_BUFFER_FACTOR) + BUFFER_PADDING;
    +    buffer = new char[buffer_size];
     
    -	if(!buffer) {
    -		LOG_DEBUG("Memory allocation error near line %d", __LINE__);
    -		*dst = (char *)0;
    -		return 0;
    -	}
    +    if(!buffer) {
    +        LOG_DEBUG("Memory allocation error near line %d", __LINE__);
    +        *dst = (char *)0;
    +        return 0;
    +    }
     
    -	memset(buffer, 0, buffer_size);
    -	count = 0;
    -	buffer[count++] = KISS_FEND;
    +    memset(buffer, 0, buffer_size);
    +    count = 0;
    +    buffer[count++] = KISS_FEND;
     
    -	for(index = 0; index < src_size; index++) {
    -		byte = (int) src[index] & 0xFF;
    -		switch(byte) {
    -			case KISS_FESC:
    -				buffer[count++] = KISS_FESC;
    -				buffer[count++] = KISS_TFESC;
    -				break;
    +    for(index = 0; index < src_size; index++) {
    +        byte = (int) src[index] & 0xFF;
    +        switch(byte) {
    +            case KISS_FESC:
    +                buffer[count++] = KISS_FESC;
    +                buffer[count++] = KISS_TFESC;
    +                break;
     
    -			case KISS_FEND:
    -				buffer[count++] = KISS_FESC;
    -				buffer[count++] = KISS_TFEND;
    -				break;
    +            case KISS_FEND:
    +                buffer[count++] = KISS_FESC;
    +                buffer[count++] = KISS_TFEND;
    +                break;
     
    -			default:
    -				buffer[count++] = byte;
    -		}
    -	}
    +            default:
    +                buffer[count++] = byte;
    +        }
    +    }
     
    -	buffer[count++] = KISS_FEND;
    -	*dst = (char *) buffer;
    +    buffer[count++] = KISS_FEND;
    +    *dst = (char *) buffer;
     
    -	return count;
    +    return count;
     }
     
     /**********************************************************************************
    @@ -1936,62 +2016,62 @@ size_t kiss_encode(char *src, size_t src_size, char **dst)
      **********************************************************************************/
     size_t kiss_decode(char *src, size_t src_size, char **dst)
     {
    -	if(!src || !dst || src_size < 1) return 0;
    +    if(!src || !dst || src_size < 1) return 0;
     
    -	size_t index = 0;
    -	int count = 0;
    -	int buffer_size = 0;
    -	int byte = 0;
    -	int last_byte = 0;
    -	char *buffer = (char *)0;
    +    size_t index = 0;
    +    int count = 0;
    +    int buffer_size = 0;
    +    int byte = 0;
    +    int last_byte = 0;
    +    char *buffer = (char *)0;
     
    -	buffer_size = src_size + BUFFER_PADDING;
    -	buffer = new char[buffer_size];
    +    buffer_size = src_size + BUFFER_PADDING;
    +    buffer = new char[buffer_size];
     
    -	if(!buffer) {
    -		LOG_DEBUG("Memory allocation error near line %d", __LINE__);
    -		*dst = (char *)0;
    -		return 0;
    -	}
    +    if(!buffer) {
    +        LOG_DEBUG("Memory allocation error near line %d", __LINE__);
    +        *dst = (char *)0;
    +        return 0;
    +    }
     
    -	memset(buffer, 0, buffer_size);
    -	count = 0;
    -	last_byte = KISS_INVALID;
    +    memset(buffer, 0, buffer_size);
    +    count = 0;
    +    last_byte = KISS_INVALID;
     
    -	for(index = 0; index < src_size; index++) {
    +    for(index = 0; index < src_size; index++) {
     
    -		byte = src[index] & 0xFF;
    +        byte = src[index] & 0xFF;
     
    -		switch(byte) {
    -			case KISS_FEND:
    -				continue;
    +        switch(byte) {
    +            case KISS_FEND:
    +                continue;
     
    -			case KISS_FESC:
    -				break;
    +            case KISS_FESC:
    +                break;
     
    -			case KISS_TFEND:
    -				if(last_byte == KISS_FESC)
    -					buffer[count++] = KISS_FEND;
    -				else
    -					buffer[count++] = byte;
    -				break;
    +            case KISS_TFEND:
    +                if(last_byte == KISS_FESC)
    +                    buffer[count++] = KISS_FEND;
    +                else
    +                    buffer[count++] = byte;
    +                break;
     
    -			case KISS_TFESC:
    -				if(last_byte == KISS_FESC)
    -					buffer[count++] = KISS_FESC;
    -				else
    -					buffer[count++] = byte;
    -				break;
    +            case KISS_TFESC:
    +                if(last_byte == KISS_FESC)
    +                    buffer[count++] = KISS_FESC;
    +                else
    +                    buffer[count++] = byte;
    +                break;
     
    -			default:
    -				buffer[count++] = byte;
    -		}
    +            default:
    +                buffer[count++] = byte;
    +        }
     
    -		last_byte = byte;
    -	}
    +        last_byte = byte;
    +    }
     
    -	*dst = (char *) buffer;
    -	return count;
    +    *dst = (char *) buffer;
    +    return count;
     }
     
     #if 0
    @@ -2000,28 +2080,28 @@ size_t kiss_decode(char *src, size_t src_size, char **dst)
      **********************************************************************************/
     std::string kiss_decode(std::string frame)
     {
    -	int count = 0;
    -	int frame_size = 0;
    -	char *dst = (char *)0;
    +    int count = 0;
    +    int frame_size = 0;
    +    char *dst = (char *)0;
     
    -	static std::string ret_str = "";
    +    static std::string ret_str = "";
     
    -	if(frame.empty()) return frame;
    +    if(frame.empty()) return frame;
     
    -	frame_size = frame.size();
    +    frame_size = frame.size();
     
    -	ret_str.clear();
    -	ret_str.reserve(frame_size + BUFFER_PADDING);
    +    ret_str.clear();
    +    ret_str.reserve(frame_size + BUFFER_PADDING);
     
    -	count = kiss_decode((char *) frame.c_str(), frame.size(), &dst);
    +    count = kiss_decode((char *) frame.c_str(), frame.size(), &dst);
     
    -	if(count && dst) {
    -		ret_str.assign(dst, count);
    -		dst[0] = 0;
    -		delete [] dst;
    -	}
    +    if(count && dst) {
    +        ret_str.assign(dst, count);
    +        dst[0] = 0;
    +        delete [] dst;
    +    }
     
    -	return ret_str;
    +    return ret_str;
     }
     #endif // 0
     
    @@ -2030,28 +2110,28 @@ std::string kiss_decode(std::string frame)
      **********************************************************************************/
     std::string kiss_encode(std::string frame)
     {
    -	int count = 0;
    -	int frame_size = 0;
    -	char *dst = (char *)0;
    +    int count = 0;
    +    int frame_size = 0;
    +    char *dst = (char *)0;
     
    -	static std::string ret_str = "";
    +    static std::string ret_str = "";
     
    -	if(frame.empty()) return frame;
    +    if(frame.empty()) return frame;
     
    -	frame_size = frame.size();
    +    frame_size = frame.size();
     
    -	ret_str.clear();
    -	ret_str.reserve((frame_size * 2) + BUFFER_PADDING);
    +    ret_str.clear();
    +    ret_str.reserve((frame_size * 2) + BUFFER_PADDING);
     
    -	count = kiss_encode((char *) frame.c_str(), frame.size(), &dst);
    +    count = kiss_encode((char *) frame.c_str(), frame.size(), &dst);
     
    -	if(count && dst) {
    -		ret_str.assign(dst, count);
    -		dst[0] = 0;
    -		delete [] dst;
    -	}
    +    if(count && dst) {
    +        ret_str.assign(dst, count);
    +        dst[0] = 0;
    +        delete [] dst;
    +    }
     
    -	return ret_str;
    +    return ret_str;
     }
     
     
    @@ -2060,67 +2140,67 @@ std::string kiss_encode(std::string frame)
      **********************************************************************************/
     size_t hdlc_encode(char *src, size_t src_size, char **dst)
     {
    -	if(!src || !dst || src_size < 1) return 0;
    +    if(!src || !dst || src_size < 1) return 0;
     
    -	size_t index = 0;
    -	int count = 0;
    -	int buffer_size = 0;
    -	int byte = 0;
    -	char *buffer = (char *)0;
    +    size_t index = 0;
    +    int count = 0;
    +    int buffer_size = 0;
    +    int byte = 0;
    +    char *buffer = (char *)0;
     
    -	buffer_size = (src_size * HDLC_BUFFER_FACTOR) + BUFFER_PADDING;
    -	buffer = new char[buffer_size];
    +    buffer_size = (src_size * HDLC_BUFFER_FACTOR) + BUFFER_PADDING;
    +    buffer = new char[buffer_size];
     
    -	if(!buffer) {
    -		LOG_DEBUG("Memory allocation error near line %d", __LINE__);
    -		*dst = (char *)0;
    -		return 0;
    -	}
    +    if(!buffer) {
    +        LOG_DEBUG("Memory allocation error near line %d", __LINE__);
    +        *dst = (char *)0;
    +        return 0;
    +    }
     
    -	memset(buffer, 0, buffer_size);
    -	count = 0;
    -	buffer[count++] = ' ';
    -	buffer[count++] = KISS_FEND;
    +    memset(buffer, 0, buffer_size);
    +    count = 0;
    +    buffer[count++] = ' ';
    +    buffer[count++] = KISS_FEND;
     
    -	for(index = 0; index < src_size; index++) {
    -		byte = (int) src[index] & 0xFF;
    +    for(index = 0; index < src_size; index++) {
    +        byte = (int) src[index] & 0xFF;
     
    -		if(not_allowed[byte]) {
    -			buffer[count++] = HDLC_CNT;
    -			if((byte + HDLC_CNT_OFFSET) > 255)
    -				buffer[count++] = ((byte - HDLC_CNT_OFFSET) & 0xFF);
    -			else
    -				buffer[count++] = ((byte + HDLC_CNT_OFFSET) & 0xFF);
    -			continue;
    -		}
    +        if(not_allowed[byte]) {
    +            buffer[count++] = HDLC_CNT;
    +            if((byte + HDLC_CNT_OFFSET) > 255)
    +                buffer[count++] = ((byte - HDLC_CNT_OFFSET) & 0xFF);
    +            else
    +                buffer[count++] = ((byte + HDLC_CNT_OFFSET) & 0xFF);
    +            continue;
    +        }
     
    -		switch(byte) {
    -			case KISS_FESC:
    -				buffer[count++] = KISS_FESC;
    -				buffer[count++] = KISS_TFESC;
    -				break;
    +        switch(byte) {
    +            case KISS_FESC:
    +                buffer[count++] = KISS_FESC;
    +                buffer[count++] = KISS_TFESC;
    +                break;
     
    -			case KISS_FEND:
    -				buffer[count++] = KISS_FESC;
    -				buffer[count++] = KISS_TFEND;
    -				break;
    +            case KISS_FEND:
    +                buffer[count++] = KISS_FESC;
    +                buffer[count++] = KISS_TFEND;
    +                break;
     
    -			case HDLC_CNT:
    -				buffer[count++] = KISS_FESC;
    -				buffer[count++] = HDLC_TCNT;
    -				break;
    +            case HDLC_CNT:
    +                buffer[count++] = KISS_FESC;
    +                buffer[count++] = HDLC_TCNT;
    +                break;
     
    -			default:
    -				buffer[count++] = byte;
    -		}
    -	}
    +            default:
    +                buffer[count++] = byte;
    +        }
    +    }
     
    -	buffer[count++] = KISS_FEND;
    -	buffer[count++] = ' ';
    +    buffer[count++] = KISS_FEND;
    +    buffer[count++] = ' ';
     
    -	*dst = (char *) buffer;
    +    *dst = (char *) buffer;
     
    -	return count;
    +    return count;
     }
     
     /**********************************************************************************
    @@ -2128,80 +2208,80 @@ size_t hdlc_encode(char *src, size_t src_size, char **dst)
      **********************************************************************************/
     size_t hdlc_decode(char *src, size_t src_size, char **dst)
     {
    -	if(!src || !dst || src_size < 1) return 0;
    +    if(!src || !dst || src_size < 1) return 0;
     
    -	size_t index = 0;
    -	int count = 0;
    -	int buffer_size = 0;
    -	int byte = 0;
    -	int last_byte = 0;
    -	int check_byte = 0;
    -	char *buffer = (char *)0;
    +    size_t index = 0;
    +    int count = 0;
    +    int buffer_size = 0;
    +    int byte = 0;
    +    int last_byte = 0;
    +    int check_byte = 0;
    +    char *buffer = (char *)0;
     
    -	buffer_size = src_size + BUFFER_PADDING;
    -	buffer = new char[buffer_size];
    +    buffer_size = src_size + BUFFER_PADDING;
    +    buffer = new char[buffer_size];
     
    -	if(!buffer) {
    -		LOG_DEBUG("Memory allocation error near line %d", __LINE__);
    -		*dst = (char *)0;
    -		return 0;
    -	}
    +    if(!buffer) {
    +        LOG_DEBUG("Memory allocation error near line %d", __LINE__);
    +        *dst = (char *)0;
    +        return 0;
    +    }
     
    -	memset(buffer, 0, buffer_size);
    -	count = 0;
    -	last_byte = KISS_INVALID;
    +    memset(buffer, 0, buffer_size);
    +    count = 0;
    +    last_byte = KISS_INVALID;
     
    -	for(index = 0; index < src_size; index++) {
    +    for(index = 0; index < src_size; index++) {
     
    -		byte = src[index] & 0xFF;
    +        byte = src[index] & 0xFF;
     
    -		if(last_byte == HDLC_CNT) {
    -			check_byte = byte - HDLC_CNT_OFFSET;
    -			if((check_byte > -1) && (check_byte < 256) && not_allowed[check_byte]) {
    -				buffer[count++] = check_byte;
    -				last_byte = byte;
    -				continue;
    -			}
    +        if(last_byte == HDLC_CNT) {
    +            check_byte = byte - HDLC_CNT_OFFSET;
    +            if((check_byte > -1) && (check_byte < 256) && not_allowed[check_byte]) {
    +                buffer[count++] = check_byte;
    +                last_byte = byte;
    +                continue;
    +            }
     
    -			check_byte = byte + HDLC_CNT_OFFSET;
    -			if((check_byte > -1) && (check_byte < 256) && not_allowed[check_byte]) {
    -				buffer[count++] = check_byte;
    -			}
    +            check_byte = byte + HDLC_CNT_OFFSET;
    +            if((check_byte > -1) && (check_byte < 256) && not_allowed[check_byte]) {
    +                buffer[count++] = check_byte;
    +            }
     
    -			last_byte = byte;
    -			continue;
    -		}
    +            last_byte = byte;
    +            continue;
    +        }
     
    -		switch(byte) {
    -			case KISS_FEND:
    -				continue;
    +        switch(byte) {
    +            case KISS_FEND:
    +                continue;
     
    -			case KISS_FESC:
    -			case HDLC_CNT:
    -				last_byte = byte;
    -				continue;
    +            case KISS_FESC:
    +            case HDLC_CNT:
    +                last_byte = byte;
    +                continue;
     
    -			case KISS_TFEND:
    -				if(last_byte == KISS_FESC)
    -					byte = KISS_FEND;
    -				break;
    +            case KISS_TFEND:
    +                if(last_byte == KISS_FESC)
    +                    byte = KISS_FEND;
    +                break;
     
    -			case KISS_TFESC:
    -				if(last_byte == KISS_FESC)
    -					byte = KISS_FESC;
    -				break;
    +            case KISS_TFESC:
    +                if(last_byte == KISS_FESC)
    +                    byte = KISS_FESC;
    +                break;
     
    -			case HDLC_TCNT:
    -				if(last_byte == KISS_FESC)
    -					byte = HDLC_CNT;
    -				break;
    -		}
    +            case HDLC_TCNT:
    +                if(last_byte == KISS_FESC)
    +                    byte = HDLC_CNT;
    +                break;
    +        }
     
    -		last_byte = buffer[count++] = byte;
    -	}
    +        last_byte = buffer[count++] = byte;
    +    }
     
    -	*dst = (char *) buffer;
    -	return count;
    +    *dst = (char *) buffer;
    +    return count;
     
     }
     
    @@ -2212,38 +2292,38 @@ size_t hdlc_decode(char *src, size_t src_size, char **dst)
      **********************************************************************************/
     static size_t encap_hdlc_frame(char *buffer, size_t data_count)
     {
    -	if(!buffer || !data_count) {
    -		LOG_DEBUG("%s", "Parameter Data Error [NULL]");
    -		return false;
    -	}
    +    if(!buffer || !data_count) {
    +        LOG_DEBUG("%s", "Parameter Data Error [NULL]");
    +        return false;
    +    }
     
    -	size_t count = 0;
    -	unsigned int crc_value = 0;
    -	char *kiss_encap = (char *)0;
    +    size_t count = 0;
    +    unsigned int crc_value = 0;
    +    char *kiss_encap = (char *)0;
     
    -	if(progdefaults.ax25_decode_enabled) {
    -		ax25_decode((unsigned char *) buffer, data_count, true, true);
    -	}
    +    if(progdefaults.ax25_decode_enabled) {
    +        ax25_decode((unsigned char *) buffer, data_count, true, true);
    +    }
     
    -	crc_value = calc_fcs_crc(buffer, (int) data_count);
    +    crc_value = calc_fcs_crc(buffer, (int) data_count);
     
    -	buffer[data_count++] = CRC_LOW(crc_value);
    -	buffer[data_count++] = CRC_HIGH(crc_value);
    +    buffer[data_count++] = CRC_LOW(crc_value);
    +    buffer[data_count++] = CRC_HIGH(crc_value);
     
    -	count = hdlc_encode(buffer, data_count, &kiss_encap);
    +    count = hdlc_encode(buffer, data_count, &kiss_encap);
     
    -	if(kiss_encap && count) {
    -		memcpy(buffer, kiss_encap, count);
    +    if(kiss_encap && count) {
    +        memcpy(buffer, kiss_encap, count);
     #ifdef EXTENED_DEBUG_INFO
    -		LOG_HEX(buffer, count);
    +        LOG_HEX(buffer, count);
     #endif
    -		delete [] kiss_encap;
    -	} else {
    -		LOG_DEBUG("%s", "Kiss Encode Memory Allocation Error");
    -		return 0;
    -	}
    +        delete [] kiss_encap;
    +    } else {
    +        LOG_DEBUG("%s", "Kiss Encode Memory Allocation Error");
    +        return 0;
    +    }
     
    -	return count;
    +    return count;
     }
     
     /*********************************************************************************
    @@ -2253,72 +2333,72 @@ static size_t encap_hdlc_frame(char *buffer, size_t data_count)
      *********************************************************************************/
     static size_t decap_hdlc_frame(char *buffer, size_t data_count)
     {
    -	if(!buffer || !data_count) {
    -		LOG_DEBUG("%s", "Parameter Data Error/NULL");
    -		return false;
    -	}
    +    if(!buffer || !data_count) {
    +        LOG_DEBUG("%s", "Parameter Data Error/NULL");
    +        return false;
    +    }
     
    -	size_t count = 0;
    -	//	size_t index = 0;
    -	unsigned int crc_value = 0;
    -	unsigned int calc_crc_value = 0;
    -	char *kiss_decap = (char *)0;
    +    size_t count = 0;
    +    //	size_t index = 0;
    +    unsigned int crc_value = 0;
    +    unsigned int calc_crc_value = 0;
    +    char *kiss_decap = (char *)0;
     
    -	count = hdlc_decode(buffer, data_count, &kiss_decap);
    +    count = hdlc_decode(buffer, data_count, &kiss_decap);
     
     #ifdef EXTENED_DEBUG_INFO
    -	if(data_count && buffer)
    -		LOG_HEX(buffer, data_count);
    +    if(data_count && buffer)
    +        LOG_HEX(buffer, data_count);
     
    -	if(count && kiss_decap)
    -		LOG_HEX(kiss_decap, count);
    +    if(count && kiss_decap)
    +        LOG_HEX(kiss_decap, count);
     #endif
     
    -	do  {
    +    do  {
     
    -		if(count > data_count || !kiss_decap) {
    -			LOG_DEBUG("%s", "Kiss decode error");
    -			count = 0;
    -			break;
    -		}
    +        if(count > data_count || !kiss_decap) {
    +            LOG_DEBUG("%s", "Kiss decode error");
    +            count = 0;
    +            break;
    +        }
     
    -		if(count > 2)
    -			count -= 2;
    +        if(count > 2)
    +            count -= 2;
     
    -		if(count) {
    -			calc_crc_value = calc_fcs_crc(kiss_decap, (int) count);
    -		}
    -		else {
    -			LOG_DEBUG("%s", "Kiss decode error");
    -			count = 0;
    -			break;
    -		}
    +        if(count) {
    +            calc_crc_value = calc_fcs_crc(kiss_decap, (int) count);
    +        }
    +        else {
    +            LOG_DEBUG("%s", "Kiss decode error");
    +            count = 0;
    +            break;
    +        }
     
    -		crc_value = CRC_LOW_HIGH(kiss_decap[count], kiss_decap[count + 1]);
    +        crc_value = CRC_LOW_HIGH(kiss_decap[count], kiss_decap[count + 1]);
     
    -		if(crc_value != calc_crc_value) {
    -			count = 0;
    -			break;
    -		}
    +        if(crc_value != calc_crc_value) {
    +            count = 0;
    +            break;
    +        }
     
    -		temp_disable_tx_inhibit = time(0) + DISABLE_TX_INHIBIT_DURATION; // valid packet, disable busy channel inhitbit for x duration.
    +        temp_disable_tx_inhibit = time(0) + DISABLE_TX_INHIBIT_DURATION; // valid packet, disable busy channel inhitbit for x duration.
     
    -		kiss_decap[count] = kiss_decap[count + 1] = 0;
    -		memcpy(buffer, kiss_decap, count);
    +        kiss_decap[count] = kiss_decap[count + 1] = 0;
    +        memcpy(buffer, kiss_decap, count);
     
    -		if(progdefaults.ax25_decode_enabled) {
    -			ax25_decode((unsigned char *) buffer, count, true, false);
    -		}
    +        if(progdefaults.ax25_decode_enabled) {
    +            ax25_decode((unsigned char *) buffer, count, true, false);
    +        }
     
    -		break;
    -	} while(1);
    +        break;
    +    } while(1);
     
    -	if(kiss_decap) {
    -		kiss_decap[0] = 0;
    -		delete [] kiss_decap;
    -	}
    +    if(kiss_decap) {
    +        kiss_decap[0] = 0;
    +        delete [] kiss_decap;
    +    }
     
    -	return count;
    +    return count;
     }
     
     
    @@ -2327,113 +2407,113 @@ static size_t decap_hdlc_frame(char *buffer, size_t data_count)
      **********************************************************************************/
     static KISS_QUEUE_FRAME *encap_kiss_frame(char *buffer, size_t buffer_size, int frame_type, int port)
     {
    -	if(!buffer || buffer_size < 1) {
    -		LOG_DEBUG("%s", "KISS encap argument 'data' contains no data");
    -		return (KISS_QUEUE_FRAME *)0;
    -	}
    +    if(!buffer || buffer_size < 1) {
    +        LOG_DEBUG("%s", "KISS encap argument 'data' contains no data");
    +        return (KISS_QUEUE_FRAME *)0;
    +    }
     
    -	if(port > 0xF || port < 0) {
    -		LOG_DEBUG("Invalid KISS port number (%d)", port);
    -		return (KISS_QUEUE_FRAME *)0;
    -	}
    +    if(port > 0xF || port < 0) {
    +        LOG_DEBUG("Invalid KISS port number (%d)", port);
    +        return (KISS_QUEUE_FRAME *)0;
    +    }
     
    -	switch(frame_type) {
    -		case KISS_DATA:
    -		case KISS_RAW:
    -		case KISS_TXDELAY:
    -		case KISS_PERSIST:
    -		case KISS_SLOTTIME:
    -		case KISS_TXTAIL:
    -		case KISS_DUPLEX:
    -		case KISS_HARDWARE:
    -			break;
    +    switch(frame_type) {
    +        case KISS_DATA:
    +        case KISS_RAW:
    +        case KISS_TXDELAY:
    +        case KISS_PERSIST:
    +        case KISS_SLOTTIME:
    +        case KISS_TXTAIL:
    +        case KISS_DUPLEX:
    +        case KISS_HARDWARE:
    +            break;
     
    -		default:
    -			LOG_DEBUG("Invalid KISS frame type (%d)", frame_type);
    -			return (KISS_QUEUE_FRAME *)0;
    -	}
    +        default:
    +            LOG_DEBUG("Invalid KISS frame type (%d)", frame_type);
    +            return (KISS_QUEUE_FRAME *)0;
    +    }
     
    -	int size = 0;
    -	int index = 0;
    -	unsigned int crc_value = 0;
    -	KISS_QUEUE_FRAME *frame = (KISS_QUEUE_FRAME *)0;
    +    int size = 0;
    +    int index = 0;
    +    unsigned int crc_value = 0;
    +    KISS_QUEUE_FRAME *frame = (KISS_QUEUE_FRAME *)0;
     
    -	frame = new KISS_QUEUE_FRAME;
    +    frame = new KISS_QUEUE_FRAME;
     
    -	if(!frame) {
    -		LOG_DEBUG("%s", "KISS struct frame memory allocation error");
    -		return (KISS_QUEUE_FRAME *)0;
    -	}
    +    if(!frame) {
    +        LOG_DEBUG("%s", "KISS struct frame memory allocation error");
    +        return (KISS_QUEUE_FRAME *)0;
    +    }
     
    -	size = (buffer_size * KISS_BUFFER_FACTOR) + BUFFER_PADDING; // Resulting data space could be 2 fold higher.
    -	frame->data = (char *) new char[size];
    +    size = (buffer_size * KISS_BUFFER_FACTOR) + BUFFER_PADDING; // Resulting data space could be 2 fold higher.
    +    frame->data = (char *) new char[size];
     
    -	if(!frame->data) {
    -		delete frame;
    -		LOG_DEBUG("%s", "KISS buffer frame memory allocation error");
    -		return (KISS_QUEUE_FRAME *)0;
    -	}
    +    if(!frame->data) {
    +        delete frame;
    +        LOG_DEBUG("%s", "KISS buffer frame memory allocation error");
    +        return (KISS_QUEUE_FRAME *)0;
    +    }
     
    -	memset(frame->data, 0, size);
    -	size = buffer_size;
    +    memset(frame->data, 0, size);
    +    size = buffer_size;
     
    -	frame->data[0] = SET_KISS_TYPE_PORT(frame_type, port);
    -	memcpy(&frame->data[1], buffer, size);
    +    frame->data[0] = SET_KISS_TYPE_PORT(frame_type, port);
    +    memcpy(&frame->data[1], buffer, size);
     
    -	size++;
    +    size++;
     
    -	if((frame_type == KISS_DATA) || (frame_type == KISS_RAW)) {
    +    if((frame_type == KISS_DATA) || (frame_type == KISS_RAW)) {
     
    -		if(smack_crc_enabled) {
    +        if(smack_crc_enabled) {
     
    -			frame->data[0] = SMACK_CRC_ASSIGN(frame->data[0]);
    +            frame->data[0] = SMACK_CRC_ASSIGN(frame->data[0]);
     
    -			switch(crc_mode) {
    -				case CRC16_CCITT:
    -					crc_value = calc_ccitt_crc((char *) frame->data, size);
    -					frame->data[size++] = CRC_LOW(crc_value);
    -					frame->data[size++] = CRC_HIGH(crc_value);
    -					break;
    +            switch(crc_mode) {
    +                case CRC16_CCITT:
    +                    crc_value = calc_ccitt_crc((char *) frame->data, size);
    +                    frame->data[size++] = CRC_LOW(crc_value);
    +                    frame->data[size++] = CRC_HIGH(crc_value);
    +                    break;
     
    -				case CRC16_FCS:
    -					crc_value = calc_fcs_crc((char *) frame->data, size);
    -					frame->data[size++] = CRC_LOW(crc_value);
    -					frame->data[size++] = CRC_HIGH(crc_value);
    -					break;
    +                case CRC16_FCS:
    +                    crc_value = calc_fcs_crc((char *) frame->data, size);
    +                    frame->data[size++] = CRC_LOW(crc_value);
    +                    frame->data[size++] = CRC_HIGH(crc_value);
    +                    break;
     
    -				case CRC8_XOR:
    -					crc_value = calc_xor_crc((char *) frame->data, size);
    -					frame->data[size++] = CRC_LOW(crc_value);
    -					break;
    +                case CRC8_XOR:
    +                    crc_value = calc_xor_crc((char *) frame->data, size);
    +                    frame->data[size++] = CRC_LOW(crc_value);
    +                    break;
     
    -				default:
    -					break;
    -			}
    -		}
    -	}
    +                default:
    +                    break;
    +            }
    +        }
    +    }
     
    -	char *tmp = (char *)0;
    +    char *tmp = (char *)0;
     
    -	index = kiss_encode((char *) frame->data, size, &tmp);
    +    index = kiss_encode((char *) frame->data, size, &tmp);
     
    -	if(tmp) {
    +    if(tmp) {
     
     #ifdef EXTENED_DEBUG_INFO
    -		LOG_HEX(tmp, index);
    +        LOG_HEX(tmp, index);
     #endif
     
    -		frame->data[0] = 0;
    -		delete [] frame->data;
    -		frame->data = (char *) tmp;
    -		frame->size = index;
    -	} else {
    -		LOG_DEBUG("KISS encode allocation error near line %d", __LINE__);
    -		delete [] frame->data;
    -		delete frame;
    -		frame = (KISS_QUEUE_FRAME *)0;
    -	}
    +        frame->data[0] = 0;
    +        delete [] frame->data;
    +        frame->data = (char *) tmp;
    +        frame->size = index;
    +    } else {
    +        LOG_DEBUG("KISS encode allocation error near line %d", __LINE__);
    +        delete [] frame->data;
    +        delete frame;
    +        frame = (KISS_QUEUE_FRAME *)0;
    +    }
     
    -	return frame;
    +    return frame;
     }
     
     /**********************************************************************************
    @@ -2441,8 +2521,8 @@ static KISS_QUEUE_FRAME *encap_kiss_frame(char *buffer, size_t buffer_size, int
      **********************************************************************************/
     static KISS_QUEUE_FRAME * encap_kiss_frame(std::string data, int frame_type, int port)
     {
    -	if(data.empty()) return (KISS_QUEUE_FRAME *)0;
    -	return encap_kiss_frame((char *) data.c_str(), (size_t) data.size(), frame_type, port);
    +    if(data.empty()) return (KISS_QUEUE_FRAME *)0;
    +    return encap_kiss_frame((char *) data.c_str(), (size_t) data.size(), frame_type, port);
     }
     
     /**********************************************************************************
    @@ -2450,100 +2530,100 @@ static KISS_QUEUE_FRAME * encap_kiss_frame(std::string data, int frame_type, int
      **********************************************************************************/
     std::string unencap_kiss_frame(char *buffer, size_t buffer_size, int *frame_type, int *kiss_port_no)
     {
    -	if(!buffer || buffer_size < 1 || !frame_type || !kiss_port_no)
    -		return std::string("");
    +    if(!buffer || buffer_size < 1 || !frame_type || !kiss_port_no)
    +        return std::string("");
     
    -	char *decoded_buffer = (char *)0;
    -	size_t count = 0;
    -	unsigned int crc_extracted = 0;
    -	unsigned int crc_calc = 0;
    -	unsigned int port = 0;
    -	unsigned int ftype = 0;
    +    char *decoded_buffer = (char *)0;
    +    size_t count = 0;
    +    unsigned int crc_extracted = 0;
    +    unsigned int crc_calc = 0;
    +    unsigned int port = 0;
    +    unsigned int ftype = 0;
     
    -	static std::string ret_str = "";
    +    static std::string ret_str = "";
     
    -	ret_str.clear();
    +    ret_str.clear();
     
     #ifdef EXTENED_DEBUG_INFO
    -	LOG_HEX(buffer, buffer_size);
    +    LOG_HEX(buffer, buffer_size);
     #endif
     
    -	count = kiss_decode(buffer, buffer_size, &decoded_buffer);
    +    count = kiss_decode(buffer, buffer_size, &decoded_buffer);
     
    -	if(!count || !decoded_buffer) {
    -		LOG_DEBUG("Kiss decoder memory allocation error near line %d", __LINE__);
    -		return ret_str;
    -	}
    +    if(!count || !decoded_buffer) {
    +        LOG_DEBUG("Kiss decoder memory allocation error near line %d", __LINE__);
    +        return ret_str;
    +    }
     
    -	ftype = KISS_CMD(decoded_buffer[0]);
    -	port = KISS_PORT(decoded_buffer[0]);
    +    ftype = KISS_CMD(decoded_buffer[0]);
    +    port = KISS_PORT(decoded_buffer[0]);
     
    -	if((ftype == KISS_DATA) || (ftype == KISS_RAW)) {
    -		smack_crc_enabled = SMACK_CRC(port);
    -		port = SMACK_CRC_MASK(port);
    +    if((ftype == KISS_DATA) || (ftype == KISS_RAW)) {
    +        smack_crc_enabled = SMACK_CRC(port);
    +        port = SMACK_CRC_MASK(port);
     
    -		if(smack_crc_enabled) {
    -			switch(crc_mode) {
    -				case CRC16_CCITT:
    -					count -= 2;
    -					if(count > 2) {
    -						crc_calc = calc_ccitt_crc(decoded_buffer, count);
    -						crc_extracted = CRC_LOW_HIGH(decoded_buffer[count], decoded_buffer[count + 1]);
    -					} else {
    -						crc_calc = crc_extracted + 1; // Force a fail
    -					}
    -					break;
    +        if(smack_crc_enabled) {
    +            switch(crc_mode) {
    +                case CRC16_CCITT:
    +                    count -= 2;
    +                    if(count > 2) {
    +                        crc_calc = calc_ccitt_crc(decoded_buffer, count);
    +                        crc_extracted = CRC_LOW_HIGH(decoded_buffer[count], decoded_buffer[count + 1]);
    +                    } else {
    +                        crc_calc = crc_extracted + 1; // Force a fail
    +                    }
    +                    break;
     
    -				case CRC16_FCS:
    -					count -= 2;
    -					if(count > 2) {
    -						crc_calc = calc_fcs_crc(decoded_buffer, count);
    -						crc_extracted = CRC_LOW_HIGH(decoded_buffer[count], decoded_buffer[count + 1]);
    -					} else {
    -						crc_calc = crc_extracted + 1;
    -					}
    -					break;
    +                case CRC16_FCS:
    +                    count -= 2;
    +                    if(count > 2) {
    +                        crc_calc = calc_fcs_crc(decoded_buffer, count);
    +                        crc_extracted = CRC_LOW_HIGH(decoded_buffer[count], decoded_buffer[count + 1]);
    +                    } else {
    +                        crc_calc = crc_extracted + 1;
    +                    }
    +                    break;
     
    -				case CRC8_XOR:
    -					count -= 1;
    -					if(count > 1) {
    -						crc_calc = CRC_LOW(calc_fcs_crc(decoded_buffer, count));
    -						crc_extracted = CRC_LOW(decoded_buffer[count]);
    -					} else {
    -						crc_calc = crc_extracted + 1;
    -					}
    -					break;
    +                case CRC8_XOR:
    +                    count -= 1;
    +                    if(count > 1) {
    +                        crc_calc = CRC_LOW(calc_fcs_crc(decoded_buffer, count));
    +                        crc_extracted = CRC_LOW(decoded_buffer[count]);
    +                    } else {
    +                        crc_calc = crc_extracted + 1;
    +                    }
    +                    break;
     
    -				default:
    -					LOG_DEBUG("CRC type not found %d", crc_mode);
    -			}
    +                default:
    +                    LOG_DEBUG("CRC type not found %d", crc_mode);
    +            }
     
    -			if(crc_calc != crc_extracted) {
    +            if(crc_calc != crc_extracted) {
     
    -				if(frame_type) *frame_type = ftype;
    -				if(kiss_port_no) *kiss_port_no = port;
    -				if(decoded_buffer) delete [] decoded_buffer;
    +                if(frame_type) *frame_type = ftype;
    +                if(kiss_port_no) *kiss_port_no = port;
    +                if(decoded_buffer) delete [] decoded_buffer;
     
    -				ret_str.clear();
    -				return ret_str;
    -			}
    -		}
    -	}
    +                ret_str.clear();
    +                return ret_str;
    +            }
    +        }
    +    }
     
    -	if(count > 0)
    -		count--;
    +    if(count > 0)
    +        count--;
     
     #ifdef EXTENED_DEBUG_INFO
    -	LOG_HEX(&decoded_buffer[1], count);
    +    LOG_HEX(&decoded_buffer[1], count);
     #endif
     
    -	ret_str.assign(&decoded_buffer[1], count);
    +    ret_str.assign(&decoded_buffer[1], count);
     
    -	if(frame_type) *frame_type = ftype;
    -	if(kiss_port_no) *kiss_port_no = port;
    -	if(decoded_buffer) delete [] decoded_buffer;
    +    if(frame_type) *frame_type = ftype;
    +    if(kiss_port_no) *kiss_port_no = port;
    +    if(decoded_buffer) delete [] decoded_buffer;
     
    -	return ret_str;
    +    return ret_str;
     }
     
     /**********************************************************************************
    @@ -2551,10 +2631,10 @@ std::string unencap_kiss_frame(char *buffer, size_t buffer_size, int *frame_type
      **********************************************************************************/
     std::string unencap_kiss_frame(std::string package, int *frame_type, int *kiss_port_no)
     {
    -	if(package.empty() || !frame_type || !kiss_port_no)
    -		return std::string("");
    +    if(package.empty() || !frame_type || !kiss_port_no)
    +        return std::string("");
     
    -	return unencap_kiss_frame((char *) package.c_str(), (size_t) package.size(), frame_type, kiss_port_no);
    +    return unencap_kiss_frame((char *) package.c_str(), (size_t) package.size(), frame_type, kiss_port_no);
     }
     
     /**********************************************************************************
    @@ -2562,66 +2642,66 @@ std::string unencap_kiss_frame(std::string package, int *frame_type, int *kiss_p
      **********************************************************************************/
     static void parse_hardware_frame(std::string frame)
     {
    -	if(frame.empty()) return;
    +    if(frame.empty()) return;
     
    -	string cmd = "";
    -	string arg = "";
    -	static char buffer[512];
    -	string parse_frame = "";
    -	char bofmsg[] = "Temp Buffer overflow";
    -	size_t count = frame.size();
    -	size_t index = 0;
    -	size_t pos = 0;
    -	size_t j = 0;
    +    string cmd = "";
    +    string arg = "";
    +    static char buffer[512];
    +    string parse_frame = "";
    +    char bofmsg[] = "Temp Buffer overflow";
    +    size_t count = frame.size();
    +    size_t index = 0;
    +    size_t pos = 0;
    +    size_t j = 0;
     
    -	parse_frame.assign(frame);
    +    parse_frame.assign(frame);
     
     #ifdef EXTENED_DEBUG_INFO
    -	LOG_HEX(frame.c_str(), frame.size());
    +    LOG_HEX(frame.c_str(), frame.size());
     #endif
     
    -	do {
    -		if(kiss_reset_flag) return;
    +    do {
    +        if(kiss_reset_flag) return;
     
    -		pos = parse_frame.find(":");
    +        pos = parse_frame.find(":");
     
    -		if(pos == string::npos) return;
    +        if(pos == string::npos) return;
     
    -		j = 0;
    -		memset(buffer, 0, sizeof(buffer));
    -		for(index = 0; index < pos; index++) {
    -			if(parse_frame[index] <= ' ') continue;
    -			buffer[j++] = toupper(parse_frame[index]);
    -			if(j >= sizeof(buffer)) {
    -				LOG_DEBUG("%s", bofmsg);
    -				return;
    -			}
    -		}
    -		cmd.assign(buffer);
    +        j = 0;
    +        memset(buffer, 0, sizeof(buffer));
    +        for(index = 0; index < pos; index++) {
    +            if(parse_frame[index] <= ' ') continue;
    +            buffer[j++] = toupper(parse_frame[index]);
    +            if(j >= sizeof(buffer)) {
    +                LOG_DEBUG("%s", bofmsg);
    +                return;
    +            }
    +        }
    +        cmd.assign(buffer);
     
    -		j = 0;
    -		memset(buffer, 0, sizeof(buffer));
    -		for(index = pos + 1; index < count; index++) {
    -			if(parse_frame[index] <= ' ') break;
    -			buffer[j++] = parse_frame[index];
    -			if(j >= sizeof(buffer)) {
    -				LOG_DEBUG("%s", bofmsg);
    -				return;
    -			}
    -		}
    -		arg.assign(buffer);
    +        j = 0;
    +        memset(buffer, 0, sizeof(buffer));
    +        for(index = pos + 1; index < count; index++) {
    +            if(parse_frame[index] <= ' ') break;
    +            buffer[j++] = parse_frame[index];
    +            if(j >= sizeof(buffer)) {
    +                LOG_DEBUG("%s", bofmsg);
    +                return;
    +            }
    +        }
    +        arg.assign(buffer);
     
    -		if(cmd.empty()) return;
    +        if(cmd.empty()) return;
     
    -		exec_hardware_command(cmd, arg);
    +        exec_hardware_command(cmd, arg);
     
    -		if(index > count)
    -			index = count;
    +        if(index > count)
    +            index = count;
     
    -		parse_frame.erase(0, index);
    -		count = parse_frame.size();
    +        parse_frame.erase(0, index);
    +        count = parse_frame.size();
     
    -	} while(count > 0);
    +    } while(count > 0);
     
     }
     
    @@ -2630,150 +2710,150 @@ static void parse_hardware_frame(std::string frame)
      **********************************************************************************/
     static void parse_kiss_frame(std::string frame_segment)
     {
    -	guard_lock kiss_rx_lock(&kiss_frame_mutex);
    +    guard_lock kiss_rx_lock(&kiss_frame_mutex);
     
    -	unsigned int cur_byte    = KISS_INVALID;
    -	unsigned int frame_size  = 0;
    -	unsigned int index       = 0;
    -	unsigned int fend_count  = 0;
    -	unsigned int cmsa_data   = 0;
    -	int buffer_size = 0;
    -	int port_no     = KISS_INVALID;
    -	int frame_type  = KISS_INVALID;
    -	int data_count = 0;
    +    unsigned int cur_byte    = KISS_INVALID;
    +    unsigned int frame_size  = 0;
    +    unsigned int index       = 0;
    +    unsigned int fend_count  = 0;
    +    unsigned int cmsa_data   = 0;
    +    int buffer_size = 0;
    +    int port_no     = KISS_INVALID;
    +    int frame_type  = KISS_INVALID;
    +    int data_count = 0;
     
    -	bool process_one_frame = false;
    -	char *buffer = (char *)0;
    +    bool process_one_frame = false;
    +    char *buffer = (char *)0;
     
    -	kiss_frame.append(frame_segment);
    +    kiss_frame.append(frame_segment);
     
    -	while(1) {
    +    while(1) {
     
    -		if(kiss_frame.empty()) return;
    +        if(kiss_frame.empty()) return;
     
    -		frame_size = kiss_frame.size();
    -		process_one_frame = false;
    -		fend_count = 0;
    -		kiss_one_frame.clear();
    +        frame_size = kiss_frame.size();
    +        process_one_frame = false;
    +        fend_count = 0;
    +        kiss_one_frame.clear();
     
    -		for(index = 0; index < frame_size; index++) {
    -			cur_byte = kiss_frame[index] & 0xFF;
    +        for(index = 0; index < frame_size; index++) {
    +            cur_byte = kiss_frame[index] & 0xFF;
     
    -			if(cur_byte == KISS_FEND) {
    -				fend_count++;
    -			}
    +            if(cur_byte == KISS_FEND) {
    +                fend_count++;
    +            }
     
    -			if(fend_count) {
    -				kiss_one_frame += cur_byte;
    -			}
    +            if(fend_count) {
    +                kiss_one_frame += cur_byte;
    +            }
     
    -			if(fend_count == 2) {
    -				kiss_frame.erase(0, index);
    -				process_one_frame = true;
    -				break;
    -			}
    -		}
    +            if(fend_count == 2) {
    +                kiss_frame.erase(0, index);
    +                process_one_frame = true;
    +                break;
    +            }
    +        }
     
    -		if(!process_one_frame)
    -			return;
    +        if(!process_one_frame)
    +            return;
     
    -		frame_size = kiss_one_frame.size();
    +        frame_size = kiss_one_frame.size();
     
    -		if(frame_size < 3) {
    -			continue; // Invalid Frame size
    -		}
    +        if(frame_size < 3) {
    +            continue; // Invalid Frame size
    +        }
     
    -		kiss_one_frame = unencap_kiss_frame(kiss_one_frame, &frame_type, &port_no);
    +        kiss_one_frame = unencap_kiss_frame(kiss_one_frame, &frame_type, &port_no);
     
    -		if(kiss_one_frame.empty())
    -			continue;
    +        if(kiss_one_frame.empty())
    +            continue;
     
    -		if(port_no != (int)kiss_port_no) {
    -			continue;
    -		}
    +        if(port_no != (int)kiss_port_no) {
    +            continue;
    +        }
     
    -		switch(frame_type) {
    -			case KISS_TXDELAY:
    -			case KISS_PERSIST:
    -			case KISS_SLOTTIME:
    -			case KISS_TXTAIL:
    -			case KISS_DUPLEX:
    -				cmsa_data = kiss_one_frame[0] & 0xFF;
    -				break;
    +        switch(frame_type) {
    +            case KISS_TXDELAY:
    +            case KISS_PERSIST:
    +            case KISS_SLOTTIME:
    +            case KISS_TXTAIL:
    +            case KISS_DUPLEX:
    +                cmsa_data = kiss_one_frame[0] & 0xFF;
    +                break;
     
    -			case KISS_DATA:
    -				if(kiss_raw_enabled == KISS_RAW_ONLY)
    -					continue;
    -				break;
    +            case KISS_DATA:
    +                if(kiss_raw_enabled == KISS_RAW_ONLY)
    +                    continue;
    +                break;
     
    -			case KISS_RAW:
    -				if(kiss_raw_enabled == KISS_RAW_DISABLED)
    -					continue;
    -				break;
    +            case KISS_RAW:
    +                if(kiss_raw_enabled == KISS_RAW_DISABLED)
    +                    continue;
    +                break;
     
    -			case KISS_HARDWARE:
    -				break;
    +            case KISS_HARDWARE:
    +                break;
     
    -			default:
    -				continue; // Unreconized frame_type.
    +            default:
    +                continue; // Unreconized frame_type.
     
    -		}
    -		//		int c = 0;
    +        }
    +        //		int c = 0;
     
    -		switch(frame_type) {
    -			case KISS_DATA:
    -				buffer_size = (frame_size * HDLC_BUFFER_FACTOR) + BUFFER_PADDING;
    -				buffer = new char[buffer_size];
    +        switch(frame_type) {
    +            case KISS_DATA:
    +                buffer_size = (frame_size * HDLC_BUFFER_FACTOR) + BUFFER_PADDING;
    +                buffer = new char[buffer_size];
     
    -				if(!buffer) {
    -					LOG_DEBUG("%s", "Buffer Allocation Error");
    -					return;
    -				}
    -				data_count = kiss_one_frame.size();
    -				memset(buffer, 0, buffer_size);
    -				memcpy(buffer, kiss_one_frame.c_str(), data_count);
    +                if(!buffer) {
    +                    LOG_DEBUG("%s", "Buffer Allocation Error");
    +                    return;
    +                }
    +                data_count = kiss_one_frame.size();
    +                memset(buffer, 0, buffer_size);
    +                memcpy(buffer, kiss_one_frame.c_str(), data_count);
     
    -				data_count = encap_hdlc_frame(buffer, data_count);
    +                data_count = encap_hdlc_frame(buffer, data_count);
     
    -				WriteToRadioBuffered((const char *) buffer, (size_t) data_count);
    +                WriteToRadioBuffered((const char *) buffer, (size_t) data_count);
     
    -				buffer[0] = 0;
    -				delete [] buffer;
    -				buffer = 0;
    +                buffer[0] = 0;
    +                delete [] buffer;
    +                buffer = 0;
     
    -				break;
    +                break;
     
    -			case KISS_RAW:
    -				WriteToRadioBuffered((const char *) kiss_one_frame.c_str(), (size_t) kiss_one_frame.size());
    -				break;
    +            case KISS_RAW:
    +                WriteToRadioBuffered((const char *) kiss_one_frame.c_str(), (size_t) kiss_one_frame.size());
    +                break;
     
    -			case KISS_TXDELAY:
    -				tx_delay = cmsa_data;
    -				break;
    +            case KISS_TXDELAY:
    +                tx_delay = cmsa_data;
    +                break;
     
    -			case KISS_PERSIST:
    -				persistance = cmsa_data;
    -				break;
    +            case KISS_PERSIST:
    +                persistance = cmsa_data;
    +                break;
     
    -			case KISS_SLOTTIME:
    -				slot_time = cmsa_data;
    -				break;
    +            case KISS_SLOTTIME:
    +                slot_time = cmsa_data;
    +                break;
     
    -			case KISS_TXTAIL:
    -				break;
    +            case KISS_TXTAIL:
    +                break;
     
    -			case KISS_DUPLEX:
    -				if(cmsa_data)
    -					duplex = KISS_FULL_DUPLEX;
    -				else
    -					duplex = KISS_HALF_DUPLEX;
    -				break;
    +            case KISS_DUPLEX:
    +                if(cmsa_data)
    +                    duplex = KISS_FULL_DUPLEX;
    +                else
    +                    duplex = KISS_HALF_DUPLEX;
    +                break;
     
    -			case KISS_HARDWARE:
    -				parse_hardware_frame(kiss_one_frame);
    -				break;
    -		}
    -	} // while(1)
    +            case KISS_HARDWARE:
    +                parse_hardware_frame(kiss_one_frame);
    +                break;
    +        }
    +    } // while(1)
     }
     
     #if 0
    @@ -2782,8 +2862,8 @@ static void parse_kiss_frame(std::string frame_segment)
      **********************************************************************************/
     static void WriteToHostBuffered(const char data)
     {
    -	guard_lock to_host_lock(&to_host_mutex);
    -	to_host += data;
    +    guard_lock to_host_lock(&to_host_mutex);
    +    to_host += data;
     }
     
     /**********************************************************************************
    @@ -2791,8 +2871,8 @@ static void WriteToHostBuffered(const char data)
      **********************************************************************************/
     static void WriteToHostBuffered(const char *data)
     {
    -	guard_lock to_host_lock(&to_host_mutex);
    -	to_host.append(data);
    +    guard_lock to_host_lock(&to_host_mutex);
    +    to_host.append(data);
     }
     #endif // #if 0
     
    @@ -2801,8 +2881,8 @@ static void WriteToHostBuffered(const char *data)
      **********************************************************************************/
     static void WriteToHostBuffered(const char *data, size_t size)
     {
    -	guard_lock to_host_lock(&to_host_mutex);
    -	to_host.append(data, size);
    +    guard_lock to_host_lock(&to_host_mutex);
    +    to_host.append(data, size);
     }
     
     #if 0
    @@ -2811,9 +2891,9 @@ static void WriteToHostBuffered(const char *data, size_t size)
      **********************************************************************************/
     static void WriteToRadioBuffered(unsigned char data)
     {
    -	guard_lock to_radio_lock(&to_radio_mutex);
    -	set_tx_timeout();
    -	to_radio += data;
    +    guard_lock to_radio_lock(&to_radio_mutex);
    +    set_tx_timeout();
    +    to_radio += data;
     }
     
     /**********************************************************************************
    @@ -2821,10 +2901,10 @@ static void WriteToRadioBuffered(unsigned char data)
      **********************************************************************************/
     static void WriteToRadioBuffered(const char *data)
     {
    -	guard_lock to_radio_lock(&to_radio_mutex);
    -	if(!data) return;
    -	set_tx_timeout();
    -	to_radio.append(data);
    +    guard_lock to_radio_lock(&to_radio_mutex);
    +    if(!data) return;
    +    set_tx_timeout();
    +    to_radio.append(data);
     }
     #endif // #if 0
     
    @@ -2833,10 +2913,10 @@ static void WriteToRadioBuffered(const char *data)
      **********************************************************************************/
     static void WriteToRadioBuffered(const char *data, size_t size)
     {
    -	guard_lock to_radio_lock(&to_radio_mutex);
    -	if(!data || size < 1) return;
    -	set_tx_timeout();
    -	to_radio.append(data, size);
    +    guard_lock to_radio_lock(&to_radio_mutex);
    +    if(!data || size < 1) return;
    +    set_tx_timeout();
    +    to_radio.append(data, size);
     }
     
     /**********************************************************************************
    @@ -2844,9 +2924,9 @@ static void WriteToRadioBuffered(const char *data, size_t size)
      **********************************************************************************/
     inline void set_tx_timeout(void)
     {
    -	if(to_radio.empty()) {
    -		transmit_buffer_flush_timeout = time(0) + TX_BUFFER_TIMEOUT;
    -	}
    +    if(to_radio.empty()) {
    +        transmit_buffer_flush_timeout = time(0) + TX_BUFFER_TIMEOUT;
    +    }
     }
     
     /**********************************************************************************
    @@ -2856,46 +2936,46 @@ inline void set_tx_timeout(void)
     #if 0
     static double detect_bandpass_signal(void)
     {
    -	int freq = 0;
    -	int bw = 500;
    -	int freq_step = 64;
    -	int freq_pos = 0;
    -	int start_freq = freq - (bw >> 1);
    -	int end_freq = freq + (bw >> 1);
    -	int freq_half_step = freq_step >> 1;
    -	double low_value = FLT_MAX;
    -	double high_value = FLT_MIN;
    -	double ratio = 0;
    -	double high_ratio = FLT_MIN;
    -	double low_ratio = FLT_MAX;
    -	double pd = 0;
    +    int freq = 0;
    +    int bw = 500;
    +    int freq_step = 64;
    +    int freq_pos = 0;
    +    int start_freq = freq - (bw >> 1);
    +    int end_freq = freq + (bw >> 1);
    +    int freq_half_step = freq_step >> 1;
    +    double low_value = FLT_MAX;
    +    double high_value = FLT_MIN;
    +    double ratio = 0;
    +    double high_ratio = FLT_MIN;
    +    double low_ratio = FLT_MAX;
    +    double pd = 0;
     
    -	for(freq = 500; freq < 3000; freq += 500) {
    +    for(freq = 500; freq < 3000; freq += 500) {
     
    -		start_freq = freq - (bw >> 1);
    -		end_freq = freq + (bw >> 1);
    -		freq_half_step = freq_step >> 1;
    -		low_value = FLT_MAX;
    -		high_value = FLT_MIN;
    -		ratio = 0;
    -		pd = 0;
    +        start_freq = freq - (bw >> 1);
    +        end_freq = freq + (bw >> 1);
    +        freq_half_step = freq_step >> 1;
    +        low_value = FLT_MAX;
    +        high_value = FLT_MIN;
    +        ratio = 0;
    +        pd = 0;
     
    -		for(; start_freq <= end_freq; start_freq += freq_step) {
    -			freq_pos = start_freq + freq_half_step;
    -			pd = wf->powerDensity((double) freq_pos, (double) freq_step);
    -			if(pd < low_value) low_value = pd;
    -			if(pd > high_value) high_value = pd;
    -		}
    +        for(; start_freq <= end_freq; start_freq += freq_step) {
    +            freq_pos = start_freq + freq_half_step;
    +            pd = wf->powerDensity((double) freq_pos, (double) freq_step);
    +            if(pd < low_value) low_value = pd;
    +            if(pd > high_value) high_value = pd;
    +        }
     
    -		ratio = (ratio + (high_value/low_value)) * 0.5;
    -		//ratio = high_value/low_value;
    +        ratio = (ratio + (high_value/low_value)) * 0.5;
    +        //ratio = high_value/low_value;
     
    -		if(high_ratio < ratio) high_ratio = ratio;
    -		if(low_ratio > ratio) low_ratio = ratio;
    +        if(high_ratio < ratio) high_ratio = ratio;
    +        if(low_ratio > ratio) low_ratio = ratio;
     
    -	}
    +    }
     
    -	return high_ratio;
    +    return high_ratio;
     }
     
     #endif // #if 0
    @@ -2907,11 +2987,11 @@ static double detect_bandpass_signal(void)
     #define IGNORE_PL_PERIOD 300
     
     typedef struct {
    -	time_t first_detected_time;
    -	int pl_index;
    -	int data_count;
    -	double pl_indexed[PL_AVG_COUNT];
    -	double pl_avg;
    +    time_t first_detected_time;
    +    int pl_index;
    +    int data_count;
    +    double pl_indexed[PL_AVG_COUNT];
    +    double pl_avg;
     } POWER_MASK;
     
     POWER_MASK power_mask[4000];
    @@ -2922,99 +3002,99 @@ POWER_MASK power_mask[4000];
      **********************************************************************************/
     static double detect_signal(int freq, int bw, double *low, double *high, double threshold)
     {
    -	int freq_step = 15;
    -	int freq_pos = 0;
    -	int start_freq = freq - (bw >> 1);
    -	int end_freq = freq + (bw >> 1);
    -	int freq_half_step = freq_step >> 1;
    -	int i = 0;
    -	double low_value = FLT_MAX;
    -	double high_value = FLT_MIN;
    -	double ratio = 0.0;
    -	double pd = 0;
    -	double ratio_avg = 0.0;
    -	static double pratio0 = 0.0;
    -	static double pratio1 = 0.0;
    -	static double pratio2 = 0.0;
    -	static old_low = 20;
    +    int freq_step = 15;
    +    int freq_pos = 0;
    +    int start_freq = freq - (bw >> 1);
    +    int end_freq = freq + (bw >> 1);
    +    int freq_half_step = freq_step >> 1;
    +    int i = 0;
    +    double low_value = FLT_MAX;
    +    double high_value = FLT_MIN;
    +    double ratio = 0.0;
    +    double pd = 0;
    +    double ratio_avg = 0.0;
    +    static double pratio0 = 0.0;
    +    static double pratio1 = 0.0;
    +    static double pratio2 = 0.0;
    +    static old_low = 20;
     
    -	time_t current_time = time(0);
    +    time_t current_time = time(0);
     
    -	if(trx_state != STATE_RX) return ratio_avg;
    +    if(trx_state != STATE_RX) return ratio_avg;
     
    -	for(i = 0; start_freq <= end_freq; start_freq += freq_step, i++) {
    -		freq_pos = start_freq + freq_half_step;
    -		pd = wf->powerDensity((double) freq_pos, (double) freq_step);
    +    for(i = 0; start_freq <= end_freq; start_freq += freq_step, i++) {
    +        freq_pos = start_freq + freq_half_step;
    +        pd = wf->powerDensity((double) freq_pos, (double) freq_step);
     
    -		if(pd > threshold) {
    -			if(!power_mask[i].first_detected_time)
    -				power_mask[i].first_detected_time = current_time;
    +        if(pd > threshold) {
    +            if(!power_mask[i].first_detected_time)
    +                power_mask[i].first_detected_time = current_time;
     
    -			if(power_mask[i].data_count < PL_INDEX_COUNT)
    -				power_mask[i].data_count++;
    +            if(power_mask[i].data_count < PL_INDEX_COUNT)
    +                power_mask[i].data_count++;
     
    -			power_mask[i].pl_index = power_mask[i].pl_index & PL_INDEX_COUNT_MASK;
    -			power_mask[i].pl_indexed[power_mask[i].pl_index] = pd;
    -			power_mask[i].pl_index++;
    +            power_mask[i].pl_index = power_mask[i].pl_index & PL_INDEX_COUNT_MASK;
    +            power_mask[i].pl_indexed[power_mask[i].pl_index] = pd;
    +            power_mask[i].pl_index++;
     
    -			if(((power_mask[i].first_detected_time + IGNORE_PL_PERIOD) < current_time) && power_mask[i].pl_avg >= threshold)
    -				pd = old_low;
    -		}
    +            if(((power_mask[i].first_detected_time + IGNORE_PL_PERIOD) < current_time) && power_mask[i].pl_avg >= threshold)
    +                pd = old_low;
    +        }
     
    -		if(pd < low_value)  old_low = low_value = pd;
    -		if(pd > high_value) high_value = pd;
    -	}
    +        if(pd < low_value)  old_low = low_value = pd;
    +        if(pd > high_value) high_value = pd;
    +    }
     
    -	if(low)  *low = low_value;
    -	if(high) *high = high_value;
    +    if(low)  *low = low_value;
    +    if(high) *high = high_value;
     
    -	old_low = low_value;
    +    old_low = low_value;
     
    -	ratio = high_value/low_value;
    -	ratio *= fractional_gain;
    -	kpsql_pl = ratio_avg = (ratio + pratio0 + pratio1 + pratio2) * 0.25;
    +    ratio = high_value/low_value;
    +    ratio *= fractional_gain;
    +    kpsql_pl = ratio_avg = (ratio + pratio0 + pratio1 + pratio2) * 0.25;
     
    -	int j = 0;
    -	int k = 0;
    -	int count = 0;
    -	doube temp_avg = 0.0;
    -	for(j = 0; j < i; j++) {
    -		count = power_mask[j].data_count;
    +    int j = 0;
    +    int k = 0;
    +    int count = 0;
    +    doube temp_avg = 0.0;
    +    for(j = 0; j < i; j++) {
    +        count = power_mask[j].data_count;
     
    -		if(count < PL_INDEX_COUNT) continue;
    +        if(count < PL_INDEX_COUNT) continue;
     
    -		for(k = 0; i < count; k++) {
    -			temp_avg += power_mask[j].pl_indexed[k];
    -		}
    +        for(k = 0; i < count; k++) {
    +            temp_avg += power_mask[j].pl_indexed[k];
    +        }
     
    -		temp_avg /= (1.0 * count);
    +        temp_avg /= (1.0 * count);
     
    -		if(temp_avg < threshold) {
    -			memset(&power_mask[j], 0, sizeof(POWER_MASK));
    -			continue;
    -		}
    +        if(temp_avg < threshold) {
    +            memset(&power_mask[j], 0, sizeof(POWER_MASK));
    +            continue;
    +        }
     
    -		power_mask[j].pl_avg = temp_avg;
    -	}
    +        power_mask[j].pl_avg = temp_avg;
    +    }
     
    -	if(ratio_avg > 0.0 && ratio_avg <= (double) HISTO_COUNT) {
    -		i = (int) ratio_avg;
    -		i &= 0xFF;
    -		histogram[i]++;
    +    if(ratio_avg > 0.0 && ratio_avg <= (double) HISTO_COUNT) {
    +        i = (int) ratio_avg;
    +        i &= 0xFF;
    +        histogram[i]++;
     
    -		if(histogram[i] > HISTO_THRESH_HOLD) {
    -			for(i = 0; i < HISTO_COUNT; i++) {
    -				histogram[i] >>= 1;
    -			}
    -			return 0.0;
    -		}
    -	}
    +        if(histogram[i] > HISTO_THRESH_HOLD) {
    +            for(i = 0; i < HISTO_COUNT; i++) {
    +                histogram[i] >>= 1;
    +            }
    +            return 0.0;
    +        }
    +    }
     
    -	pratio2 = pratio1;
    -	pratio1 = pratio0;
    -	pratio0 = ratio;
    +    pratio2 = pratio1;
    +    pratio1 = pratio0;
    +    pratio0 = ratio;
     
    -	return ratio;
    +    return ratio;
     }
     #else
     /**********************************************************************************
    @@ -3023,67 +3103,67 @@ static double detect_signal(int freq, int bw, double *low, double *high, double
      **********************************************************************************/
     static double detect_signal(int freq, int bw, double *low, double *high)
     {
    -	int freq_step = 10;
    -	int freq_pos = 0;
    -	int start_freq = freq - (bw >> 1);
    -	int end_freq = freq + (bw >> 1);
    -	int freq_half_step = freq_step >> 1;
    -	int i = 0;
    -	double low_value = FLT_MAX;
    -	double high_value = FLT_MIN;
    -	double ratio = 0.0;
    -	double pd = 0;
    -	double ratio_avg = 0.0;
    -	static double pratio0 = 0.0;
    -	static double pratio1 = 0.0;
    -	static double pratio2 = 0.0;
    -	static double pratio3 = 0.0;
    +    int freq_step = 10;
    +    int freq_pos = 0;
    +    int start_freq = freq - (bw >> 1);
    +    int end_freq = freq + (bw >> 1);
    +    int freq_half_step = freq_step >> 1;
    +    int i = 0;
    +    double low_value = FLT_MAX;
    +    double high_value = FLT_MIN;
    +    double ratio = 0.0;
    +    double pd = 0;
    +    double ratio_avg = 0.0;
    +    static double pratio0 = 0.0;
    +    static double pratio1 = 0.0;
    +    static double pratio2 = 0.0;
    +    static double pratio3 = 0.0;
     
    -	if(trx_state != STATE_RX) return ratio_avg;
    +    if(trx_state != STATE_RX) return ratio_avg;
     
    -	for(i = 0; start_freq <= end_freq; start_freq += freq_step, i++) {
    -		freq_pos = start_freq + freq_half_step;
    -		pd = wf->powerDensity((double) freq_pos, (double) freq_step);
    -		if(pd < low_value)  low_value = pd;
    -		if(pd > high_value) high_value = pd;
    -	}
    +    for(i = 0; start_freq <= end_freq; start_freq += freq_step, i++) {
    +        freq_pos = start_freq + freq_half_step;
    +        pd = wf->powerDensity((double) freq_pos, (double) freq_step);
    +        if(pd < low_value)  low_value = pd;
    +        if(pd > high_value) high_value = pd;
    +    }
     
    -	if(low)  *low = low_value;
    -	if(high) *high = high_value;
    +    if(low)  *low = low_value;
    +    if(high) *high = high_value;
     
    -	ratio = high_value/low_value;
    -	ratio *= fractional_gain;
    +    ratio = high_value/low_value;
    +    ratio *= fractional_gain;
     
    -	kpsql_pl = ratio_avg = (ratio + pratio0 + pratio1 + pratio2 + pratio3) * 0.20;
    +    kpsql_pl = ratio_avg = (ratio + pratio0 + pratio1 + pratio2 + pratio3) * 0.20;
     
    -	if((ratio_avg > 0.0) && (ratio_avg <= (double) HISTO_COUNT)) {
    -		i = (int) ratio_avg;
    -		i &= 0xFF;
    -		histogram[i]++;
    +    if((ratio_avg > 0.0) && (ratio_avg <= (double) HISTO_COUNT)) {
    +        i = (int) ratio_avg;
    +        i &= 0xFF;
    +        histogram[i]++;
     
    -		if(histogram[i] > HISTO_THRESH_HOLD) {
    -			for(i = 0; i < HISTO_COUNT; i++) {
    -				histogram[i] >>= 1;
    -			}
    -			return 0.0;
    -		}
    -	}
    +        if(histogram[i] > HISTO_THRESH_HOLD) {
    +            for(i = 0; i < HISTO_COUNT; i++) {
    +                histogram[i] >>= 1;
    +            }
    +            return 0.0;
    +        }
    +    }
     
    -	pratio3 = pratio2;
    -	pratio2 = pratio1;
    -	pratio1 = pratio0;
    -	pratio0 = ratio;
    +    pratio3 = pratio2;
    +    pratio2 = pratio1;
    +    pratio1 = pratio0;
    +    pratio0 = ratio;
     
    -	return ratio;
    +    return ratio;
     }
     
     #endif // 0
     
     static void reset_histogram(void)
     {
    -	memset(histogram, 0, sizeof(histogram));
    -	histogram[3] = 1;
    -	inhibit_tx_seconds = time(0) + HISTO_RESET_TX_TIME;
    +    memset(histogram, 0, sizeof(histogram));
    +    histogram[3] = 1;
    +    inhibit_tx_seconds = time(0) + HISTO_RESET_TX_TIME;
     }
     
     /**********************************************************************************
    @@ -3091,28 +3171,28 @@ static void reset_histogram(void)
      **********************************************************************************/
     static void update_sql_display(void)
     {
    -	static int prev_power_level = 0;
    -	static double convert_scale = (1.0 / ((double)HISTO_COUNT));
    +    static int prev_power_level = 0;
    +    static double convert_scale = (1.0 / ((double)HISTO_COUNT));
     
    -	if(progStatus.pwrsqlonoff) {
    -		double high_limit = 0;
    -		double low_limit = 0;
    +    if(progStatus.kpsql_enabled) {
    +        double high_limit = 0;
    +        double low_limit = 0;
     
    -		if(kpsql_pl != prev_power_level) {
    -			prev_power_level = kpsql_pl;
    -			high_limit = sldrSquelch->maximum();
    -			low_limit = sldrSquelch->minimum();
    -			if(kpsql_pl > HISTO_COUNT) {
    -				global_display_metric(low_limit);
    -			} else {
    -				double diff = high_limit - low_limit;
    -				double scaled_value = kpsql_pl * convert_scale;
    -				double convert_value = scaled_value * diff;
    -				double results = high_limit - convert_value;
    -				global_display_metric(results);
    -			}
    -		}
    -	}
    +        if(kpsql_pl != prev_power_level) {
    +            prev_power_level = kpsql_pl;
    +            high_limit = sldrSquelch->maximum();
    +            low_limit = sldrSquelch->minimum();
    +            if(kpsql_pl > HISTO_COUNT) {
    +                global_display_metric(low_limit);
    +            } else {
    +                double diff = high_limit - low_limit;
    +                double scaled_value = kpsql_pl * convert_scale;
    +                double convert_value = scaled_value * diff;
    +                double results = high_limit - convert_value;
    +                global_display_metric(results);
    +            }
    +        }
    +    }
     }
     
     /**********************************************************************************
    @@ -3120,20 +3200,20 @@ static void update_sql_display(void)
      **********************************************************************************/
     static void flush_tx_buffer(void)
     {
    -	int data_count = 0;
    +    int data_count = 0;
     
    -	{
    -		guard_lock to_host_lock(&to_radio_mutex);
    -		kiss_text_available = false;
    -		pText = 0;
    -		data_count = to_radio.size();
    +    {
    +        guard_lock to_host_lock(&to_radio_mutex);
    +        kiss_text_available = false;
    +        pText = 0;
    +        data_count = to_radio.size();
     
    -		if(data_count)
    -			to_radio.clear();
    -	}
    +        if(data_count)
    +            to_radio.clear();
    +    }
     
    -	if(data_count)
    -		bcast_tx_buffer_empty_kiss_frame();
    +    if(data_count)
    +        bcast_tx_buffer_empty_kiss_frame();
     }
     
     /**********************************************************************************
    @@ -3141,30 +3221,30 @@ static void flush_tx_buffer(void)
      **********************************************************************************/
     static void WriteToHostARQBuffered(void)
     {
    -	std::string arq_data = "";
    +    std::string arq_data = "";
     
    -	{
    -		guard_lock to_host_arq_lock(&to_host_arq_mutex);
    -		int data_available = to_arq_host.size();
    +    {
    +        guard_lock to_host_arq_lock(&to_host_arq_mutex);
    +        int data_available = to_arq_host.size();
     
    -		if(kiss_raw_enabled == KISS_RAW_DISABLED) {
    -			if(data_available) {
    -				to_arq_host.clear();
    -			}
    -			return;
    -		}
    +        if(kiss_raw_enabled == KISS_RAW_DISABLED) {
    +            if(data_available) {
    +                to_arq_host.clear();
    +            }
    +            return;
    +        }
     
    -		if(data_available < 1) return;
    +        if(data_available < 1) return;
     
     #ifdef EXTENED_DEBUG_INFO
    -		LOG_HEX(to_arq_host.c_str(), to_arq_host.size());
    +        LOG_HEX(to_arq_host.c_str(), to_arq_host.size());
     #endif
     
    -		arq_data.assign(to_arq_host);
    -		to_arq_host.clear();
    -	}
    +        arq_data.assign(to_arq_host);
    +        to_arq_host.clear();
    +    }
     
    -	kiss_queue_frame(encap_kiss_frame(arq_data, KISS_RAW, kiss_port_no), string("ARQ"));
    +    kiss_queue_frame(encap_kiss_frame(arq_data, KISS_RAW, kiss_port_no), string("ARQ"));
     
     }
     
    @@ -3173,180 +3253,180 @@ static void WriteToHostARQBuffered(void)
      **********************************************************************************/
     static void TransmitCSMA(void)
     {
    -	if(trx_state != STATE_RX) return;
    +    if(trx_state != STATE_RX) return;
     
    -	int data_flag = 0;
    -	int loop_count = KISSLOOP_TIMING / KISSLOOP_FRACTION;
    -	int half_count = loop_count >> 1;
    -	unsigned int random_number = 0;
    -	int index = 0;
    -	//	int skip = 0;
    -	//	int i = 0;
    -	int bw = active_modem->get_bandwidth();
    -	int bw_margin = 100;
    -	int freq = active_modem->get_txfreq();
    -	int delay_time = 0;
    -	int delay_remainder = KISSLOOP_TIMING;
    -	bool detected_signal = true;
    -	time_t busyChannelSeconds = progdefaults.busyChannelSeconds;
    -	int current_time = time(0);
    -	double low = 0.0;
    -	double high = 0.0;
    -	double level = 0.0;
    +    int data_flag = 0;
    +    int loop_count = KISSLOOP_TIMING / KISSLOOP_FRACTION;
    +    int half_count = loop_count >> 1;
    +    unsigned int random_number = 0;
    +    int index = 0;
    +    //	int skip = 0;
    +    //	int i = 0;
    +    int bw = active_modem->get_bandwidth();
    +    int bw_margin = 100;
    +    int freq = active_modem->get_txfreq();
    +    int delay_time = 0;
    +    int delay_remainder = KISSLOOP_TIMING;
    +    bool detected_signal = true;
    +    time_t busyChannelSeconds = progdefaults.busyChannelSeconds;
    +    int current_time = time(0);
    +    double low = 0.0;
    +    double high = 0.0;
    +    double level = 0.0;
     
    -	{
    -		guard_lock to_radio_lock(&to_radio_mutex);
    -		data_flag = to_radio.size();
    -	}
    +    {
    +        guard_lock to_radio_lock(&to_radio_mutex);
    +        data_flag = to_radio.size();
    +    }
     
    -	if(!progdefaults.enableBusyChannel) {
    -		inhibit_tx_seconds = temp_disable_tx_inhibit = 0;
    -	}
    +    if(!progdefaults.enableBusyChannel) {
    +        inhibit_tx_seconds = temp_disable_tx_inhibit = 0;
    +    }
     
    -	// Enabled on signal above threshold and option selected
    -	if(inhibit_tx_seconds) {
    -		if(current_time > inhibit_tx_seconds)
    -			inhibit_tx_seconds = 0;
    -	}
    +    // Enabled on signal above threshold and option selected
    +    if(inhibit_tx_seconds) {
    +        if(current_time > inhibit_tx_seconds)
    +            inhibit_tx_seconds = 0;
    +    }
     
    -	// Enabled on valid packet reception.
    -	if(temp_disable_tx_inhibit) {
    -		if(current_time > temp_disable_tx_inhibit) {
    -			temp_disable_tx_inhibit = 0;
    -		}
    -		busyChannelSeconds = 1;
    -	}
    +    // Enabled on valid packet reception.
    +    if(temp_disable_tx_inhibit) {
    +        if(current_time > temp_disable_tx_inhibit) {
    +            temp_disable_tx_inhibit = 0;
    +        }
    +        busyChannelSeconds = 1;
    +    }
     
    -	// If busy for an extended time flush transmit buffer
    -	if((current_time > (int)transmit_buffer_flush_timeout) && data_flag) {
    -		transmit_buffer_flush_timeout = current_time + TX_BUFFER_TIMEOUT;
    -		flush_tx_buffer();
    -		data_flag = 0;
    -	}
    +    // If busy for an extended time flush transmit buffer
    +    if((current_time > (int)transmit_buffer_flush_timeout) && data_flag) {
    +        transmit_buffer_flush_timeout = current_time + TX_BUFFER_TIMEOUT;
    +        flush_tx_buffer();
    +        data_flag = 0;
    +    }
     
    -	if(progStatus.pwrsqlonoff) {
    -		threshold = (int) (progStatus.sldrPwrSquelchValue * 2.56); // Histogram scaled.
    -	} else {
    -		int idx = 0;
    -		int first_value = 0;
    -		int offset = 2;
    -		for(index = 0; index < HISTO_COUNT; index++) {
    -			if(histogram[index]) {
    -				if(idx == 0) {
    -					first_value = index;
    -				}
    +    if(progStatus.kpsql_enabled) {
    +        threshold = (int) (progStatus.sldrPwrSquelchValue * 2.56); // Histogram scaled.
    +    } else {
    +        int idx = 0;
    +        int first_value = 0;
    +        int offset = 2;
    +        for(index = 0; index < HISTO_COUNT; index++) {
    +            if(histogram[index]) {
    +                if(idx == 0) {
    +                    first_value = index;
    +                }
     
    -				if(idx >= offset) {
    -					threshold = (double) index;
    -					break;
    -				}
    -				idx++;
    -			}
    -		}
    +                if(idx >= offset) {
    +                    threshold = (double) index;
    +                    break;
    +                }
    +                idx++;
    +            }
    +        }
     
    -		if(index > HISTO_COUNT) {
    -			threshold = (double) (first_value + offset);
    -		}
    -	}
    +        if(index > HISTO_COUNT) {
    +            threshold = (double) (first_value + offset);
    +        }
    +    }
     
    -	kpsql_threshold = threshold;
    +    kpsql_threshold = threshold;
     
    -	// Minimum measured bandwidth set to KPSQL_MIN_BANDWIDTH Hz
    -	if(bw < KPSQL_MIN_BANDWIDTH) {
    -		bw = KPSQL_MIN_BANDWIDTH;
    -	}
    +    // Minimum measured bandwidth set to KPSQL_MIN_BANDWIDTH Hz
    +    if(bw < KPSQL_MIN_BANDWIDTH) {
    +        bw = KPSQL_MIN_BANDWIDTH;
    +    }
     
    -	if((data_flag < 1) || (inhibit_tx_seconds)) {
    -		int no_of_hits = 0;
    -		for(index = 0; index < loop_count; index++) {
    -			level = detect_signal(freq, bw + bw_margin, &low, &high);
    +    if((data_flag < 1) || (inhibit_tx_seconds)) {
    +        int no_of_hits = 0;
    +        for(index = 0; index < loop_count; index++) {
    +            level = detect_signal(freq, bw + bw_margin, &low, &high);
     
    -			if(progdefaults.enableBusyChannel) {
    -				if(level > threshold) {
    -					no_of_hits++;
    -					if(no_of_hits > half_count) {
    -						inhibit_tx_seconds = time(0) + busyChannelSeconds;
    -					}
    -				}
    -			}
    -			MilliSleep(loop_count);
    -		}
    +            if(progdefaults.enableBusyChannel) {
    +                if(level > threshold) {
    +                    no_of_hits++;
    +                    if(no_of_hits > half_count) {
    +                        inhibit_tx_seconds = time(0) + busyChannelSeconds;
    +                    }
    +                }
    +            }
    +            MilliSleep(loop_count);
    +        }
     
    -		return;
    -	}
    +        return;
    +    }
     
    -	for(index = 0; index < loop_count; index++) {
    -		if(kiss_reset_flag) return;
    -		int no_of_hits = 0;
    -		level = detect_signal(freq, bw + bw_margin, &low, &high);
    -		if(progdefaults.enableBusyChannel) {
    -			if(level > threshold) {
    -				no_of_hits++;
    -				if(no_of_hits > half_count) {
    -					inhibit_tx_seconds = time(0) + busyChannelSeconds;
    -					return;
    -				}
    -			}
    -		}
    +    for(index = 0; index < loop_count; index++) {
    +        if(kiss_reset_flag) return;
    +        int no_of_hits = 0;
    +        level = detect_signal(freq, bw + bw_margin, &low, &high);
    +        if(progdefaults.enableBusyChannel) {
    +            if(level > threshold) {
    +                no_of_hits++;
    +                if(no_of_hits > half_count) {
    +                    inhibit_tx_seconds = time(0) + busyChannelSeconds;
    +                    return;
    +                }
    +            }
    +        }
     
    -		if(level == 0) return;
    +        if(level == 0) return;
     
    -		if(level < threshold) {
    -			detected_signal = false;
    -			break;
    -		}
    +        if(level < threshold) {
    +            detected_signal = false;
    +            break;
    +        }
     
    -		MilliSleep(KISSLOOP_FRACTION);
    -		delay_remainder -= KISSLOOP_FRACTION;
    -	}
    +        MilliSleep(KISSLOOP_FRACTION);
    +        delay_remainder -= KISSLOOP_FRACTION;
    +    }
     
     #undef DEBUG_HISTO
     #if defined DEBUG_HISTO
    -	for(index = 0; index < 60; index++)
    -		if(histogram[index])
    -			printf("%d = %d ", index, histogram[index]);
    -	printf("\nL=%f T=%f\n", level, threshold);
    +    for(index = 0; index < 60; index++)
    +        if(histogram[index])
    +            printf("%d = %d ", index, histogram[index]);
    +    printf("\nL=%f T=%f\n", level, threshold);
     #endif
     
    -	if(detected_signal || inhibit_tx_seconds) {
    -		return;
    -	}
    +    if(detected_signal || inhibit_tx_seconds) {
    +        return;
    +    }
     
    -	if(progdefaults.csma_enabled) {
    -		if(persistance > 1) {
    -			random_number = rand() & 0xFF;
    -			if(random_number > persistance) {
    -				delay_time = (slot_time * 10);
    -				MilliSleep(delay_time);
    -				delay_remainder -= delay_time;
    +    if(progdefaults.csma_enabled) {
    +        if(persistance > 1) {
    +            random_number = rand() & 0xFF;
    +            if(random_number > persistance) {
    +                delay_time = (slot_time * 10);
    +                MilliSleep(delay_time);
    +                delay_remainder -= delay_time;
     
    -				if(delay_remainder > 0)
    -					MilliSleep(delay_remainder);
    -				return;
    -			}
    -		}
    +                if(delay_remainder > 0)
    +                    MilliSleep(delay_remainder);
    +                return;
    +            }
    +        }
     
    -		delay_time = (tx_delay * 10);
    -		idling = true;
    +        delay_time = (tx_delay * 10);
    +        idling = true;
     
    -		if(trx_state == STATE_RX)
    -			trx_transmit();
    +        if(trx_state == STATE_RX)
    +            trx_transmit();
     
    -		if(delay_time > 0)
    -			MilliSleep(delay_time);
    +        if(delay_time > 0)
    +            MilliSleep(delay_time);
     
    -	} else {
    -		if(trx_state == STATE_RX)
    -			trx_transmit();
    -	}
    -
    -	{
    -		kiss_text_available = true;
    -		idling = false;
    -		active_modem->set_stopflag(false);
    -	}
    -
    -	transmit_buffer_flush_timeout = time(0) + TX_BUFFER_TIMEOUT;
    +    } else {
    +        if(trx_state == STATE_RX)
    +            trx_transmit();
    +    }
    +    
    +    {
    +        kiss_text_available = true;
    +        idling = false;
    +        active_modem->set_stopflag(false);
    +    }
    +    
    +    transmit_buffer_flush_timeout = time(0) + TX_BUFFER_TIMEOUT;
     }
     
     #ifdef KISS_RX_THREAD
    @@ -3355,43 +3435,72 @@ static void TransmitCSMA(void)
      **********************************************************************************/
     static void *ReadFromHostSocket(void *args)
     {
    -	if(!kiss_socket) return (void *)0;
    -
    -	static char buffer[2048];
    -	string str_buffer;
    -	size_t count = 0;
    -
    -	memset(buffer, 0, sizeof(buffer));
    -	str_buffer.reserve(sizeof(buffer));
    -
    -	LOG_INFO("%s", "Kiss RX loop started. ");
    -
    -	while(!kiss_rx_exit) {
    -
    -		memset(buffer, 0, sizeof(buffer));
    -
    -		try {
    -			count = kiss_socket->recvFrom((void *) buffer, sizeof(buffer) - 1);
    -		} catch (...) {
    -			if (errno) LOG_INFO("recvFrom Socket Error %d", errno);
    -			count = 0;
    -		}
    -
    -		if(count && (data_io_enabled == KISS_IO)) {
    -
    +    if(!kiss_socket) return (void *)0;
    +    
    +    static char buffer[2048];
    +    string str_buffer;
    +    size_t count = 0;
    +    Socket *tmp_socket = (Socket *)0;
    +    memset(buffer, 0, sizeof(buffer));
    +    str_buffer.reserve(sizeof(buffer));
    +    
    +    LOG_INFO("%s", "Kiss RX loop started. ");
    +    
    +    kiss_rx_exit = false;
    +    allow_kiss_socket_io = false;
    +    
    +    if(progStatus.kiss_tcp_io && progStatus.kiss_tcp_listen) {
    +        tmp_socket = kiss_socket->accept2();
    +        if(!tmp_socket) {
    +            kiss_rx_exit = true;
    +        } else {
    +            kiss_socket->shut_down();
    +            kiss_socket->close();
    +            kiss_socket = tmp_socket;
    +        }
    +    }
    +    
    +    allow_kiss_socket_io = true;
    +    
    +    while(!kiss_rx_exit) {
    +        
    +        memset(buffer, 0, sizeof(buffer));
    +        
    +        try {
    +            if(allow_kiss_socket_io) {
    +                if(progStatus.kiss_tcp_io)
    +                    count = kiss_socket->recv((void *) buffer, sizeof(buffer) - 1);
    +                else
    +                    count = kiss_socket->recvFrom((void *) buffer, sizeof(buffer) - 1);
    +            }
    +        } catch (...) {
    +            if (errno)
    +                LOG_INFO("recv/recvFrom Socket Error %d", errno);
    +            count = 0;
    +        }
    +        
    +        if((count == 0) && (errno != 0)) {
    +            kiss_rx_exit = true;
    +        }
    +        
    +        if(count && (data_io_enabled == KISS_IO)) {
     #ifdef EXTENED_DEBUG_INFO
    -			LOG_HEX(buffer, count);
    +            LOG_HEX(buffer, count);
     #endif
    -			guard_lock from_host_lock(&from_host_mutex);
    -			from_host.append(buffer, count);
    -		}
    -	}
    -
    -	kiss_exit = true;
    -
    -	LOG_INFO("%s", "Kiss RX loop exit. ");
    -
    -	return (void *)0;
    +            guard_lock from_host_lock(&from_host_mutex);
    +            from_host.append(buffer, count);
    +        }
    +    }
    +    
    +    kiss_exit = true;
    +    allow_kiss_socket_io = false;
    +    if(kiss_socket)
    +        kiss_socket->shut_down();
    +    
    +    Fl::awake(kiss_main_thread_close, (void *) 0);
    +    LOG_INFO("%s", "Kiss RX loop exit. ");
    +    
    +    return (void *)0;
     }
     #else
     /**********************************************************************************
    @@ -3399,36 +3508,41 @@ static void *ReadFromHostSocket(void *args)
      **********************************************************************************/
     static void ReadFromHostSocket()
     {
    -	if(!kiss_socket) return;
    -
    -	static char buffer[2048];
    -	string str_buffer;
    -	size_t count = 0;
    -
    -	memset(buffer, 0, sizeof(buffer));
    -	str_buffer.reserve(sizeof(buffer));
    -
    -	if(data_io_enabled != KISS_IO) {
    -		if(str_buffer.size())
    -			str_buffer.clear();
    -		return;
    -	}
    -
    -	try {
    -		count = kiss_socket->recvFrom((void *) buffer, sizeof(buffer) - 1);
    -	} catch (...) {
    -		LOG_INFO("Kiss RX Loop Shutdown");
    -		count = 0;
    -		kiss_rx_exit = true;
    -	}
    -
    -	if(count) {
    +    if(!kiss_socket) return;
    +    
    +    static char buffer[2048];
    +    string str_buffer;
    +    size_t count = 0;
    +    
    +    memset(buffer, 0, sizeof(buffer));
    +    str_buffer.reserve(sizeof(buffer));
    +    
    +    if(data_io_enabled != KISS_IO) {
    +        if(str_buffer.size())
    +            str_buffer.clear();
    +        return;
    +    }
    +    
    +    try {
    +        if(allow_kiss_socket_io) {
    +            if(progStatus.kiss_tcp_io)
    +                count = kiss_socket->recv((void *) buffer, sizeof(buffer) - 1);
    +            else
    +                count = kiss_socket->recvFrom((void *) buffer, sizeof(buffer) - 1);
    +        }
    +    } catch (...) {
    +        LOG_INFO("Kiss RX Loop Shutdown");
    +        count = 0;
    +        kiss_rx_exit = true;
    +    }
    +    
    +    if(count) {
     #ifdef EXTENED_DEBUG_INFO
    -		LOG_HEX(buffer, count);
    +        LOG_HEX(buffer, count);
     #endif
    -		guard_lock from_host_lock(&from_host_mutex);
    -		from_host.append(buffer, count);
    -	}
    +        guard_lock from_host_lock(&from_host_mutex);
    +        from_host.append(buffer, count);
    +    }
     }
     #endif
     
    @@ -3440,51 +3554,51 @@ extern Progress	*pgrsSquelch;
      **********************************************************************************/
     static void *kiss_loop(void *args)
     {
    -	SET_THREAD_ID(KISS_TID);
    -
    -	int old_trx_state = STATE_TX;
    -
    -	LOG_INFO("%s", "Kiss loop started. ");
    -
    -	while(!kiss_exit){
    -		if(data_io_enabled != KISS_IO) {
    -			MilliSleep(100);
    -			kiss_text_available = false;
    -			kiss_reset_buffers();
    -			continue;
    -		}
    -
    -		if(old_trx_state != trx_state) {
    -			if(kiss_bcast_trx_toggle) {
    -				switch(trx_state) {
    -					case STATE_TX:
    -					case STATE_RX:
    -					case STATE_TUNE:
    -						bcast_trxs_kiss_frame(trx_state);
    -					default :
    -						break;
    -				}
    -			}
    -
    -			old_trx_state = trx_state;
    -		}
    -
    -		update_sql_display();
    -		ReadFromHostBuffered();
    -		ReadFromRadioBuffered();
    -		WriteToHostBCastFramesBuffered();
    -		WriteToHostARQBuffered();
    -		WriteToHostSocket();
    -
    -		TransmitCSMA(); // Loop delay located in this routine.
    -
    +    SET_THREAD_ID(KISS_TID);
    +    
    +    int old_trx_state = STATE_TX;
    +    
    +    LOG_INFO("%s", "Kiss loop started. ");
    +    
    +    while(!kiss_exit){
    +        if(data_io_enabled != KISS_IO) {
    +            MilliSleep(100);
    +            kiss_text_available = false;
    +            kiss_reset_buffers();
    +            continue;
    +        }
    +        
    +        if(old_trx_state != trx_state) {
    +            if(kiss_bcast_trx_toggle) {
    +                switch(trx_state) {
    +                    case STATE_TX:
    +                    case STATE_RX:
    +                    case STATE_TUNE:
    +                        bcast_trxs_kiss_frame(trx_state);
    +                    default :
    +                        break;
    +                }
    +            }
    +            
    +            old_trx_state = trx_state;
    +        }
    +        
    +        update_sql_display();
    +        ReadFromHostBuffered();
    +        ReadFromRadioBuffered();
    +        WriteToHostBCastFramesBuffered();
    +        WriteToHostARQBuffered();
    +        WriteToHostSocket();
    +        
    +        TransmitCSMA(); // Loop delay located in this routine.
    +        
     #ifndef KISS_RX_THREAD
    -		ReadFromHostSocket();
    +        ReadFromHostSocket();
     #endif
    -
    -	}
    -	// exit the kiss thread
    -	return NULL;
    +        MilliSleep(5);
    +    }
    +    // exit the kiss thread
    +    return NULL;
     }
     
     
    @@ -3493,19 +3607,19 @@ static void *kiss_loop(void *args)
      **********************************************************************************/
     void WriteKISS(const char data)
     {
    -	if (active_modem->get_mode() == MODE_FSQ) return;
    -
    -	if(kiss_reset_flag) return;
    -
    -	{
    -		guard_lock from_radio_lock(&from_radio_mutex);
    -		from_radio += data;
    -	}
    -
    -	if(kiss_raw_enabled != KISS_RAW_DISABLED) {
    -		guard_lock to_host_arq_lock(&to_host_arq_mutex);
    -		to_arq_host += data;
    -	}
    +    if (active_modem->get_mode() == MODE_FSQ) return;
    +    
    +    if(kiss_reset_flag) return;
    +    
    +    {
    +        guard_lock from_radio_lock(&from_radio_mutex);
    +        from_radio += data;
    +    }
    +    
    +    if(kiss_raw_enabled != KISS_RAW_DISABLED) {
    +        guard_lock to_host_arq_lock(&to_host_arq_mutex);
    +        to_arq_host += data;
    +    }
     }
     
     /**********************************************************************************
    @@ -3513,21 +3627,21 @@ void WriteKISS(const char data)
      **********************************************************************************/
     void WriteKISS(const char *data)
     {
    -	if (active_modem->get_mode() == MODE_FSQ) return;
    -
    -	if(kiss_reset_flag) return;
    -
    -	{
    -		guard_lock from_radio_lock(&from_radio_mutex);
    -		if(data)
    -			from_radio.append(data);
    -	}
    -
    -	{
    -		guard_lock to_host_arq_lock(&to_host_arq_mutex);
    -		if(data && (kiss_raw_enabled != KISS_RAW_DISABLED))
    -			to_arq_host.append(data);
    -	}
    +    if (active_modem->get_mode() == MODE_FSQ) return;
    +    
    +    if(kiss_reset_flag) return;
    +    
    +    {
    +        guard_lock from_radio_lock(&from_radio_mutex);
    +        if(data)
    +            from_radio.append(data);
    +    }
    +    
    +    {
    +        guard_lock to_host_arq_lock(&to_host_arq_mutex);
    +        if(data && (kiss_raw_enabled != KISS_RAW_DISABLED))
    +            to_arq_host.append(data);
    +    }
     }
     
     /**********************************************************************************
    @@ -3535,23 +3649,23 @@ void WriteKISS(const char *data)
      **********************************************************************************/
     void WriteKISS(const char *data, size_t size)
     {
    -	if (active_modem->get_mode() == MODE_FSQ) return;
    -
    -	if(kiss_reset_flag) return;
    -
    -	{
    -		guard_lock from_radio_lock(&from_radio_mutex);
    -		if(data && size) {
    -			from_radio.append(data, size);
    -		}
    -	}
    -
    -	{
    -		guard_lock to_host_arq_lock(&to_host_arq_mutex);
    -		if(data && size && (kiss_raw_enabled != KISS_RAW_DISABLED)) {
    -			to_arq_host.append(data, size);
    -		}
    -	}
    +    if (active_modem->get_mode() == MODE_FSQ) return;
    +    
    +    if(kiss_reset_flag) return;
    +    
    +    {
    +        guard_lock from_radio_lock(&from_radio_mutex);
    +        if(data && size) {
    +            from_radio.append(data, size);
    +        }
    +    }
    +    
    +    {
    +        guard_lock to_host_arq_lock(&to_host_arq_mutex);
    +        if(data && size && (kiss_raw_enabled != KISS_RAW_DISABLED)) {
    +            to_arq_host.append(data, size);
    +        }
    +    }
     }
     
     /**********************************************************************************
    @@ -3559,23 +3673,23 @@ void WriteKISS(const char *data, size_t size)
      **********************************************************************************/
     void WriteKISS(std::string data)
     {
    -	if (active_modem->get_mode() == MODE_FSQ) return;
    -
    -	if(kiss_reset_flag) return;
    -
    -	{
    -		guard_lock from_radio_lock(&from_radio_mutex);
    -		if(!data.empty()) {
    -			from_radio.append(data);
    -		}
    -	}
    -
    -	{
    -		guard_lock to_host_arq_lock(&to_host_arq_mutex);
    -		if(!data.empty() && (kiss_raw_enabled != KISS_RAW_DISABLED)) {
    -			to_arq_host.append(data);
    -		}
    -	}
    +    if (active_modem->get_mode() == MODE_FSQ) return;
    +    
    +    if(kiss_reset_flag) return;
    +    
    +    {
    +        guard_lock from_radio_lock(&from_radio_mutex);
    +        if(!data.empty()) {
    +            from_radio.append(data);
    +        }
    +    }
    +    
    +    {
    +        guard_lock to_host_arq_lock(&to_host_arq_mutex);
    +        if(!data.empty() && (kiss_raw_enabled != KISS_RAW_DISABLED)) {
    +            to_arq_host.append(data);
    +        }
    +    }
     }
     
     /**********************************************************************************
    @@ -3583,18 +3697,30 @@ void WriteKISS(std::string data)
      **********************************************************************************/
     void WriteToHostSocket(void)
     {
    -	if(kiss_reset_flag) return;
    +    if(kiss_reset_flag) return;
     
    -	guard_lock to_host_lock(&to_host_mutex);
    -	if(to_host.empty()) return;
    +    guard_lock to_host_lock(&to_host_mutex);
    +    size_t count = 0;
     
    -	if(kiss_socket && data_io_enabled == KISS_IO) {
    -		kiss_socket->sendTo(to_host.c_str(), to_host.size());
    +    if(to_host.empty()) return;
    +    
    +    if(kiss_socket && data_io_enabled == KISS_IO) {
    +        if(allow_kiss_socket_io) {
    +            if(progStatus.kiss_tcp_io)
    +                count = kiss_socket->send(to_host.c_str(), to_host.size());
    +            else
    +                count = kiss_socket->sendTo(to_host.c_str(), to_host.size());
    +        }
     #ifdef EXTENED_DEBUG_INFO
    -		LOG_HEX(to_host.c_str(), to_host.size());
    +        LOG_HEX(to_host.c_str(), to_host.size());
     #endif
    -	}
    -	to_host.clear();
    +        if(count == 0) {
    +            Fl::awake(kiss_main_thread_close, (void *) 0);
    +            LOG_INFO("%s", "Write error to KISS socket. ");
    +        }
    +    }
    +
    +    to_host.clear();
     }
     
     /**********************************************************************************
    @@ -3602,15 +3728,15 @@ void WriteToHostSocket(void)
      **********************************************************************************/
     static void ReadFromHostBuffered(void)
     {
    -	if(!kiss_socket) return;
    -
    -	guard_lock from_host_lock(&from_host_mutex);
    -	if(from_host.empty()) return;
    +    if(!kiss_socket) return;
    +    
    +    guard_lock from_host_lock(&from_host_mutex);
    +    if(from_host.empty()) return;
     #ifdef EXTENED_DEBUG_INFO
    -	LOG_HEX(from_host.c_str(), from_host.size());
    +    LOG_HEX(from_host.c_str(), from_host.size());
     #endif
    -	parse_kiss_frame(from_host);
    -	from_host.clear();
    +    parse_kiss_frame(from_host);
    +    from_host.clear();
     }
     
     /**********************************************************************************
    @@ -3618,91 +3744,91 @@ static void ReadFromHostBuffered(void)
      **********************************************************************************/
     void ReadFromRadioBuffered(void)
     {
    -	if(kiss_reset_flag) return;
    -
    -	guard_lock from_radio_lock(&from_radio_mutex);
    -	if(from_radio.empty()) return;
    -
    -	int pos = 0;
    -	int pos2 = 0;
    -	//	unsigned int crc = 0;
    -	KISS_QUEUE_FRAME *frame = (KISS_QUEUE_FRAME *)0;
    -	static char frame_marker[2] = { (char)(KISS_FEND), 0 };
    -	std::string one_frame = "";
    -
    -	pos = from_radio.find(frame_marker);
    -
    -	if(pos == (int)(std::string::npos)) {
    -		from_radio.clear();
    -		return;
    -	}
    -
    -	if(pos != 0) {
    -		from_radio.erase(0, pos);
    -		pos = 0;
    -	}
    -
    -	pos2 = from_radio.find(frame_marker, pos + 1);
    -	if(pos2 != (int)(std::string::npos)) {
    -		one_frame.assign(from_radio, pos, pos2 - pos + 1);
    -	} else {
    -		if(from_radio.size() > MAX_TEMP_BUFFER_SIZE)
    -			from_radio.clear();
    -		return;
    -	}
    -
    -	char *buffer = (char *)0;
    -	size_t buffer_size = one_frame.size() + BUFFER_PADDING;
    -
    -	buffer = new char [buffer_size];
    -
    -	if(!buffer) {
    -		LOG_DEBUG("Memory Allocation Error Near Line No. %d", __LINE__);
    -		goto EXIT;
    -	}
    -
    -	memset(buffer, 0, buffer_size);
    -
    -	buffer_size = one_frame.size();
    -	memcpy(buffer, one_frame.c_str(), buffer_size);
    -
    +    if(kiss_reset_flag) return;
    +    
    +    guard_lock from_radio_lock(&from_radio_mutex);
    +    if(from_radio.empty()) return;
    +    
    +    int pos = 0;
    +    int pos2 = 0;
    +    //	unsigned int crc = 0;
    +    KISS_QUEUE_FRAME *frame = (KISS_QUEUE_FRAME *)0;
    +    static char frame_marker[2] = { (char)(KISS_FEND), 0 };
    +    std::string one_frame = "";
    +    
    +    pos = from_radio.find(frame_marker);
    +    
    +    if(pos == (int)(std::string::npos)) {
    +        from_radio.clear();
    +        return;
    +    }
    +    
    +    if(pos != 0) {
    +        from_radio.erase(0, pos);
    +        pos = 0;
    +    }
    +    
    +    pos2 = from_radio.find(frame_marker, pos + 1);
    +    if(pos2 != (int)(std::string::npos)) {
    +        one_frame.assign(from_radio, pos, pos2 - pos + 1);
    +    } else {
    +        if(from_radio.size() > MAX_TEMP_BUFFER_SIZE)
    +            from_radio.clear();
    +        return;
    +    }
    +    
    +    char *buffer = (char *)0;
    +    size_t buffer_size = one_frame.size() + BUFFER_PADDING;
    +    
    +    buffer = new char [buffer_size];
    +    
    +    if(!buffer) {
    +        LOG_DEBUG("Memory Allocation Error Near Line No. %d", __LINE__);
    +        goto EXIT;
    +    }
    +    
    +    memset(buffer, 0, buffer_size);
    +    
    +    buffer_size = one_frame.size();
    +    memcpy(buffer, one_frame.c_str(), buffer_size);
    +    
     #ifdef EXTENED_DEBUG_INFO
    -	LOG_HEX(buffer, buffer_size);
    +    LOG_HEX(buffer, buffer_size);
     #endif
    -
    -	buffer_size = decap_hdlc_frame(buffer, buffer_size);
    -
    -	if(buffer_size) {
    -		from_radio.erase(pos, pos2 - pos + 1);
    -
    -		if(kiss_raw_enabled != KISS_RAW_ONLY) {
    -			frame = encap_kiss_frame(buffer, buffer_size, KISS_DATA, kiss_port_no);
    -
    -			if(!frame || !frame->data) {
    -				LOG_DEBUG("Frame Allocation Error Near Line %d", __LINE__);
    -				goto EXIT;
    -			}
    -
    -			WriteToHostBuffered((const char *) frame->data, (size_t) frame->size);
    -		}
    -	} else {
    -		from_radio.erase(pos, pos + 1);
    -	}
    -
    +    
    +    buffer_size = decap_hdlc_frame(buffer, buffer_size);
    +    
    +    if(buffer_size) {
    +        from_radio.erase(pos, pos2 - pos + 1);
    +        
    +        if(kiss_raw_enabled != KISS_RAW_ONLY) {
    +            frame = encap_kiss_frame(buffer, buffer_size, KISS_DATA, kiss_port_no);
    +            
    +            if(!frame || !frame->data) {
    +                LOG_DEBUG("Frame Allocation Error Near Line %d", __LINE__);
    +                goto EXIT;
    +            }
    +            
    +            WriteToHostBuffered((const char *) frame->data, (size_t) frame->size);
    +        }
    +    } else {
    +        from_radio.erase(pos, pos + 1);
    +    }
    +    
     EXIT:;
    -
    -	if(frame) {
    -		if(frame->data) {
    -			frame->data[0] = 0;
    -			delete [] frame->data;
    -		}
    -		delete frame;
    -	}
    -
    -	if(buffer) {
    -		buffer[0] = 0;
    -		delete [] buffer;
    -	}
    +    
    +    if(frame) {
    +        if(frame->data) {
    +            frame->data[0] = 0;
    +            delete [] frame->data;
    +        }
    +        delete frame;
    +    }
    +    
    +    if(buffer) {
    +        buffer[0] = 0;
    +        delete [] buffer;
    +    }
     }
     
     /**********************************************************************************
    @@ -3710,15 +3836,64 @@ EXIT:;
      **********************************************************************************/
     void WriteToHostBCastFramesBuffered(void)
     {
    -	guard_lock kiss_bc_frame_lock(&kiss_bc_frame_mutex);
    -	if(kiss_bc_frame.empty()) return;
    -	WriteToHostBuffered((const char *) kiss_bc_frame.c_str(), (size_t) kiss_bc_frame.size());
    -
    +    guard_lock kiss_bc_frame_lock(&kiss_bc_frame_mutex);
    +    if(kiss_bc_frame.empty()) return;
    +    WriteToHostBuffered((const char *) kiss_bc_frame.c_str(), (size_t) kiss_bc_frame.size());
    +    
     #ifdef EXTENED_DEBUG_INFO
    -	LOG_HEX(kiss_bc_frame.c_str(), (size_t) kiss_bc_frame.size());
    +    LOG_HEX(kiss_bc_frame.c_str(), (size_t) kiss_bc_frame.size());
     #endif
    +    
    +    kiss_bc_frame.clear();
    +}
     
    -	kiss_bc_frame.clear();
    +/**********************************************************************************
    + *
    + **********************************************************************************/
    +bool tcp_init(bool connect_flag)
    +{
    +    if(progdefaults.kiss_address.empty() || progdefaults.kiss_io_port.empty()) {
    +        LOG_DEBUG("%s", "KISS IP Address or Port null");
    +        return false;
    +    }
    +    
    +    kiss_ip_address.assign(progdefaults.kiss_address);
    +    kiss_ip_io_port.assign(progdefaults.kiss_io_port);
    +    kiss_ip_out_port.assign(progdefaults.kiss_out_port);
    +    
    +    try {
    +        kiss_socket = new Socket(Address(kiss_ip_address.c_str(), kiss_ip_io_port.c_str(), "tcp"));
    +        kiss_socket->set_autoclose(true);
    +        kiss_socket->set_nonblocking(false);
    +        
    +        if(progdefaults.kiss_tcp_listen)
    +            kiss_socket->bind();
    +    }
    +    catch (const SocketException& e) {
    +        LOG_ERROR("Could not resolve %s: %s", kiss_ip_address.c_str(), e.what());
    +        if(kiss_socket) {
    +            kiss_socket->shut_down();
    +            kiss_socket->close();
    +            delete kiss_socket;
    +            kiss_socket = 0;
    +            kiss_enabled = 0;
    +        }
    +        return false;
    +    }
    +    
    +    if(connect_flag) {
    +        if(kiss_socket->connect1() == false) {
    +            LOG_INFO("Connection Failed: Host program present?");
    +            kiss_socket->shut_down();
    +            kiss_socket->close();
    +            delete kiss_socket;
    +            kiss_socket = 0;
    +            kiss_enabled = 0;
    +            return false;
    +        }
    +    }
    +    
    +    return true;
     }
     
     /**********************************************************************************
    @@ -3726,60 +3901,70 @@ void WriteToHostBCastFramesBuffered(void)
      **********************************************************************************/
     bool udp_init(void)
     {
    -	if(progdefaults.kiss_address.empty() || progdefaults.kiss_io_port.empty()) {
    -		LOG_DEBUG("%s", "KISS IP Address or Port null");
    -		return false;
    -	}
    -
    -	kiss_ip_address.assign(progdefaults.kiss_address);
    -	kiss_ip_io_port.assign(progdefaults.kiss_io_port);
    -	kiss_ip_out_port.assign(progdefaults.kiss_out_port);
    -
    -	try {
    -		kiss_socket = new Socket(Address(kiss_ip_address.c_str(), kiss_ip_io_port.c_str(), "udp"));
    -		kiss_socket->dual_port(&progdefaults.kiss_dual_port_enabled);
    -		kiss_socket->set_dual_port_number(kiss_ip_out_port);
    -		kiss_socket->set_autoclose(true);
    -		kiss_socket->set_nonblocking(false);
    -		kiss_socket->bindUDP();
    -	}
    -	catch (const SocketException& e) {
    -		LOG_ERROR("Could not resolve %s: %s", kiss_ip_address.c_str(), e.what());
    -		return false;
    -	}
    -
    -	return true;
    +    if(progdefaults.kiss_address.empty() || progdefaults.kiss_io_port.empty()) {
    +        LOG_DEBUG("%s", "KISS IP Address or Port null");
    +        return false;
    +    }
    +    
    +    kiss_ip_address.assign(progdefaults.kiss_address);
    +    kiss_ip_io_port.assign(progdefaults.kiss_io_port);
    +    kiss_ip_out_port.assign(progdefaults.kiss_out_port);
    +    
    +    try {
    +        kiss_socket = new Socket(Address(kiss_ip_address.c_str(), kiss_ip_io_port.c_str(), "udp"));
    +        kiss_socket->dual_port(&progdefaults.kiss_dual_port_enabled);
    +        kiss_socket->set_dual_port_number(kiss_ip_out_port);
    +        kiss_socket->set_autoclose(true);
    +        kiss_socket->set_nonblocking(false);
    +        
    +        if(progdefaults.kiss_tcp_listen) // Listen flag indcates server mode.
    +            kiss_socket->bindUDP();
    +        
    +    } catch (const SocketException& e) {
    +        LOG_ERROR("Could not resolve %s: %s", kiss_ip_address.c_str(), e.what());
    +        if(kiss_socket) {
    +            kiss_socket->shut_down();
    +            kiss_socket->close();
    +            delete kiss_socket;
    +            kiss_socket = 0;
    +            kiss_enabled = 0;
    +        }
    +        return false;
    +    }
    +    
    +    return true;
     }
    +
     /**********************************************************************************
      *
      **********************************************************************************/
     void kiss_reset_buffers(void)
     {
    -	{
    -		guard_lock to_host_lock(&to_host_mutex);
    -		if(!to_host.empty())
    -			to_host.clear();
    -	}
    -
    -	{
    -		guard_lock to_host_lock(&from_radio_mutex);
    -		if(!from_radio.empty())
    -			from_radio.clear();
    -	}
    -
    -	{
    -		guard_lock to_host_lock(&to_radio_mutex);
    -		pText = 0;
    -		kiss_text_available = false;
    -		if(!to_radio.empty())
    -			to_radio.clear();
    -	}
    -
    -	{
    -		guard_lock kiss_bc_frame_lock(&kiss_bc_frame_mutex);
    -		if(!kiss_bc_frame.empty())
    -			kiss_bc_frame.clear();
    -	}
    +    {
    +        guard_lock to_host_lock(&to_host_mutex);
    +        if(!to_host.empty())
    +            to_host.clear();
    +    }
    +    
    +    {
    +        guard_lock to_host_lock(&from_radio_mutex);
    +        if(!from_radio.empty())
    +            from_radio.clear();
    +    }
    +    
    +    {
    +        guard_lock to_host_lock(&to_radio_mutex);
    +        pText = 0;
    +        kiss_text_available = false;
    +        if(!to_radio.empty())
    +            to_radio.clear();
    +    }
    +    
    +    {
    +        guard_lock kiss_bc_frame_lock(&kiss_bc_frame_mutex);
    +        if(!kiss_bc_frame.empty())
    +            kiss_bc_frame.clear();
    +    }
     }
     
     /**********************************************************************************
    @@ -3787,126 +3972,219 @@ void kiss_reset_buffers(void)
      **********************************************************************************/
     void kiss_reset(void)
     {
    -	kiss_reset_flag     = true;
    -	kiss_text_available = false;
    -	persistance         = 63;
    -	tx_delay            = 50;
    -	duplex              = KISS_HALF_DUPLEX;
    -	crc_mode            = CRC16_NONE;
    -	smack_crc_enabled   = false;
    -	pText = 0;
    -
    -	if(data_io_enabled == KISS_IO)
    -		data_io_enabled = DISABLED_IO;
    -
    -	MilliSleep(1000);
    -
    -	void kiss_reset_buffers(void);
    -
    -	if (trx_state == STATE_TX || trx_state == STATE_TUNE) {
    -		REQ(abort_tx);
    -	}
    -
    -	kiss_reset_flag = false;
    -
    -	if(data_io_enabled == DISABLED_IO)
    -		data_io_enabled = KISS_IO;
    +    kiss_reset_flag     = true;
    +    kiss_text_available = false;
    +    persistance         = 63;
    +    tx_delay            = 50;
    +    duplex              = KISS_HALF_DUPLEX;
    +    crc_mode            = CRC16_NONE;
    +    smack_crc_enabled   = false;
    +    pText = 0;
    +    
    +    if(data_io_enabled == KISS_IO)
    +        data_io_enabled = DISABLED_IO;
    +    
    +    MilliSleep(1000);
    +    
    +    void kiss_reset_buffers(void);
    +    
    +    if (trx_state == STATE_TX || trx_state == STATE_TUNE) {
    +        REQ(abort_tx);
    +    }
    +    
    +    kiss_reset_flag = false;
    +    
    +    if(data_io_enabled == DISABLED_IO)
    +        data_io_enabled = KISS_IO;
     }
     
     /**********************************************************************************
      *
      **********************************************************************************/
    -void kiss_init(void)
    +void kiss_init(bool connect_flag)
     {
    -	kiss_enabled = false;
    -	kiss_exit = false;
    -
    -	int index = 0;
    -
    -	for(index = 0; index < NUM_MODES; index++)
    -		if(mode_info[index].iface_io & KISS_IO)
    -			availabe_kiss_modems.push_back(mode_info[index].sname);
    -
    -// progStatus.data_io_enabled (widget state), data_io_enabled (program state)
    -	if(progStatus.data_io_enabled == KISS_IO) {
    -		if(!(active_modem->iface_io() & KISS_IO)) {
    -			set_default_kiss_modem();
    -		}
    -	}
    -
    -
    -	if(init_hist_flag) {
    -		memset(histogram, 0, sizeof(histogram));
    -		init_hist_flag = false;
    -	}
    -
    -	if(!udp_init()) return;
    -
    -	LOG_INFO("%s", "UDP Init - OK");
    -
    -	srand(time(0)); // For CSMA persistance
    -
    -	update_kpsql_fractional_gain(progdefaults.kpsql_attenuation);
    -
    -	if (pthread_create(&kiss_thread, NULL, kiss_loop, NULL) < 0) {
    -		LOG_ERROR("KISS kiss_thread: pthread_create failed");
    -		return;
    -	}
    -
    -
    +    kiss_enabled = false;
    +    kiss_exit = false;
    +    
    +    // progStatus.data_io_enabled (widget state), data_io_enabled (program state)
    +    
    +    if(progStatus.data_io_enabled == KISS_IO) {
    +        if(!(active_modem->iface_io() & KISS_IO)) {
    +            set_default_kiss_modem();
    +        }
    +    }
    +    
    +    if(init_hist_flag) {
    +        memset(histogram, 0, sizeof(histogram));
    +        init_hist_flag = false;
    +    }
    +    
    +    srand(time(0)); // For CSMA persistance
    +    update_kpsql_fractional_gain(progdefaults.kpsql_attenuation);
    +    
    +    data_io_type = DATA_IO_NA;
    +    
    +    if(progStatus.kiss_tcp_io) {
    +        
    +        if(retry_count > KISS_CONNECT_RETRY_COUNT)
    +            retry_count = KISS_CONNECT_RETRY_COUNT;
    +        
    +        if(progStatus.kiss_tcp_listen)
    +            connect_flag = false;
    +        
    +        do {
    +            if(tcp_init(connect_flag)) break;
    +            
    +            if(progStatus.kiss_tcp_listen) return;
    +            
    +            MilliSleep(KISS_RETRY_WAIT_TIME);
    +            
    +            if(retry_count-- > 0) continue;
    +            else return;
    +            
    +        } while(1);
    +        
    +        LOG_INFO("%s", "TCP Init - OK");
    +    } else {
    +        if(!udp_init()) return;
    +        LOG_INFO("%s", "UDP Init - OK");
    +    }
    +    
    +    Fl::awake(kiss_io_set_button_state, (void *) IO_START_STR);
    +    
    +    if (pthread_create(&kiss_thread, NULL, kiss_loop, NULL) < 0) {
    +        LOG_ERROR("KISS kiss_thread: pthread_create failed");
    +        return;
    +    }
    +    
     #ifdef KISS_RX_THREAD
    -	if (pthread_create(&kiss_rx_socket_thread, NULL, ReadFromHostSocket, NULL) < 0) {
    -		LOG_ERROR("KISS kiss_rx_socket_thread: pthread_create failed");
    -		kiss_exit = true;
    -		pthread_join(kiss_thread, NULL);
    -		return;
    -	}
    +    if (pthread_create(&kiss_rx_socket_thread, NULL, ReadFromHostSocket, NULL) < 0) {
    +        LOG_ERROR("KISS kiss_rx_socket_thread: pthread_create failed");
    +        kiss_exit = true;
    +        pthread_join(kiss_thread, NULL);
    +        return;
    +    }
     #endif
    -
    -	kiss_enabled = true;
    +    
    +    if(progStatus.kiss_tcp_io) {
    +        data_io_type = DATA_IO_TCP;
    +    } else {
    +        data_io_type = DATA_IO_UDP;
    +    }
    +    
    +    Fl::awake(kiss_io_set_button_state, (void *) IO_STOP_STR);
    +    
    +    if(progdefaults.data_io_enabled == KISS_IO)
    +        data_io_enabled = KISS_IO;
    +    
    +    kiss_enabled = true;
    +    allow_kiss_socket_io = true;
     }
     
     /**********************************************************************************
      *
      **********************************************************************************/
    -void kiss_close(void)
    +void kiss_main_thread_close(void *ptr)
     {
    -	if (!kiss_enabled) return;
    -
    -	kiss_text_available = false;
    -
    -	if(data_io_enabled == KISS_IO)
    -		data_io_enabled = DISABLED_IO;
    -
    -	if(kiss_socket) {
    -		kiss_socket->shut_down();
    -		kiss_socket->close();
    -	}
    +    kiss_close(true);
    +}
     
    +/**********************************************************************************
    + *
    + **********************************************************************************/
    +void kiss_close(bool override_flag)
    +{
    +    //	if (!kiss_enabled && !override_flag) return;
    +    
    +    kiss_text_available = false;
    +    allow_kiss_socket_io = false;
    +    
    +    if(data_io_enabled == KISS_IO) {
    +        data_io_enabled = DISABLED_IO;
    +        data_io_type = DATA_IO_NA;
    +    }
    +    
    +    if(kiss_socket) {
    +        kiss_socket->shut_down();
    +        kiss_socket->close();
    +    } else {
    +        return;
    +    }
    +    
     #ifdef KISS_RX_THREAD
    -	kiss_rx_exit = true;
    -
    -	MilliSleep(250);
    -
    -	if(kiss_rx_exit)
    -		pthread_join(kiss_rx_socket_thread, NULL);
    -	else
    -		CANCEL_THREAD(kiss_rx_socket_thread);
    +    kiss_rx_exit = true;
    +    
    +    MilliSleep(250);
    +    
    +    if(kiss_rx_exit)
    +        pthread_join(kiss_rx_socket_thread, NULL);
    +    else
    +        CANCEL_THREAD(kiss_rx_socket_thread);
     #else
    -	kiss_exit = true;
    +    kiss_exit = true;
     #endif
    +    
    +    MilliSleep(250);
    +    
    +    if(kiss_exit)
    +        pthread_join(kiss_thread, NULL);
    +    else
    +        CANCEL_THREAD(kiss_thread);
    +    
    +    LOG_INFO("%s", "Kiss loop terminated. ");
    +    
    +    kiss_socket = 0;
    +    kiss_enabled = false;
    +    
    +    Fl::awake(kiss_io_set_button_state, (void *) IO_START_STR);
    +    
    +    if((retry_count > 0) && progStatus.kiss_tcp_io)
    +        Fl::awake(kiss_main_thread_retry_open, (void *) 0);
    +    
    +}
     
    -	MilliSleep(250);
    +/**********************************************************************************
    + *
    + **********************************************************************************/
    +void kiss_main_thread_retry_open(void *ptr)
    +{
    +    if(!progStatus.kiss_tcp_listen)
    +        MilliSleep(KISS_RETRY_WAIT_TIME);
    +    connect_to_kiss_io(false);
    +}
     
    -	if(kiss_exit)
    -		pthread_join(kiss_thread, NULL);
    -	else
    -		CANCEL_THREAD(kiss_thread);
    +/**********************************************************************************
    + *
    + **********************************************************************************/
    +void connect_to_kiss_io(bool user_requested)
    +{
    +    guard_lock external_lock(&restart_mutex);
    +    
    +    if(kiss_socket) {
    +        if(user_requested)
    +            retry_count = 0;
    +        
    +        kiss_close(true);
    +        
    +        if(user_requested)
    +            return;
    +    }
    +    
    +    if(user_requested || progStatus.kiss_tcp_listen)
    +        retry_count = KISS_CONNECT_RETRY_COUNT;
    +    
    +    if(retry_count > 0) {
    +        retry_count--;
    +        kiss_init(progdefaults.kiss_tcp_listen ? false : true);
    +    }
    +}
     
    -	LOG_INFO("%s", "Kiss loop terminated. ");
    -
    -
    -	kiss_enabled = false;
    +/**********************************************************************************
    + *
    + **********************************************************************************/
    +bool kiss_thread_running(void)
    +{
    +    return (bool) kiss_enabled;
     }
     
     /**********************************************************************************
    @@ -3914,27 +4192,27 @@ void kiss_close(void)
      **********************************************************************************/
     int kiss_get_char(void)
     {
    -	/// Mutex is unlocked when returning from function
    -	guard_lock to_radio_lock(&to_radio_mutex);
    -	int c = 0;
    -	static bool toggle_flag = 0;
    -
    -	if (kiss_text_available) {
    -		if (pText != (int)to_radio.length()) {
    -			c = to_radio[pText++] & 0xFF;
    -			toggle_flag = true;
    -		} else {
    -			kiss_text_available = false;
    -			to_radio.clear();
    -			pText = 0;
    -			c = GET_TX_CHAR_ETX;
    -
    -			if(toggle_flag) {
    -				bcast_tx_buffer_empty_kiss_frame();
    -				toggle_flag = 0;
    -			}
    -		}
    -	}
    -
    -	return c;
    +    /// Mutex is unlocked when returning from function
    +    guard_lock to_radio_lock(&to_radio_mutex);
    +    int c = 0;
    +    static bool toggle_flag = 0;
    +    
    +    if (kiss_text_available) {
    +        if (pText != (int)to_radio.length()) {
    +            c = to_radio[pText++] & 0xFF;
    +            toggle_flag = true;
    +        } else {
    +            kiss_text_available = false;
    +            to_radio.clear();
    +            pText = 0;
    +            c = GET_TX_CHAR_ETX;
    +            
    +            if(toggle_flag) {
    +                bcast_tx_buffer_empty_kiss_frame();
    +                toggle_flag = 0;
    +            }
    +        }
    +    }
    +    
    +    return c;
     }
    diff --git a/src/misc/kmlserver.cxx b/src/misc/kmlserver.cxx
    index 5623050c..92ff91d6 100644
    --- a/src/misc/kmlserver.cxx
    +++ b/src/misc/kmlserver.cxx
    @@ -45,6 +45,7 @@
     #include "threads.h"
     #include "strutil.h"
     #include "configuration.h"
    +#include "fl_digi.h"
     
     #include "irrXML.h"
     
    @@ -100,7 +101,7 @@ static time_t KmlFromTimestamp( const char * ts ) {
     
     	/// So all fields are initialised with correct default values.
     	time_t timNow = time(NULL);
    -	tm objTm = *gmtime( &timNow ); 
    +	tm objTm = *gmtime( &timNow );
     
     	int r = sscanf( ts, "%4d-%02d-%02dT%02d:%02dZ",
     			&objTm.tm_year,
    @@ -203,7 +204,7 @@ static void KmlHeader( std::ostream & ostrm, const std::string & title ) {
     }
     
     /// Appended at the end of each KML document.
    -static const char KmlFooter[] = 
    +static const char KmlFooter[] =
     	"\n"
     	"\n" ;
     
    @@ -260,7 +261,7 @@ class  KmlSrvImpl : public KmlServer {
     					ostrm << "<" FLDIGI_TAG_ITM " " FLDIGI_TAG_KEY "=\"" << it->first
     						<< "\" " FLDIGI_TAG_VAL "=\"";
     					StripHtmlTags(ostrm,it->second);
    -					ostrm << "\" />"; 
    +					ostrm << "\" />";
     				}
     				ostrm << "\n" ;
     			}
    @@ -320,7 +321,8 @@ class  KmlSrvImpl : public KmlServer {
     			if( ( 0 == strncmp( str, namStyles.c_str(), sz ) ) && ( str[sz] == '#' ) ) {
     				m_styleNam = str + sz + 1;
     			} else {
    -				LOG_INFO("Inconsistent URL style:%s",str );
    +				if (bMOREINFO)
    +					LOG_INFO("Inconsistent URL style:%s",str );
     				m_styleNam = str ;
     			}
     		}
    @@ -410,7 +412,8 @@ class  KmlSrvImpl : public KmlServer {
     
     			// There should be at least one event.
     			if( beEvt == enEvt ) {
    -				LOG_WARN("Inconsistency: No event kmlId=%s",m_kmlId.c_str() );
    +				if (bMOREINFO)
    +					LOG_WARN("Inconsistency: No event kmlId=%s",m_kmlId.c_str() );
     				return ;
     			}
     
    @@ -611,7 +614,8 @@ class  KmlSrvImpl : public KmlServer {
     			/// this key, and this iterator is forward_iterator only.
     			iterator it = find( refVL.first ), en = end() ;
     			if( it == en ) {
    -				// LOG_INFO("Cannot find '%s'", refVL.first.c_str() );
    +				if (bMOREINFO)
    +					LOG_INFO("Cannot find '%s'", refVL.first.c_str() );
     				it = insert( end(), refVL );
     				return;
     			}
    @@ -639,7 +643,8 @@ class  KmlSrvImpl : public KmlServer {
     				return ;
     			}
     
    -			// LOG_INFO("Inserted '%s' merge_dist=%lf", refVL.first.c_str(), dist );
    +			if (bMOREINFO)
    +				LOG_INFO("Inserted '%s' merge_dist=%lf", refVL.first.c_str(), dist );
     
     			/// The object is inserted at the end of all elements with the same key.
     			iterator ret = insert( next, refVL );
    @@ -677,7 +682,10 @@ class  KmlSrvImpl : public KmlServer {
     		/// Called by the subthread. It can merge data of placemarks with the same name
     		/// and different positions due to a move. This has to be very fast because under lock protection.
     		void FlushQueue(double merge_dist) {
    -			// LOG_INFO("FlushQueue nbelts %d sz=%d", m_queue_to_insert.size(), size() );
    +			if (bMOREINFO)
    +				LOG_INFO("FlushQueue nbelts %d sz=%d", 
    +					static_cast(m_queue_to_insert.size()),
    +					static_cast(size()) );
     
     			if( m_queue_to_insert.empty() ) return ;
     
    @@ -685,7 +693,8 @@ class  KmlSrvImpl : public KmlServer {
     			{
     				DirectInsert( *itPL, merge_dist );
     			}
    -			// LOG_INFO("Flushed into sz=%d", size() );
    +			if (bMOREINFO)
    +				LOG_INFO("Flushed into sz=%d", static_cast(size()) );
     
     			// TODO: If lock contention problems, we might swap this list with another one owned by this
     			// objet. This would later be merged into the container before saving data to disk.
    @@ -715,8 +724,10 @@ class  KmlSrvImpl : public KmlServer {
     			/// Cleanup all data older than this.
     			time_t limit_time = now - retention_delay * seconds_per_hour ;
     
    -			LOG_INFO("sz=%d retention=%d hours now=%s limit=%s",
    -				(int)size(), retention_delay, KmlTimestamp(now).c_str(), KmlTimestamp(limit_time).c_str() );
    +			if (bMOREINFO)
    +				LOG_INFO("sz=%d retention=%d hours now=%s limit=%s",
    +					(int)size(), retention_delay,
    +					KmlTimestamp(now).c_str(), KmlTimestamp(limit_time).c_str() );
     
     			size_t nbFullErased = 0 ;
     			size_t nbPartErased = 0 ;
    @@ -737,8 +748,9 @@ class  KmlSrvImpl : public KmlServer {
     
     			// Maybe the container only lost data because of data expiration, so it must be saved.
     			bool must_save_now = m_must_save || ( nbFullErased > 0 ) || ( nbPartErased > 0 ) ;
    -			LOG_INFO("Sz=%d FullyErased=%d PartialErased=%d m_must_save=%d must_save_now=%d",
    -					(int)size(), (int)nbFullErased, (int)nbPartErased, m_must_save, must_save_now );
    +			if (bMOREINFO)
    +				LOG_INFO("Sz=%d FullyErased=%d PartialErased=%d m_must_save=%d must_save_now=%d",
    +						(int)size(), (int)nbFullErased, (int)nbPartErased, m_must_save, must_save_now );
     			m_must_save = must_save_now ;
     		}
     
    @@ -758,7 +770,8 @@ class  KmlSrvImpl : public KmlServer {
     
     			/// For safety purpose, we do not empty the file. It might be an error.
     			if( empty() ) {
    -				LOG_INFO("Should empty KML file %s. Grace period.", kmlFilNam.c_str() );
    +				if (bMOREINFO)
    +					LOG_INFO("Should empty KML file %s. Grace period.", kmlFilNam.c_str() );
     				return false ;
     			}
     
    @@ -822,7 +835,9 @@ class  KmlSrvImpl : public KmlServer {
     
     			ar << KmlFooter ;
     
    -			LOG_INFO("Saved %s: %d placemarks to %s", category.c_str(), nbPlacemarks, kmlFilNam.c_str() );
    +			if (bMOREINFO)
    +				LOG_INFO("Saved %s: %d placemarks to %s",
    +						category.c_str(), nbPlacemarks, kmlFilNam.c_str() );
     			return true ;
     		} // KmlSrvImpl::PlacesMapT::RewriteKmlFileOneCategory
     
    @@ -855,7 +870,7 @@ class  KmlSrvImpl : public KmlServer {
     	/// This points to the specific KML file of the category.
     	void CategoryNetworkLink( std::ostream & strm, const std::string & category ) const
     	{
    -		strm << 
    +		strm <<
     			"\n"
     			"	" << category << "\n"
     			"	\n"
    @@ -880,17 +895,20 @@ class  KmlSrvImpl : public KmlServer {
     
     		/// If the file is there, leave as it is because it is maybe customize.
     		if( filDst ) {
    -			LOG_INFO("Style file %s not altered", namDst.c_str() );
    +			if (bMOREINFO)
    +				LOG_INFO("Style file %s not altered", namDst.c_str() );
     			goto close_and_quit ;
     		}
     		filDst = fopen( namDst.c_str(), "w" );
     		if( filDst == NULL ) {
    -			LOG_INFO("Cannot open destination style file %s", namDst.c_str() );
    +			if (bMOREINFO)
    +				LOG_INFO("Cannot open destination style file %s", namDst.c_str() );
     			goto close_and_quit ;
     		}
     		filSrc = fopen( namSrc.c_str(), "r" );
     		if( filSrc == NULL ) {
    -			LOG_INFO("Cannot open source style file %s", namSrc.c_str() );
    +			if (bMOREINFO)
    +				LOG_INFO("Cannot open source style file %s", namSrc.c_str() );
     			goto close_and_quit ;
     		}
     
    @@ -905,7 +923,8 @@ class  KmlSrvImpl : public KmlServer {
     				goto close_and_quit ;
     			}
         		}
    -		LOG_INFO("Style file %s copied to %s", namSrc.c_str(), namDst.c_str() );
    +		if (bMOREINFO)
    +			LOG_INFO("Style file %s copied to %s", namSrc.c_str(), namDst.c_str() );
     	close_and_quit:
     		if( filDst ) fclose(filDst);
     		if( filSrc ) fclose(filSrc);
    @@ -916,7 +935,8 @@ class  KmlSrvImpl : public KmlServer {
     		// This is the file, that the user must click on.
     		std::string baseFil = m_kml_dir + "fldigi.kml" ;
     
    -		LOG_INFO("Creating baseFil=%s", baseFil.c_str() );
    +		if (bMOREINFO)
    +			LOG_INFO("Creating baseFil=%s", baseFil.c_str() );
     
     		/// We do not need to make this file atomic because it is read once only.
     		AtomicRenamer ar( baseFil );
    @@ -947,7 +967,7 @@ class  KmlSrvImpl : public KmlServer {
     			"\n";
     		double dist = 0.0 ;
     		int nbStops = 0 ;
    -		// "135.2, 35.4, 0. 
    +		// "135.2, 35.4, 0.
     		for(;;) {
     			beg->second.WriteCooSub( ostrm );
     			ostrm << "\n";
    @@ -980,7 +1000,8 @@ class  KmlSrvImpl : public KmlServer {
     		: m_filnam( filnam )
     		, m_filtmp( filnam + ".tmp" )
     		{
    -			// LOG_INFO("AtomicRenamer opening tmp %s", filnam.c_str() );
    +			if (bMOREINFO)
    +				LOG_INFO("AtomicRenamer opening tmp %s", filnam.c_str() );
     			open( m_filtmp.c_str() );
     			if( bad() ) {
     				LOG_WARN("Cannot open %s", m_filtmp.c_str() );
    @@ -1069,7 +1090,8 @@ class  KmlSrvImpl : public KmlServer {
     	void ReloadSingleKmlFile( const std::string & category ) {
     		std::string kmlFilNam = CategFile( category );
     
    -		LOG_INFO("kmlFilNam=%s m_merge_dist=%lf", kmlFilNam.c_str(), m_merge_dist );
    +		if (bMOREINFO)
    +			LOG_INFO("kmlFilNam=%s m_merge_dist=%lf", kmlFilNam.c_str(), m_merge_dist );
     
     		PlacesMapT *ptrMap = m_placemarks.FindCategory( category );
     
    @@ -1124,19 +1146,19 @@ class  KmlSrvImpl : public KmlServer {
     				const char * msgTxt = xml->getNodeData();
     				LOG_DEBUG( "getNodeData=%s currState=%s", msgTxt, KmlRdToStr(currState) );
     				switch(currState) {
    -					case KMLRD_FOLDER_NAME : 
    +					case KMLRD_FOLDER_NAME :
     					       currFolderName = msgTxt ? msgTxt : "NullFolder";
     					       break;
    -					case KMLRD_FOLDER_PLACEMARK_POINT_COORDINATES : 
    +					case KMLRD_FOLDER_PLACEMARK_POINT_COORDINATES :
     					       currPM.SetCoordinates(msgTxt);
     					       break;
    -					case KMLRD_FOLDER_PLACEMARK_NAME : 
    +					case KMLRD_FOLDER_PLACEMARK_NAME :
     					       currPlcmrkName = msgTxt ? msgTxt : "NullPlacemarkName";
     					       break;
    -					case KMLRD_FOLDER_PLACEMARK_SNIPPET : 
    +					case KMLRD_FOLDER_PLACEMARK_SNIPPET :
     					       currPlacemarkDescr = msgTxt ? msgTxt : "NullSnippet";
     					       break;
    -					case KMLRD_FOLDER_PLACEMARK_STYLEURL : 
    +					case KMLRD_FOLDER_PLACEMARK_STYLEURL :
     					       currPM.SetStyle(msgTxt);
     					       break;
     					default:
    @@ -1148,7 +1170,8 @@ class  KmlSrvImpl : public KmlServer {
     				if( ! avoidNode.empty() ) break ;
     
     				const char *nodeName = xml->getNodeName();
    -				// LOG_INFO( "getNodeName=%s currState=%s", nodeName, KmlRdToStr(currState) );
    +				if (bMOREINFO)
    +					LOG_INFO( "getNodeName=%s currState=%s", nodeName, KmlRdToStr(currState) );
     				// TODO: Have a hashmap for each case.
     				switch(currState) {
     					case KMLRD_NONE :
    @@ -1160,12 +1183,13 @@ class  KmlSrvImpl : public KmlServer {
     								strcmp( "Document", nodeName ) &&
     								strcmp( "name", nodeName ) )
     							{
    +						if (bMOREINFO)
     							LOG_INFO("Unexpected %s in document %s. currState=%s",
    -								nodeName, category.c_str(), KmlRdToStr(currState) );
    +									nodeName, category.c_str(), KmlRdToStr(currState) );
     							}
     						}
     						break;
    -					case KMLRD_FOLDER : 
    +					case KMLRD_FOLDER :
     						if (!strcmp("name", nodeName)) {
     							currState = KMLRD_FOLDER_NAME ;
     						}
    @@ -1178,11 +1202,12 @@ class  KmlSrvImpl : public KmlServer {
     						else {
     							avoidNode = nodeName ;
     							currState = KMLRD_FOLDER_UNDEFINED ;
    -							LOG_INFO("Unexpected %s in folder %s. currState=%s",
    -								nodeName, currFolderName.c_str(), KmlRdToStr(currState) );
    +							if (bMOREINFO)
    +								LOG_INFO("Unexpected %s in folder %s. currState=%s",
    +									nodeName, currFolderName.c_str(), KmlRdToStr(currState) );
     						}
     						break;
    -					case KMLRD_FOLDER_PLACEMARK : 
    +					case KMLRD_FOLDER_PLACEMARK :
     						// There are different sorts of Placemark such as Point or LineString.
     						if (!strcmp("Point", nodeName)) {
     							currState = KMLRD_FOLDER_PLACEMARK_POINT ;
    @@ -1214,18 +1239,20 @@ class  KmlSrvImpl : public KmlServer {
     
     							// Other occurences of the same nodes will not be signaled.
     							if( pr.second ) {
    -								LOG_INFO("Unexpected %s in placemark id=%s name=%s. currState=%s",
    +								if (bMOREINFO)
    +									LOG_INFO("Unexpected %s in placemark id=%s name=%s. currState=%s",
     									nodeName, currPM.KmlId().c_str(),
     									currPlcmrkName.c_str(), KmlRdToStr(currState) );
     							}
     						}
     						break;
    -					case KMLRD_FOLDER_PLACEMARK_POINT : 
    +					case KMLRD_FOLDER_PLACEMARK_POINT :
     						if (!strcmp("coordinates", nodeName)) {
     							currState = KMLRD_FOLDER_PLACEMARK_POINT_COORDINATES ;
     						}
     						else {
    -							LOG_INFO("Unexpected %s in coordinates. currState=%s",
    +							if (bMOREINFO)
    +								LOG_INFO("Unexpected %s in coordinates. currState=%s",
     								nodeName, KmlRdToStr(currState) );
     						}
     						break;
    @@ -1235,7 +1262,10 @@ class  KmlSrvImpl : public KmlServer {
     							currTimestamp = KmlFromTimestamp( xml->getAttributeValue(FLDIGI_TIMESTAMP) );
     							currCustData.clear();
     						}
    -						else LOG_INFO("Unexpected %s in extended data. currState=%s", nodeName, KmlRdToStr(currState) );
    +						else
    +							if (bMOREINFO)
    +								LOG_INFO("Unexpected %s in extended data. currState=%s",
    +										nodeName, KmlRdToStr(currState) );
     						break;
     					case KMLRD_FOLDER_PLACEMARK_EXTENDEDDATA_FLDIGIEVENT:
     						// http://irrlicht.sourceforge.net/forum/viewtopic.php?t=10532
    @@ -1246,17 +1276,22 @@ class  KmlSrvImpl : public KmlServer {
     							assert( xml->isEmptyElement() );
     							const char * strKey = xml->getAttributeValue(FLDIGI_TAG_KEY);
     							if(strKey == NULL ) {
    -								LOG_INFO("Null item key");
    +								if (bMOREINFO)
    +									LOG_INFO("Null item key");
     								break ;
     							}
     							const char * strVal = xml->getAttributeValue(FLDIGI_TAG_VAL);
     							if(strVal == NULL ) {
    -								LOG_INFO("Null item value");
    +								if (bMOREINFO)
    +									LOG_INFO("Null item value");
     								break ;
     							}
     							currCustData.Push( strKey, strVal );
     						}
    -						else LOG_INFO("Unexpected %s in event. currState=%s", nodeName, KmlRdToStr(currState) );
    +						else
    +							if (bMOREINFO)
    +								LOG_INFO("Unexpected %s in event. currState=%s",
    +										nodeName, KmlRdToStr(currState) );
     						break;
     					default:
     						break;
    @@ -1267,19 +1302,23 @@ class  KmlSrvImpl : public KmlServer {
     				if( ! avoidNode.empty() ) {
     					const char * msgTxt = xml->getNodeData();
     					if( avoidNode == msgTxt ) {
    -						// LOG_INFO("Leaving forbidden element %s. currState=%s", avoidNode.c_str(), KmlRdToStr(currState) );
    +						if (bMOREINFO)
    +							LOG_INFO("Leaving forbidden element %s. currState=%s", avoidNode.c_str(), KmlRdToStr(currState) );
     						// We can leave the quarantine.
     						avoidNode.clear();
     					} else {
    -						// LOG_INFO("Still in forbidden element %s, leaving %s. currState=%s",
    -						// 		avoidNode.c_str(), msgTxt, KmlRdToStr(currState) );
    +						if (bMOREINFO)
    +							LOG_INFO("Still in forbidden element %s, leaving %s. currState=%s",
    +									avoidNode.c_str(), msgTxt, KmlRdToStr(currState) );
     						break ;
     					}
     				}
     
     				// We should check that this string matches wuth the state expects, but this is much
     				// faster to use only integers.
    -				// LOG_INFO("End of %s currState=%s", xml->getNodeData(), KmlRdToStr(currState) );
    +				if (bMOREINFO)
    +					LOG_INFO("End of %s currState=%s",
    +						xml->getNodeData(), KmlRdToStr(currState) );
     				switch(currState) {
     					case KMLRD_FOLDER :
     						currState = KMLRD_NONE ;
    @@ -1323,7 +1362,8 @@ class  KmlSrvImpl : public KmlServer {
     						LOG_ERROR("Should not happen %s", KmlRdToStr(currState));
     						break;
     					}
    -				// LOG_INFO("currState=%s", KmlRdToStr(currState) );
    +				if (bMOREINFO)
    +					LOG_INFO("currState=%s", KmlRdToStr(currState) );
     				break;
     			}
     			case EXN_NONE:
    @@ -1337,18 +1377,22 @@ class  KmlSrvImpl : public KmlServer {
     			}
     		}
     
    -		LOG_INFO("kmlFilNam=%s loaded sz=%d", kmlFilNam.c_str(), (int)ptrMap->size() );
    +		if (bMOREINFO)
    +			LOG_INFO("kmlFilNam=%s loaded sz=%d",
    +					kmlFilNam.c_str(), (int)ptrMap->size() );
     	} // KmlSrvImpl::ReloadSingleKmlFile
     
     	/// Rewrites only the categories which have changed.
     	bool RewriteKmlFileFull(void) {
     		bool wasSaved = false ;
    -		// LOG_INFO("nb_categories=%d", nb_categories );
    +		if (bMOREINFO)
    +			LOG_INFO("nb_categories=%d", static_cast(nb_categories) );
     		for( size_t i = 0; i < nb_categories; ++i ) {
     			const char * category = categories[i];
     			PlacesMapT *ptrMap = m_placemarks.FindCategory( category );
     			if( ptrMap == NULL ) {
    -				LOG_INFO("Category %s undefined", category );
    +				if (bMOREINFO)
    +					LOG_INFO("Category %s undefined", category );
     				continue;
     			}
     			ptrMap->PruneKmlFile( m_retention_delay );
    @@ -1403,7 +1447,7 @@ class  KmlSrvImpl : public KmlServer {
     				tmp_tim.tv_sec = time(NULL) + refresh_delay;
     				tmp_tim.tv_nsec = 0 ;
     
    -				// LOG_INFO("About to wait %d seconds", refresh );
    +				//LOG_INFO("About to wait %d seconds", refresh );
     				r = pthread_cond_timedwait( &m_cond_queue, &m_mutex_write, &tmp_tim );
     				if( ( r != ETIMEDOUT ) && ( r != 0 ) ) {
     					LOG_ERROR("pthread_cond_timedwait %s d=%d", strerror(errno), m_refresh_interval );
    @@ -1417,7 +1461,8 @@ class  KmlSrvImpl : public KmlServer {
     				MilliSleep( 1000 );
     				if( m_kml_must_leave )
     				{
    -					LOG_INFO("Exit flag detected. Leaving");
    +					if (bMOREINFO)
    +						LOG_INFO("Exit flag detected. Leaving");
     					return (void *)"Exit flag detected";
     				}
     			}
    @@ -1436,7 +1481,8 @@ class  KmlSrvImpl : public KmlServer {
     						return (void *)error_message ;
     					}
     					--nb_retries ;
    -					LOG_INFO("KML server not ready yet. Cnt=%d. Restarting.",nb_retries);
    +					if (bMOREINFO)
    +						LOG_INFO("KML server not ready yet. Cnt=%d. Restarting.",nb_retries);
     					MilliSleep(1000); // Give time to load data.
     					continue ;
     				}
    @@ -1446,18 +1492,20 @@ class  KmlSrvImpl : public KmlServer {
     				{
     					PlacesMapT *ptrMap = m_placemarks.FindCategory( categories[i] );
     					if( ptrMap == NULL ) {
    -						LOG_INFO("Category %s undefined", categories[i] );
    +						if (bMOREINFO)
    +							LOG_INFO("Category %s undefined", categories[i] );
     						continue;
     					}
     					// TODO: If there are contention problems, internally swap the queue
     					// with a fresh empty one.
     					ptrMap->FlushQueue( m_merge_dist );
     				}
    -				// LOG_INFO("Releasing lock" );
    +				if (bMOREINFO)
    +					LOG_INFO("Releasing lock" );
     			}
     			if( r == ETIMEDOUT )
     			{
    -				// LOG_INFO("Saving after wait=%d", refresh );
    +				//LOG_INFO("Saving after wait=%d", refresh );
     				bool wasSaved = RewriteKmlFileFull();
     
     				// Maybe a user process must be created to process these KML files.
    @@ -1471,7 +1519,7 @@ class  KmlSrvImpl : public KmlServer {
     			} else {
     				refresh_delay = tmp_tim.tv_sec - time(NULL);
     				if( refresh_delay <= 0 ) refresh_delay = 1 ;
    -				// LOG_INFO("Interrupted when waiting. Restart with wait=%d", refresh );
    +				//LOG_INFO("Interrupted when waiting. Restart with wait=%d", refresh );
     #endif
     			}
     		} // Endless loop.
    @@ -1512,8 +1560,10 @@ public:
     		m_refresh_interval = kml_refresh_interval ;
     		m_balloon_style = kml_balloon_style ;
     
    -		LOG_INFO("dir=%s merge_distance=%lf retention_delay=%d refresh_interval=%d balloon_style=%d",
    -			kml_dir.c_str(), kml_merge_distance, kml_retention_delay, kml_refresh_interval, kml_balloon_style );
    +		if (bMOREINFO)
    +			LOG_INFO("dir=%s merge_distance=%lf retention_delay=%d refresh_interval=%d balloon_style=%d",
    +				kml_dir.c_str(), kml_merge_distance,
    +				kml_retention_delay, kml_refresh_interval, kml_balloon_style );
     
     		m_kml_dir = kml_dir ;
     
    @@ -1544,14 +1594,14 @@ public:
     			try {
     				ReloadSingleKmlFile( categories[i] );
     			} catch( const std::exception & exc ) {
    -				LOG_INFO("Category %s. Caught %s", categories[i], exc.what() );
    +				LOG_ERROR("Category %s. Caught %s", categories[i], exc.what() );
     			}
     		}
     
     		// Now the object is usable. Theoretically should be protected by a mutex.
     		LOG_DEBUG("Object ready");
     
    -		/// Even if an exception was thrown when loading the previous file, it does not 
    +		/// Even if an exception was thrown when loading the previous file, it does not
     		/// prevent to overwrite the old files with new and clean ones.
     		m_loaded = true ;
     	}
    @@ -1618,32 +1668,38 @@ public:
     #else
     		m_bool_queue = true;
     #endif
    -		LOG_INFO("'%s' sz=%d time=%s nb_broad=%d m_merge_dist=%lf",
    -			descrTxt.c_str(), (int)ptrMap->size(),
    -			KmlTimestamp(evtTim).c_str(),
    -			KmlServer::m_nb_broadcasts,m_merge_dist );
    +		if (bMOREINFO)
    +			LOG_INFO("'%s' sz=%d time=%s nb_broad=%d m_merge_dist=%lf",
    +				descrTxt.c_str(), (int)ptrMap->size(),
    +				KmlTimestamp(evtTim).c_str(),
    +				KmlServer::m_nb_broadcasts,m_merge_dist );
     	}
     
     	/// It flushes the content to disk.
     	~KmlSrvImpl() {
     		{
     			/// This will not be killed in the middle of the writing.
    -			LOG_INFO("Cancelling writer thread");
    +			if (bMOREINFO)
    +				LOG_INFO("Cancelling writer thread");
     			guard_lock myGuard( &m_mutex_write );
     
     #ifdef FLDIGI_KML_CONDITION_VARIABLE
    -			LOG_INFO("Cancelling subthread");
    +			if (bMOREINFO)
    +				LOG_INFO("Cancelling subthread");
     			int r = pthread_cancel( m_writer_thread );
     			if( r ) {
    -				LOG_ERROR("pthread_cancel %s", strerror(errno) );
    +				if (bMOREINFO)
    +					LOG_ERROR("pthread_cancel %s", strerror(errno) );
     				return ;
     			}
     #else
    -			LOG_INFO("Setting exit flag.");
    +			if (bMOREINFO)
    +				LOG_INFO("Setting exit flag.");
     			m_kml_must_leave = true ;
     #endif
     		}
    -		// LOG_INFO("Joining subthread");
    +		if (bMOREINFO)
    +			LOG_INFO("Joining subthread");
     		void * retPtr;
     		int r = pthread_join( m_writer_thread, &retPtr );
     		if( r ) {
    @@ -1656,7 +1712,8 @@ public:
     				: (retPtr == PTHREAD_CANCELED)
     					? "Canceled thread"
     					: static_cast(retPtr);
    -		LOG_INFO("Thread stopped. Message:%s", msg );
    +		if (bMOREINFO)
    +			LOG_INFO("Thread stopped. Message:%s", msg );
     
     		/// Here we are sure that the subthread is stopped. The subprocess is not called.
     		RewriteKmlFileFull();
    @@ -1687,7 +1744,9 @@ public:
     		if( is_proc_still_running == -1 ) return ;
     		if( ( m_pid_command <= 0 ) || ( is_proc_still_running == 0 ) ) {
     			m_pid_command = fork_process( m_command.c_str() );
    -			LOG_INFO("%s: Pid=%d Command=%s", __FUNCTION__, m_pid_command, m_command.c_str() );
    +			if (bMOREINFO)
    +				LOG_INFO("%s: Pid=%d Command=%s",
    +						__FUNCTION__, m_pid_command, m_command.c_str() );
     		}
     	}
     
    @@ -1741,7 +1800,8 @@ void KmlServer::SpawnProcess() {
     /// Called by thr main program, clean exit.
     void KmlServer::Exit(void) {
     	// We assume that the calling program has no try/catch handler.
    -	// LOG_INFO("Exiting");
    +	if (bMOREINFO)
    +		LOG_INFO("Exiting");
     	try {
     		KmlServer * pKml = Pointer();
     		if( pKml ) {
    diff --git a/src/misc/log.cxx b/src/misc/log.cxx
    index 205dd1b5..3e7087de 100644
    --- a/src/misc/log.cxx
    +++ b/src/misc/log.cxx
    @@ -40,6 +40,8 @@
     #include "fl_digi.h"
     #include "timeops.h"
     
    +#include "ascii.h"
    +
     using namespace std;
     
     static const char *lognames[] = { "RX", "TX", "", "" };
    @@ -84,7 +86,8 @@ void cLogfile::log_to_file(log_t type, const string& s)
     			fprintf(logfile, "%s %s : %s (%s): ", lognames[type], freq, logmode, timestr);
     		}
     		for (size_t i = 0; i < s.length(); i++)
    -			if (s[i] == '\n' || (unsigned char)s[i] >= ' ') fprintf(logfile, "%c", s[i]);
    +			fprintf(logfile, "%s", ascii3[s[i] & 0xFF]);
    +//			if (s[i] == '\n' || (unsigned char)s[i] >= ' ') fprintf(logfile, "%c", s[i]);
     		retflag = *s.rbegin() == '\n';
     		if (!retflag)
     			fflush(logfile);
    diff --git a/src/misc/macroedit.cxx b/src/misc/macroedit.cxx
    index a03f6cea..07bb9792 100644
    --- a/src/misc/macroedit.cxx
    +++ b/src/misc/macroedit.cxx
    @@ -150,6 +150,8 @@ void loadBrowser(Fl_Widget *widget) {
     	w->add(_("\tincr/decr xcvr freq"));
     	w->add(_("\tvalid xcvr mode"));
     	w->add(_("\tvalid xcvr filter width"));
    +	w->add(_("\tvalid xcvr low cutoff filter"));
    +	w->add(_("\tvalid xcvr hi cutoff filter"));
     	w->add(_("\trig freq has kbd focus"));
     
     	w->add(LINE_SEP);
    @@ -164,7 +166,7 @@ void loadBrowser(Fl_Widget *widget) {
     	w->add(_("\tidle signal for NN.nn sec"));
     	w->add(_("\trepeat every NN sec"));
     	w->add(_("\ttune signal for NN sec"));
    -	w->add(_("\tdelay xmt for NN sec"));
    +	w->add(_("\tdelay xmt for NN.n sec"));
     	w->add(_("\trepeat macro continuously"));
     	w->add(_("\tschedule execution"));
     
    @@ -216,6 +218,7 @@ void loadBrowser(Fl_Widget *widget) {
     
     	w->add(LINE_SEP);
     	w->add(_("\tAnalysis CSV on,off,toggle"));
    +
     	w->add(LINE_SEP);
     	assert(MODE_CONTESTIA < MODE_OLIVIA);
     	char s[256];
    @@ -307,9 +310,9 @@ void update_macro_button(int iMacro, const char *text, const char *name)
     
     	if (progdefaults.mbar_scheme > MACRO_SINGLE_BAR_MAX) {
     		if (iMacro < NUMMACKEYS) {
    -			btnMacro[iMacro % NUMMACKEYS]->label( macros.name[iMacro].c_str() );
    -			btnMacro[iMacro % NUMMACKEYS]->redraw_label();
    -		} else {
    +			btnMacro[iMacro]->label( macros.name[iMacro].c_str() );
    +			btnMacro[iMacro]->redraw_label();
    +		} else if ((iMacro / NUMMACKEYS) == altMacros) {
     			btnMacro[(iMacro % NUMMACKEYS) + NUMMACKEYS]->label( macros.name[iMacro].c_str() );
     			btnMacro[(iMacro % NUMMACKEYS) + NUMMACKEYS]->redraw_label();
     		}
    @@ -317,7 +320,10 @@ void update_macro_button(int iMacro, const char *text, const char *name)
     		btnMacro[iMacro % NUMMACKEYS]->label( macros.name[iMacro].c_str() );
     		btnMacro[iMacro % NUMMACKEYS]->redraw_label();
     	}
    -
    +	if (progdefaults.dockable_macros) {
    +		btnDockMacro[iMacro]->label(macros.name[iMacro].c_str());
    +		btnDockMacro[iMacro]->redraw_label();
    +	}
     	macros.changed = true;
     }
     
    @@ -338,7 +344,7 @@ void cbInsertMacro(Fl_Widget *, void *)
     			_("Text file to insert"),
     			filters.c_str(),
     			HomeDir.c_str());
    -		if (p) {
    +		if (p && *p) {
     			text.insert(6, p);
     		} else
     			text = "";
    @@ -348,7 +354,7 @@ void cbInsertMacro(Fl_Widget *, void *)
     			_("Test text file"),
     			filters.c_str(),
     			HomeDir.c_str());
    -		if (p) {
    +		if (p && *p) {
     			text.insert(10, p);
     		} else
     			text = "";
    @@ -358,7 +364,7 @@ void cbInsertMacro(Fl_Widget *, void *)
     			_("MFSK image file"),
     			filters.c_str(),
     			PicsDir.c_str());
    -		if (p) {
    +		if (p && *p) {
     			text.insert(7, p);
     		} else
     			text = "";
    @@ -368,7 +374,7 @@ void cbInsertMacro(Fl_Widget *, void *)
     			_("Change to Macro file"),
     			filters.c_str(),
     			MacrosDir.c_str());
    -		if (p) {
    +		if (p && *p) {
     			text.insert(8, p);
     		} else
     			text = "";
    @@ -380,7 +386,7 @@ void cbInsertMacro(Fl_Widget *, void *)
     			_("Executable file to insert"),
     			filters.c_str(),
     			HomeDir.c_str());
    -		if (p) {
    +		if (p && *p) {
     			string exefile = p;
     			exefile.append("");
     			text.insert(6, exefile);
    diff --git a/src/misc/macros.cxx b/src/misc/macros.cxx
    index 23c3a24d..538e70de 100644
    --- a/src/misc/macros.cxx
    +++ b/src/misc/macros.cxx
    @@ -106,6 +106,7 @@ std::string text2repeat = "";
     size_t repeatchar = 0;
     
     bool macro_idle_on = false;
    +bool macro_rx_wait = false;
     
     static float  idleTime = 0;
     static bool TransmitON = false;
    @@ -122,9 +123,14 @@ static bool GET = false;
     static bool timed_exec = false;
     static bool within_exec = false;
     
    +void rx_que_continue(void *);
    +
     static void postQueue(std::string s)
     {
    -	ReceiveText->addstr(s, FTextBase::CTRL);
    +	if (active_modem->get_mode() == MODE_IFKP)
    +		ifkp_rx_text->addstr(s, FTextBase::CTRL);
    +	else
    +		ReceiveText->addstr(s, FTextBase::CTRL);
     }
     
     static const char cutnumbers[] = "T12345678N";
    @@ -225,18 +231,24 @@ chars/sec:    %f",
     			num_cps_chars / (xmttime - overhead));
     	LOG_INFO("%s", results);
     	strcat(results, "\n");
    -	ReceiveText->add(results, FTextBase::ALTR);
    +	if (active_modem->get_mode() == MODE_IFKP)
    +		ifkp_rx_text->add(results, FTextBase::ALTR);
    +	else
    +		ReceiveText->add(results, FTextBase::ALTR);
     	PERFORM_CPS_TEST = false;
     }
     
     static void pCPS_TEST(std::string &s, size_t &i, size_t endbracket)
     {
     	trx_mode id = active_modem->get_mode();
    -	if ( id == MODE_SSB || id == MODE_WWV || 
    +	if ( id == MODE_SSB || id == MODE_WWV ||
     		id == MODE_ANALYSIS || id == MODE_FFTSCAN ||
     		id == MODE_WEFAX_576 || id == MODE_WEFAX_288 ||
     		id == MODE_SITORB || id == MODE_NAVTEX ) {
    -		ReceiveText->add("Mode not supported\n", FTextBase::ALTR);
    +		if (active_modem->get_mode() == MODE_IFKP)
    +			ifkp_tx_text->add("Mode not supported\n", FTextBase::ALTR);
    +		else
    +			ReceiveText->add("Mode not supported\n", FTextBase::ALTR);
     		s.clear();
     		return;
     	}
    @@ -250,7 +262,7 @@ static void pCPS_TEST(std::string &s, size_t &i, size_t endbracket)
     	if (n <= 0) n = 10;
     	if (n > 100) n = 100;
     
    -// sample count with 'n' characters 
    +// sample count with 'n' characters
     	int s1[256];
     	for (int i = 0; i < 256; i++) s1[i] = 0;
     // converstion from sample count to milliseconds
    @@ -285,7 +297,10 @@ static void pCPS_TEST(std::string &s, size_t &i, size_t endbracket)
     	}
     	if (!line_out.empty()) {
     		LOG_INFO("%s", line_out.c_str());
    -		ReceiveText->add(line_out.c_str(), FTextBase::ALTR);
    +		if (active_modem->get_mode() == MODE_IFKP)
    +			ifkp_rx_text->add(line_out.c_str(), FTextBase::ALTR);
    +		else
    +			ReceiveText->add(line_out.c_str(), FTextBase::ALTR);
     	}
     	return;
     }
    @@ -293,11 +308,14 @@ static void pCPS_TEST(std::string &s, size_t &i, size_t endbracket)
     static void pCPS_FILE(std::string &s, size_t &i, size_t endbracket)
     {
     	trx_mode id = active_modem->get_mode();
    -	if ( id == MODE_SSB || id == MODE_WWV || 
    +	if ( id == MODE_SSB || id == MODE_WWV ||
     		id == MODE_ANALYSIS || id == MODE_FFTSCAN ||
     		id == MODE_WEFAX_576 || id == MODE_WEFAX_288 ||
     		id == MODE_SITORB || id == MODE_NAVTEX ) {
    -		ReceiveText->add("Mode not supported\n", FTextBase::ALTR);
    +		if (active_modem->get_mode() == MODE_IFKP)
    +			ifkp_rx_text->add("Mode not supported\n", FTextBase::ALTR);
    +		else
    +			ReceiveText->add("Mode not supported\n", FTextBase::ALTR);
     		s.clear();
     		return;
     	}
    @@ -314,7 +332,10 @@ static void pCPS_FILE(std::string &s, size_t &i, size_t endbracket)
     			}
     			s.clear();
     			fclose(toadd);
    -			TransmitText->clear();
    +			if (active_modem->get_mode() == MODE_IFKP)
    +				ifkp_tx_text->clear();
    +			else
    +				TransmitText->clear();
     			testfilename = fname;
     
     			stopMacroTimer();
    @@ -331,7 +352,10 @@ static void pCPS_FILE(std::string &s, size_t &i, size_t endbracket)
     		} else {
     			string resp = "Could not locate ";
     			resp.append(fname).append("\n");
    -			ReceiveText->add(resp.c_str(), FTextBase::ALTR);
    +			if (active_modem->get_mode() == MODE_IFKP)
    +				ifkp_rx_text->add(resp.c_str(), FTextBase::ALTR);
    +			else
    +				ReceiveText->add(resp.c_str(), FTextBase::ALTR);
     			LOG_WARN("%s not found", fname.c_str());
     			s.replace(i, endbracket - i + 1, "");
     			PERFORM_CPS_TEST = false;
    @@ -345,11 +369,14 @@ static void pCPS_FILE(std::string &s, size_t &i, size_t endbracket)
     static void pCPS_STRING(std::string &s, size_t &i, size_t endbracket)
     {
     	trx_mode id = active_modem->get_mode();
    -	if ( id == MODE_SSB || id == MODE_WWV || 
    +	if ( id == MODE_SSB || id == MODE_WWV ||
     		id == MODE_ANALYSIS || id == MODE_FFTSCAN ||
     		id == MODE_WEFAX_576 || id == MODE_WEFAX_288 ||
     		id == MODE_SITORB || id == MODE_NAVTEX ) {
    -		ReceiveText->add("Mode not supported\n", FTextBase::ALTR);
    +		if (active_modem->get_mode() == MODE_IFKP)
    +			ifkp_rx_text->add("Mode not supported\n", FTextBase::ALTR);
    +		else
    +			ReceiveText->add("Mode not supported\n", FTextBase::ALTR);
     		s.clear();
     		return;
     	}
    @@ -363,7 +390,10 @@ static void pCPS_STRING(std::string &s, size_t &i, size_t endbracket)
     		p = buffer.find("\\n");
     	}
     	if (buffer.length()) {
    -		TransmitText->clear();
    +		if (active_modem->get_mode() == MODE_IFKP)
    +			ifkp_tx_text->clear();
    +		else
    +			TransmitText->clear();
     
     		stopMacroTimer();
     		active_modem->set_stopflag(false);
    @@ -380,7 +410,10 @@ static void pCPS_STRING(std::string &s, size_t &i, size_t endbracket)
     		string resp = "Text not specified";
     		LOG_WARN("%s", resp.c_str());
     		resp.append("\n");
    -		ReceiveText->add(resp.c_str(), FTextBase::ALTR);
    +		if (active_modem->get_mode() == MODE_IFKP)
    +			ifkp_rx_text->add(resp.c_str(), FTextBase::ALTR);
    +		else
    +			ReceiveText->add(resp.c_str(), FTextBase::ALTR);
     		PERFORM_CPS_TEST = false;
     	}
     }
    @@ -388,11 +421,14 @@ static void pCPS_STRING(std::string &s, size_t &i, size_t endbracket)
     static void pCPS_N(std::string &s, size_t &i, size_t endbracket)
     {
     	trx_mode id = active_modem->get_mode();
    -	if ( id == MODE_SSB || id == MODE_WWV || 
    +	if ( id == MODE_SSB || id == MODE_WWV ||
     		id == MODE_ANALYSIS || id == MODE_FFTSCAN ||
     		id == MODE_WEFAX_576 || id == MODE_WEFAX_288 ||
     		id == MODE_SITORB || id == MODE_NAVTEX ) {
    -		ReceiveText->add("Mode not supported\n", FTextBase::ALTR);
    +		if (active_modem->get_mode() == MODE_IFKP)
    +			ifkp_rx_text->add("Mode not supported\n", FTextBase::ALTR);
    +		else
    +			ReceiveText->add("Mode not supported\n", FTextBase::ALTR);
     		s.clear();
     		return;
     	}
    @@ -418,7 +454,10 @@ static void pCPS_N(std::string &s, size_t &i, size_t endbracket)
     		else buffer += ' ';
     	}
     
    -	TransmitText->clear();
    +	if (active_modem->get_mode() == MODE_IFKP)
    +		ifkp_tx_text->clear();
    +	else
    +		TransmitText->clear();
     
     	stopMacroTimer();
     	active_modem->set_stopflag(false);
    @@ -438,11 +477,14 @@ static void pWAV_TEST(std::string &s, size_t &i, size_t endbracket)
     {
     	s.clear();
     	trx_mode id = active_modem->get_mode();
    -	if ( id == MODE_SSB || id == MODE_WWV || 
    +	if ( id == MODE_SSB || id == MODE_WWV ||
     		id == MODE_ANALYSIS || id == MODE_FFTSCAN ||
     		id == MODE_WEFAX_576 || id == MODE_WEFAX_288 ||
     		id == MODE_SITORB || id == MODE_NAVTEX ) {
    -		ReceiveText->add("Mode not supported\n", FTextBase::ALTR);
    +		if (active_modem->get_mode() == MODE_IFKP)
    +			ifkp_rx_text->add("Mode not supported\n", FTextBase::ALTR);
    +		else
    +			ReceiveText->add("Mode not supported\n", FTextBase::ALTR);
     		return;
     	}
     	testfilename = "internal string";
    @@ -459,11 +501,14 @@ static void pWAV_TEST(std::string &s, size_t &i, size_t endbracket)
     static void pWAV_N(std::string &s, size_t &i, size_t endbracket)
     {
     	trx_mode id = active_modem->get_mode();
    -	if ( id == MODE_SSB || id == MODE_WWV || 
    +	if ( id == MODE_SSB || id == MODE_WWV ||
     		id == MODE_ANALYSIS || id == MODE_FFTSCAN ||
     		id == MODE_WEFAX_576 || id == MODE_WEFAX_288 ||
     		id == MODE_SITORB || id == MODE_NAVTEX ) {
    -		ReceiveText->add("Mode not supported\n", FTextBase::ALTR);
    +		if (active_modem->get_mode() == MODE_IFKP)
    +			ifkp_rx_text->add("Mode not supported\n", FTextBase::ALTR);
    +		else
    +			ReceiveText->add("Mode not supported\n", FTextBase::ALTR);
     		s.clear();
     		return;
     	}
    @@ -489,7 +534,10 @@ static void pWAV_N(std::string &s, size_t &i, size_t endbracket)
     		else buffer += ' ';
     	}
     
    -	TransmitText->clear();
    +	if (active_modem->get_mode() == MODE_IFKP)
    +		ifkp_tx_text->clear();
    +	else
    +		TransmitText->clear();
     
     	stopMacroTimer();
     	active_modem->set_stopflag(false);
    @@ -504,11 +552,14 @@ static void pWAV_N(std::string &s, size_t &i, size_t endbracket)
     static void pWAV_FILE(std::string &s, size_t &i, size_t endbracket)
     {
     	trx_mode id = active_modem->get_mode();
    -	if ( id == MODE_SSB || id == MODE_WWV || 
    +	if ( id == MODE_SSB || id == MODE_WWV ||
     		id == MODE_ANALYSIS || id == MODE_FFTSCAN ||
     		id == MODE_WEFAX_576 || id == MODE_WEFAX_288 ||
     		id == MODE_SITORB || id == MODE_NAVTEX ) {
    -		ReceiveText->add("Mode not supported\n", FTextBase::ALTR);
    +		if (active_modem->get_mode() == MODE_IFKP)
    +			ifkp_rx_text->add("Mode not supported\n", FTextBase::ALTR);
    +		else
    +			ReceiveText->add("Mode not supported\n", FTextBase::ALTR);
     		s.clear();
     		return;
     	}
    @@ -525,7 +576,10 @@ static void pWAV_FILE(std::string &s, size_t &i, size_t endbracket)
     			}
     			s.clear();
     			fclose(toadd);
    -			TransmitText->clear();
    +			if (active_modem->get_mode() == MODE_IFKP)
    +				ifkp_tx_text->clear();
    +			else
    +				TransmitText->clear();
     			testfilename = fname;
     
     			stopMacroTimer();
    @@ -539,7 +593,10 @@ static void pWAV_FILE(std::string &s, size_t &i, size_t endbracket)
     		} else {
     			string resp = "Could not locate ";
     			resp.append(fname).append("\n");
    -			ReceiveText->add(resp.c_str(), FTextBase::ALTR);
    +			if (active_modem->get_mode() == MODE_IFKP)
    +				ifkp_rx_text->add(resp.c_str(), FTextBase::ALTR);
    +			else
    +				ReceiveText->add(resp.c_str(), FTextBase::ALTR);
     			LOG_WARN("%s not found", fname.c_str());
     			s.replace(i, endbracket - i + 1, "");
     			PERFORM_CPS_TEST = false;
    @@ -553,11 +610,14 @@ static void pWAV_FILE(std::string &s, size_t &i, size_t endbracket)
     static void pWAV_STRING(std::string &s, size_t &i, size_t endbracket)
     {
     	trx_mode id = active_modem->get_mode();
    -	if ( id == MODE_SSB || id == MODE_WWV || 
    +	if ( id == MODE_SSB || id == MODE_WWV ||
     		id == MODE_ANALYSIS || id == MODE_FFTSCAN ||
     		id == MODE_WEFAX_576 || id == MODE_WEFAX_288 ||
     		id == MODE_SITORB || id == MODE_NAVTEX ) {
    -		ReceiveText->add("Mode not supported\n", FTextBase::ALTR);
    +		if (active_modem->get_mode() == MODE_IFKP)
    +			ifkp_rx_text->add("Mode not supported\n", FTextBase::ALTR);
    +		else
    +			ReceiveText->add("Mode not supported\n", FTextBase::ALTR);
     		s.clear();
     		return;
     	}
    @@ -571,7 +631,10 @@ static void pWAV_STRING(std::string &s, size_t &i, size_t endbracket)
     		p = buffer.find("\\n");
     	}
     	if (buffer.length()) {
    -		TransmitText->clear();
    +		if (active_modem->get_mode() == MODE_IFKP)
    +			ifkp_tx_text->clear();
    +		else
    +			TransmitText->clear();
     
     		stopMacroTimer();
     		active_modem->set_stopflag(false);
    @@ -585,7 +648,10 @@ static void pWAV_STRING(std::string &s, size_t &i, size_t endbracket)
     		string resp = "Text not specified";
     		LOG_WARN("%s", resp.c_str());
     		resp.append("\n");
    -		ReceiveText->add(resp.c_str(), FTextBase::ALTR);
    +		if (active_modem->get_mode() == MODE_IFKP)
    +			ifkp_rx_text->add(resp.c_str(), FTextBase::ALTR);
    +		else
    +			ReceiveText->add(resp.c_str(), FTextBase::ALTR);
     		PERFORM_CPS_TEST = false;
     	}
     }
    @@ -986,7 +1052,7 @@ static void pTxQueIDLE(std::string &s, size_t &i, size_t endbracket)
     }
     
     static bool useTune = false;
    -static int  tuneTime = 0;
    +static float  tuneTime = 0;
     
     static void pTUNE(std::string &s, size_t &i, size_t endbracket)
     {
    @@ -1042,7 +1108,7 @@ static void pNRSID(std::string &s, size_t &i, size_t endbracket)
     }
     
     static bool useWait = false;
    -static int  waitTime = 0;
    +static float  waitTime = 0;
     
     static void pWAIT(std::string &s, size_t &i, size_t endbracket)
     {
    @@ -1050,10 +1116,10 @@ static void pWAIT(std::string &s, size_t &i, size_t endbracket)
     		s.replace(i, endbracket - i + 1, "");
     		return;
     	}
    -	int number;
    +	float number;
     	std::string sTime = s.substr(i+6, endbracket - i - 6);
     	if (sTime.length() > 0) {
    -		sscanf(sTime.c_str(), "%d", &number);
    +		sscanf(sTime.c_str(), "%f", &number);
     		useWait = true;
     		waitTime = number;
     	}
    @@ -1069,12 +1135,12 @@ static void doneWAIT(void *)
     
     static void doWAIT(std::string s)
     {
    -	int number;
    +	float number;
     	std::string sTime = s.substr(7, s.length() - 8);
     	if (sTime.length() > 0) {
    -		sscanf(sTime.c_str(), "%d", &number);
    +		sscanf(sTime.c_str(), "%f", &number);
     		Qwait_time = number;
    -		Fl::add_timeout (number * 1.0, doneWAIT);
    +		Fl::add_timeout (number, doneWAIT);
     	} else
     		Qwait_time = 0;
     }
    @@ -1090,6 +1156,27 @@ static void pTxQueWAIT(std::string &s, size_t &i, size_t endbracket)
     	s.replace(i, endbracket - i + 1, "^!");
     }
     
    +static void doRxWAIT(std::string s)
    +{
    +	float number = 0;
    +	std::string sTime = s.substr(7, s.length() - 8);
    +	if (sTime.length() > 0) {
    +		sscanf(sTime.c_str(), "%f", &number);
    +		macro_rx_wait = true;
    +		Fl::add_timeout(number, rx_que_continue);
    +	}
    +}
    +
    +static void pRxQueWAIT(std::string &s, size_t &i, size_t endbracket)
    +{
    +	if (within_exec) {
    +		s.replace(i, endbracket - i + 1, "");
    +		return;
    +	}
    +	struct CMDS cmd = { s.substr(i, endbracket - i + 1), doRxWAIT };
    +	push_rxcmd(cmd);
    +	s.replace(i, endbracket - i + 1, "");
    +}
     
     static void pINFO1(std::string &s, size_t &i, size_t endbracket)
     {
    @@ -1108,7 +1195,14 @@ static void pCLRRX(std::string &s, size_t &i, size_t endbracket)
     		return;
     	}
     	s.replace( i, 7, "" );
    -	ReceiveText->clear();
    +	trx_mode md = active_modem->get_mode();
    +
    +	if (md == MODE_IFKP)
    +		ifkp_rx_text->clear();
    +	else if ((md >= MODE_FELDHELL) && (md <= MODE_HELL80))
    +		FHdisp->clear();
    +	else
    +		ReceiveText->clear();
     }
     
     static void pCLRTX(std::string &s, size_t &i, size_t endbracket)
    @@ -1119,7 +1213,10 @@ static void pCLRTX(std::string &s, size_t &i, size_t endbracket)
     	}
     	s.replace( i, 7, "" );
     	queue_reset();
    -	TransmitText->clear();
    +	if (active_modem->get_mode() == MODE_IFKP)
    +		ifkp_tx_text->clear();
    +	else
    +		TransmitText->clear();
     }
     
     static void pFOCUS(std::string &s, size_t &i, size_t endbracket)
    @@ -1127,7 +1224,10 @@ static void pFOCUS(std::string &s, size_t &i, size_t endbracket)
     	if (!within_exec) {
     		if (qsoFreqDisp->is_reversed_colors()) {
     			qsoFreqDisp->restore_colors();
    -			TransmitText->take_focus();
    +			if (active_modem->get_mode() == MODE_IFKP)
    +				ifkp_tx_text->take_focus();
    +			else
    +				TransmitText->take_focus();
     		} else {
     			qsoFreqDisp->take_focus();
     			qsoFreqDisp->reverse_colors();
    @@ -1161,7 +1261,10 @@ static void pQSYPLUS(std::string &s, size_t &i, size_t endbracket)
     
     static void pCALL(std::string &s, size_t &i, size_t endbracket)
     {
    -	s.replace( i, 6, inpCall->value() );
    +	string call = inpCall->value();
    +	if (active_modem->get_mode() == MODE_IFKP && progdefaults.ifkp_lowercase_call)
    +		for (size_t n = 0; n < call.length(); n++) call[n] = tolower(call[n]);
    +	s.replace( i, 6, call );
     }
     
     static void pGET(std::string &s, size_t &i, size_t endbracket)
    @@ -1176,7 +1279,7 @@ static void pFREQ(std::string &s, size_t &i, size_t endbracket)
     }
     
     static void pBAND(std::string &s, size_t &i, size_t endbracket)
    -{ 
    +{
             s.replace( i, 6, band_name( band( wf->rfcarrier() ) ) );
     }
     
    @@ -1213,7 +1316,10 @@ static void pRST(std::string &s, size_t &i, size_t endbracket)
     
     static void pMYCALL(std::string &s, size_t &i, size_t endbracket)
     {
    -	s.replace( i, 8, inpMyCallsign->value() );
    +	string call = inpMyCallsign->value();
    +	if (active_modem->get_mode() == MODE_IFKP && progdefaults.ifkp_lowercase)
    +		for (size_t n = 0; n < call.length(); n++) call[n] = tolower(call[n]);
    +	s.replace( i, 8, call );
     }
     
     static void pMYLOC(std::string &s, size_t &i, size_t endbracket)
    @@ -1237,8 +1343,8 @@ static void pMYRST(std::string &s, size_t &i, size_t endbracket)
     }
     
     static void pANTENNA(std::string &s, size_t &i, size_t endbracket)
    -{ 
    -        s.replace( i, 9, progdefaults.myAntenna.c_str() );  
    +{
    +        s.replace( i, 9, progdefaults.myAntenna.c_str() );
     }
     
     static void pLDT(std::string &s, size_t &i, size_t endbracket)
    @@ -1790,6 +1896,74 @@ static void pTxQueIMAGE(std::string &s, size_t &i, size_t endbracket)
     	s.replace(i, endbracket - i + 1, "^!");
     }
     
    +static void doINSERTIMAGE(std::string s)
    +{
    +	if (s.length() > 0) {
    +
    +		bool Greyscale = false;
    +		size_t p = string::npos;
    +		string fname = s.substr(7);
    +		p = fname.find(">");
    +		fname.erase(p);
    +		p = fname.find("G,");
    +		if (p == string::npos) p = fname.find("g,");
    +		if (p != string::npos) {
    +			Greyscale = true;
    +			fname.erase(p,2);
    +		}
    +		while (fname[0] == ' ') fname.erase(0,1);
    +		if (s.empty()) return;
    +
    +		trx_mode md = active_modem->get_mode();
    +		if ((md == MODE_MFSK16 || md == MODE_MFSK32 ||
    +			 md == MODE_MFSK64 || md == MODE_MFSK128) &&
    +			active_modem->get_cap() & modem::CAP_IMG) {
    +				Greyscale ?
    +					active_modem->send_Grey_image(fname) :
    +					active_modem->send_color_image(fname);
    +		}
    +		else if (md == MODE_IFKP) {
    +			ifkp_load_scaled_image(fname);
    +		}
    +		else if (md >= MODE_THOR_FIRST && md <= MODE_THOR_LAST)
    +			thor_load_scaled_image(fname);
    +	}
    +	que_ok = true;
    +}
    +
    +void TxQueINSERTIMAGE(std::string s)
    +{
    +	trx_mode active_mode = active_modem->get_mode();
    +	if (! (active_mode == MODE_MFSK16 ||
    +		   active_mode == MODE_MFSK32 ||
    +		   active_mode == MODE_MFSK64 ||
    +		   active_mode == MODE_MFSK128 ||
    +		   active_mode == MODE_IFKP ||
    +		   (active_mode >= MODE_THOR_FIRST && active_mode <= MODE_THOR_LAST) ) &&
    +		   active_modem->get_cap() & modem::CAP_IMG)
    +		return;
    +
    +	string scmd = "";
    +	scmd.insert(7,s);
    +
    +	struct CMDS cmd = { scmd, doINSERTIMAGE };
    +	push_txcmd(cmd);
    +
    +	string itext = s;
    +	size_t p = itext.rfind("\\");
    +	if (p == string::npos) p = itext.rfind("/");
    +	if (p != string::npos) itext.erase(0, p+1);
    +	p = itext.rfind(".");
    +	if (p != string::npos) itext.erase(p);
    +	itext.insert(0, "\nImage: ");
    +	itext.append(" ^!");
    +
    +	if (active_mode == MODE_IFKP)
    +		ifkp_tx_text->add_text(itext);
    +	else
    +		TransmitText->add_text(itext);
    +}
    +
     #include 
     #include "re.h"
     
    @@ -2303,6 +2477,7 @@ static void doGOFREQ(std::string s)
     		if (number > progdefaults.HighFreqCutoff)
     			number = progdefaults.HighFreqCutoff;
     		active_modem->set_freq(number);
    +		wf->redraw();
     	}
     	que_ok = true;
     }
    @@ -2446,57 +2621,13 @@ static void pTxQueQSY(std::string &s, size_t &i, size_t endbracket)
     	s.replace(i, endbracket - i + 1, "^!");
     }
     
    -float  waitFILWID = 0.0;
    +float  wait_after_mode_change = 0.0;
     static string sFILWID;
     static void delayedFILWID(void *)
     {
     	qso_opBW->value(sFILWID.c_str());
     	cb_qso_opBW();
    -	waitFILWID = 0.0;
    -}
    -
    -static void pRIGMODE(std::string& s, size_t& i, size_t endbracket)
    -{
    -	if (within_exec) {
    -		s.replace(i, endbracket - i + 1, "");
    -		return;
    -	}
    -	std::string sMode = s.substr(i+9, endbracket - i - 9);
    -	qso_opMODE->value(sMode.c_str());
    -	cb_qso_opMODE();
    -	s.replace(i, endbracket - i + 1, "");
    -	if (s.find("FILWID") != string::npos)
    -		waitFILWID = progdefaults.mbw;
    -}
    -
    -static void doRIGMODE(std::string s)
    -{
    -	std::string sMode = s.substr(10, s.length() - 11);
    -	qso_opMODE->value(sMode.c_str());
    -	cb_qso_opMODE();
    -	que_ok = true;
    -}
    -
    -static void pTxQueRIGMODE(std::string &s, size_t &i, size_t endbracket)
    -{
    -	if (within_exec) {
    -		s.replace(i, endbracket - i + 1, "");
    -		return;
    -	}
    -	struct CMDS cmd = { s.substr(i, endbracket - i + 1), doRIGMODE };
    -	push_txcmd(cmd);
    -	s.replace(i, endbracket - i + 1, "^!");
    -}
    -
    -static void pRxQueRIGMODE(std::string &s, size_t &i, size_t endbracket)
    -{
    -	if (within_exec) {
    -		s.replace(i, endbracket - i + 1, "");
    -		return;
    -	}
    -	struct CMDS cmd = { s.substr(i, endbracket - i + 1), doRIGMODE };
    -	push_rxcmd(cmd);
    -	s.replace(i, endbracket - i + 1, "");
    +	wait_after_mode_change = 0.0;
     }
     
     static void pFILWID(std::string& s, size_t& i, size_t endbracket)
    @@ -2506,10 +2637,8 @@ static void pFILWID(std::string& s, size_t& i, size_t endbracket)
     		return;
     	}
     	std::string sWidth = s.substr(i+8, endbracket - i - 8);
    -//	qso_opBW->value(sWidth.c_str());
    -//	cb_qso_opBW();
     	sFILWID = sWidth;
    -	Fl::add_timeout(waitFILWID, delayedFILWID);
    +	Fl::add_timeout(wait_after_mode_change, delayedFILWID);
     	s.replace(i, endbracket - i + 1, "");
     }
     
    @@ -2543,6 +2672,166 @@ static void pRxQueFILWID(std::string &s, size_t &i, size_t endbracket)
     	s.replace(i, endbracket - i + 1, "");
     }
     
    +static void pRIGMODE(std::string& s, size_t& i, size_t endbracket)
    +{
    +	if (within_exec) {
    +		s.replace(i, endbracket - i + 1, "");
    +		return;
    +	}
    +	std::string sMode = s.substr(i+9, endbracket - i - 9);
    +	qso_opMODE->value(sMode.c_str());
    +	cb_qso_opMODE();
    +	s.replace(i, endbracket - i + 1, "");
    +	if ((s.find("FILWID") != string::npos) ||
    +		(s.find("RIGLO") != string::npos) ||
    +		(s.find("RIGHI") != string::npos) )
    +		wait_after_mode_change = progdefaults.mbw;
    +	else
    +		wait_after_mode_change = 0;
    +}
    +
    +static void doRIGMODE(std::string s)
    +{
    +	std::string sMode = s.substr(10, s.length() - 11);
    +	qso_opMODE->value(sMode.c_str());
    +	cb_qso_opMODE();
    +	que_ok = true;
    +}
    +
    +static void pTxQueRIGMODE(std::string &s, size_t &i, size_t endbracket)
    +{
    +	if (within_exec) {
    +		s.replace(i, endbracket - i + 1, "");
    +		return;
    +	}
    +	struct CMDS cmd = { s.substr(i, endbracket - i + 1), doRIGMODE };
    +	push_txcmd(cmd);
    +	s.replace(i, endbracket - i + 1, "^!");
    +}
    +
    +static void pRxQueRIGMODE(std::string &s, size_t &i, size_t endbracket)
    +{
    +	if (within_exec) {
    +		s.replace(i, endbracket - i + 1, "");
    +		return;
    +	}
    +	struct CMDS cmd = { s.substr(i, endbracket - i + 1), doRIGMODE };
    +	push_rxcmd(cmd);
    +	s.replace(i, endbracket - i + 1, "");
    +}
    +
    +static string sRIGLO;
    +
    +static void delayedRIGLO(void *)
    +{
    +	qso_opBW2->value(sRIGLO.c_str());
    +	cb_qso_opBW2();
    +	wait_after_mode_change = 0.0;
    +}
    +
    +static void pRIGLO(std::string& s, size_t& i, size_t endbracket)
    +{
    +	if (within_exec) {
    +		s.replace(i, endbracket - i + 1, "");
    +		return;
    +	}
    +	std::string sLO = s.substr(i+7, endbracket - i - 7);
    +	sRIGLO = sLO;
    +	if (wait_after_mode_change)
    +		Fl::add_timeout(wait_after_mode_change, delayedRIGLO);
    +	else {
    +		qso_opBW2->value(sLO.c_str());
    +		cb_qso_opBW2();
    +	}
    +	s.replace(i, endbracket - i + 1, "");
    +}
    +
    +static void doRIGLO(std::string s)
    +{
    +	std::string sLO = s.substr(8, s.length() - 9);
    +	qso_opBW2->value(sLO.c_str());
    +	cb_qso_opBW2();
    +	que_ok = true;
    +}
    +
    +static void pTxQueRIGLO(std::string &s, size_t &i, size_t endbracket)
    +{
    +	if (within_exec) {
    +		s.replace(i, endbracket - i + 1, "");
    +		return;
    +	}
    +	struct CMDS cmd = { s.substr(i, endbracket - i + 1), doRIGLO };
    +	push_txcmd(cmd);
    +	s.replace(i, endbracket - i + 1, "^!");
    +}
    +
    +static void pRxQueRIGLO(std::string &s, size_t &i, size_t endbracket)
    +{
    +	if (within_exec) {
    +		s.replace(i, endbracket - i + 1, "");
    +		return;
    +	}
    +	struct CMDS cmd = { s.substr(i, endbracket - i + 1), doRIGLO };
    +	push_rxcmd(cmd);
    +	s.replace(i, endbracket - i + 1, "");
    +}
    +
    +static string sRIGHI;
    +
    +static void delayedRIGHI(void *)
    +{
    +	qso_opBW1->value(sRIGHI.c_str());
    +	cb_qso_opBW1();
    +	wait_after_mode_change = 0.0;
    +}
    +
    +static void pRIGHI(std::string& s, size_t& i, size_t endbracket)
    +{
    +	if (within_exec) {
    +		s.replace(i, endbracket - i + 1, "");
    +		return;
    +	}
    +	std::string sHI = s.substr(i+7, endbracket - i - 7);
    +	sRIGHI = sHI;
    +	if (wait_after_mode_change)
    +		Fl::add_timeout(wait_after_mode_change, delayedRIGHI);
    +	else {
    +		qso_opBW1->value(sHI.c_str());
    +		cb_qso_opBW1();
    +	}
    +	s.replace(i, endbracket - i + 1, "");
    +}
    +
    +static void doRIGHI(std::string s)
    +{
    +	std::string sHI = s.substr(8, s.length() - 9);
    +	qso_opBW1->value(sHI.c_str());
    +	cb_qso_opBW1();
    +	que_ok = true;
    +}
    +
    +static void pTxQueRIGHI(std::string &s, size_t &i, size_t endbracket)
    +{
    +	if (within_exec) {
    +		s.replace(i, endbracket - i + 1, "");
    +		return;
    +	}
    +	struct CMDS cmd = { s.substr(i, endbracket - i + 1), doRIGHI };
    +	push_txcmd(cmd);
    +	s.replace(i, endbracket - i + 1, "^!");
    +}
    +
    +static void pRxQueRIGHI(std::string &s, size_t &i, size_t endbracket)
    +{
    +	if (within_exec) {
    +		s.replace(i, endbracket - i + 1, "");
    +		return;
    +	}
    +	struct CMDS cmd = { s.substr(i, endbracket - i + 1), doRIGHI };
    +	push_rxcmd(cmd);
    +	s.replace(i, endbracket - i + 1, "");
    +}
    +
     static void pWX(std::string &s, size_t &i, size_t endbracket)
     {
     	string wx;
    @@ -2565,21 +2854,82 @@ void set_macro_env(void)
     #ifndef __WOE32__
     		pSKEDH, FLDIGI_RX_IPC_KEY, FLDIGI_TX_IPC_KEY,
     #endif
    -		FLDIGI_XMLRPC_ADDRESS, FLDIGI_XMLRPC_PORT,
    -		FLDIGI_ARQ_ADDRESS, FLDIGI_ARQ_PORT,
    +		FLDIGI_XMLRPC_ADDRESS,
    +		FLDIGI_XMLRPC_PORT,
    +		FLDIGI_ARQ_ADDRESS,
    +		FLDIGI_ARQ_PORT,
     
    -		FLDIGI_VERSION_ENVVAR, FLDIGI_PID, FLDIGI_CONFIG_DIR,
    +		FLDIGI_VERSION_ENVVAR,
    +		FLDIGI_PID,
    +		FLDIGI_CONFIG_DIR,
     
    -		FLDIGI_MY_CALL, FLDIGI_MY_NAME, FLDIGI_MY_LOCATOR,
    +		FLDIGI_MY_CALL,
    +		FLDIGI_MY_NAME,
    +		FLDIGI_MY_LOCATOR,
     
    -		FLDIGI_MODEM, FLDIGI_MODEM_LONG_NAME, FLDIGI_DIAL_FREQUENCY,
    -		FLDIGI_AUDIO_FREQUENCY, FLDIGI_FREQUENCY,
    +		FLDIGI_MODEM,
    +		FLDIGI_MODEM_LONG_NAME,
    +		FLDIGI_MODEM_ADIF_NAME,
    +		FLDIGI_DIAL_FREQUENCY,
    +		FLDIGI_AUDIO_FREQUENCY,
    +		FLDIGI_FREQUENCY,
     
     		FLDIGI_MACRO_FILE,
    +
     		FLDIGI_LOG_FILE,
    -		FLDIGI_LOG_FREQUENCY, FLDIGI_LOG_TIME_ON, FLDIGI_LOG_TIME_OFF, FLDIGI_LOG_CALL, FLDIGI_LOG_NAME,
    -		FLDIGI_LOG_RST_IN, FLDIGI_LOG_RST_OUT, FLDIGI_LOG_QTH, FLDIGI_LOG_LOCATOR,
    -		FLDIGI_LOG_NOTES, FLDIGI_AZ, ENV_SIZE
    +		FLDIGI_LOG_FREQUENCY,
    +		FLDIGI_LOG_DATE,
    +		FLDIGI_LOG_DATE_OFF,
    +		FLDIGI_LOG_TIME_ON,
    +		FLDIGI_LOG_TIME_OFF,
    +		FLDIGI_LOG_CALL,
    +		FLDIGI_LOG_NAME,
    +		FLDIGI_LOG_RST_IN,
    +		FLDIGI_LOG_RST_OUT,
    +		FLDIGI_LOG_QTH,
    +		FLDIGI_LOG_LOCATOR,
    +		FLDIGI_LOG_NOTES,
    +		FLDIGI_LOG_STATE,
    +		FLDIGI_LOG_COUNTRY,
    +		FLDIGI_LOG_SERNO_IN,
    +		FLDIGI_LOG_SERNO_OUT,
    +		FLDIGI_XCHG_IN,
    +		FLDIGI_XCGH_OUT,
    +		FLDIGI_VE_PROV,
    +		FLDIGI_AZ,
    +
    +		FLDIGI_LOGBOOK_CALL,
    +		FLDIGI_LOGBOOK_NAME,
    +		FLDIGI_LOGBOOK_DATE,
    +		FLDIGI_LOGBOOK_TIME_ON,
    +		FLDIGI_LOGBOOK_DATE_OFF,
    +		FLDIGI_LOGBOOK_TIME_OFF,
    +		FLDIGI_LOGBOOK_RST_IN,
    +		FLDIGI_LOGBOOK_RST_OUT,
    +		FLDIGI_LOGBOOK_FREQUENCY,
    +		FLDIGI_LOGBOOK_MODE,
    +		FLDIGI_LOGBOOK_STATE,
    +		FLDIGI_LOGBOOK_VE_PROV,
    +		FLDIGI_LOGBOOK_COUNTRY,
    +		FLDIGI_LOGBOOK_SERNO_IN,
    +		FLDIGI_LOGBOOK_SERNO_OUT,
    +		FLDIGI_LOGBOOK_XCHG_IN,
    +		FLDIGI_LOGBOOK_XCHG_OUT,
    +		FLDIGI_LOGBOOK_QTH,
    +		FLDIGI_LOGBOOK_LOCATOR,
    +		FLDIGI_LOGBOOK_QSL_R,
    +		FLDIGI_LOGBOOK_QSL_S,
    +		FLDIGI_LOGBOOK_NOTES,
    +		FLDIGI_LOGBOOK_TX_PWR,
    +		FLDIGI_LOGBOOK_COUNTY,
    +		FLDIGI_LOGBOOK_IOTA,
    +		FLDIGI_LOGBOOK_DXCC,
    +		FLDIGI_LOGBOOK_QSL_VIA,
    +		FLDIGI_LOGBOOK_CONTINENT,
    +		FLDIGI_LOGBOOK_CQZ,
    +		FLDIGI_LOGBOOK_ITUZ,
    +
    +		ENV_SIZE
     	};
     
     	struct {
    @@ -2606,6 +2956,8 @@ void set_macro_env(void)
     
     		{ "FLDIGI_MODEM", mode_info[active_modem->get_mode()].sname },
     		{ "FLDIGI_MODEM_LONG_NAME", mode_info[active_modem->get_mode()].name },
    +		{ "FLDIGI_MODEM_ADIF_NAME", mode_info[active_modem->get_mode()].adif_name },
    +
     		{ "FLDIGI_DIAL_FREQUENCY", "" },
     		{ "FLDIGI_AUDIO_FREQUENCY", "" },
     		{ "FLDIGI_FREQUENCY", "" },
    @@ -2614,7 +2966,10 @@ void set_macro_env(void)
     		{ "FLDIGI_MACRO_FILE", progStatus.LastMacroFile.c_str() },
     
     		{ "FLDIGI_LOG_FILE", progdefaults.logbookfilename.c_str() },
    +
     		{ "FLDIGI_LOG_FREQUENCY", inpFreq->value() },
    +		{ "FLDIGI_LOG_DATE", inpDate_log->value() },
    +		{ "FLDIGI_LOG_DATE_OFF", inpDateOff_log->value() },
     		{ "FLDIGI_LOG_TIME_ON", inpTimeOn->value() },
     		{ "FLDIGI_LOG_TIME_OFF", inpTimeOff->value() },
     		{ "FLDIGI_LOG_CALL", inpCall->value() },
    @@ -2624,7 +2979,46 @@ void set_macro_env(void)
     		{ "FLDIGI_LOG_QTH", inpQth->value() },
     		{ "FLDIGI_LOG_LOCATOR", inpLoc->value() },
     		{ "FLDIGI_LOG_NOTES", inpNotes->value() },
    -		{ "FLDIGI_AZ", inpAZ->value() }
    +		{ "FLDIGI_LOG_STATE", inpState->value() },
    +		{ "FLDIGI_LOG_COUNTRY", inpCountry->value() },
    +		{ "FLDIGI_LOG_SERNO_IN", inpSerNo->value() },
    +		{ "FLDIGI_LOG_SERNO_OUT", outSerNo->value() },
    +		{ "FLDIGI_XCHG_IN", inpXchgIn->value() },
    +		{ "FLDIGI_XCHG_OUT", inpSend1->value() },
    +		{ "FLDIGI_VE_PROV", inpVEprov->value() },
    +		{ "FLDIGI_AZ", inpAZ->value() },
    +
    +		{ "FLDIGI_LOGBOOK_CALL", inpCall_log->value() },
    +		{ "FLDIGI_LOGBOOK_NAME", inpName_log->value () },
    +		{ "FLDIGI_LOGBOOK_DATE", inpDate_log->value() },
    +		{ "FLDIGI_LOGBOOK_TIME_ON", inpTimeOn_log->value() },
    +		{ "FLDIGI_LOGBOOK_DATE_OFF", inpDateOff_log->value() },
    +		{ "FLDIGI_LOGBOOK_TIME_OFF", inpTimeOff_log->value() },
    +		{ "FLDIGI_LOGBOOK_RST_IN", inpRstR_log->value() },
    +		{ "FLDIGI_LOGBOOK_RST_OUT", inpRstS_log->value() },
    +		{ "FLDIGI_LOGBOOK_FREQUENCY", inpFreq_log->value() },
    +		{ "FLDIGI_LOGBOOK_MODE", inpMode_log->value() },
    +		{ "FLDIGI_LOGBOOK_STATE", inpState_log->value() },
    +		{ "FLDIGI_LOGBOOK_VE_PROV", inpVE_Prov_log->value() },
    +		{ "FLDIGI_LOGBOOK_COUNTRY", inpCountry_log->value() },
    +		{ "FLDIGI_LOGBOOK_SERNO_IN", inpSerNoIn_log->value() },
    +		{ "FLDIGI_LOGBOOK_SERNO_OUT", inpSerNoOut_log->value() },
    +		{ "FLDIGI_LOGBOOK_XCHG_IN", inpXchgIn_log->value() },
    +		{ "FLDIGI_LOGBOOK_XCHG_OUT", inpMyXchg_log->value() },
    +		{ "FLDIGI_LOGBOOK_QTH", inpQth_log->value() },
    +		{ "FLDIGI_LOGBOOK_LOCATOR", inpLoc_log->value() },
    +		{ "FLDIGI_LOGBOOK_QSL_R", inpQSLrcvddate_log->value() },
    +		{ "FLDIGI_LOGBOOK_QSL_S", inpQSLsentdate_log->value() },
    +		{ "FLDIGI_LOGBOOK_NOTES", inpNotes_log->value() },
    +		{ "FLDIGI_LOGBOOK_TX_PWR", inpTX_pwr_log->value() },
    +		{ "FLDIGI_LOGBOOK_COUNTY", inpCNTY_log->value() },
    +		{ "FLDIGI_LOGBOOK_IOTA", inpIOTA_log->value() },
    +		{ "FLDIGI_LOGBOOK_DXCC", inpDXCC_log->value() },
    +		{ "FLDIGI_LOGBOOK_QSL_VIA", inpQSL_VIA_log->value() },
    +		{ "FLDIGI_LOGBOOK_CONTINENT", inpCONT_log->value() },
    +		{ "FLDIGI_LOGBOOK_CQZ", inpCQZ_log->value() },
    +		{ "FLDIGI_LOGBOOK_ITUZ", inpITUZ_log->value() }
    +
     	};
     
     #ifndef __WOE32__
    @@ -2669,8 +3063,13 @@ void set_macro_env(void)
     	unsetenv("MALLOC_PERTURB_");
     #endif
     
    -	for (size_t j = 0; j < ENV_SIZE; j++)
    -		setenv(env[j].var, env[j].val, 1);
    +	string temp;
    +	size_t pch;
    +	for (size_t j = 0; j < ENV_SIZE; j++) {
    +		temp = env[j].val;
    +		while ((pch = temp.find("\n")) != string::npos) temp[pch] = ';';
    +		setenv(env[j].var, temp.c_str(), 1);
    +	}
     
     	string path = getenv("PATH");
     	string mypath = ScriptsDir;
    @@ -2982,21 +3381,22 @@ bool queue_must_rx()
     // occurs immediately after the ^r execution
     // AND after TX_STATE returns to Rx
     // ^r is the control string substitute for the  macro tag
    -void Rx_queue_execute()
    +int time_out = 400;
    +void Rx_queue_execution(void *)
     {
    -	if (Rx_cmds.empty()) return;
    -
    -	int time_out = 100; // force return after ten seconds
    -	while (trx_state != STATE_RX && time_out) {
    -		time_out--;
    -		Fl::awake();
    -		MilliSleep(100);
    -	}
    -	if (!time_out) {
    -		while (!Rx_cmds.empty()) Rx_cmds.pop();
    +	if (trx_state != STATE_RX) {
    +		if (time_out-- == 0) {
    +			while (!Rx_cmds.empty()) Rx_cmds.pop();
    +			LOG_ERROR("%s", "failed");
    +			time_out = 200;
    +			return;
    +		}
    +		Fl::repeat_timeout( .050, Rx_queue_execution );
     		return;
     	}
    +	LOG_INFO("action delayed by %4.2f seconds", (400 - time_out)*.050);
     
    +	time_out = 400;
     	CMDS cmd;
     	while (!Rx_cmds.empty()) {
     		cmd = Rx_cmds.front();
    @@ -3006,10 +3406,24 @@ void Rx_queue_execute()
     		cmd.cmd.erase(0,2);
     		cmd.cmd.insert(0,"",		pQSYFM},
     {"",		pMAPIT},
     {"",	pREPEAT},
    @@ -3124,6 +3540,7 @@ static const MTAGS mtags[] = {
     	{"",		pWX},
     	{"",	pRxQueGOHOME},
     	{"<@RIGMODE:",	pRxQueRIGMODE},
     	{"<@FILWID:",	pRxQueFILWID},
    +    {"<@RIGHI:",    pRxQueRIGHI},
    +    {"<@RIGLO:",    pRxQueRIGLO},
     	{"<@TXRSID:",	pRxQueTXRSID},
    +	{"<@WAIT:",     pRxQueWAIT},
     
     	{0, 0}
     };
    @@ -3240,7 +3662,10 @@ void MACROTEXT::loadDefault()
     		LOG_INFO("%s", Macroset.c_str());
     		Macroset.insert(0, "\n");
     		Macroset.append("\n");
    -		ReceiveText->addstr(Macroset);
    +		if (active_modem->get_mode() == MODE_IFKP)
    +			ifkp_rx_text->addstr(Macroset);
    +		else
    +			ReceiveText->addstr(Macroset);
     	}
     }
     
    @@ -3258,15 +3683,17 @@ void MACROTEXT::openMacroFile()
     								 _("Open macro file"),
     								 _("Fldigi macro definition file\t*.{mdf}"),
     								 deffilename.c_str());
    -	if (p) {
    +	if (p && *p) {
     		loadMacros(p);
     		progStatus.LastMacroFile = p;
    -//	}
     		showMacroSet();
     		if (progdefaults.DisplayMacroFilename) {
     			string Macroset;
     			Macroset.assign("\nLoaded macros: ").append(progStatus.LastMacroFile).append("\n");
    -			ReceiveText->addstr(Macroset);
    +			if (active_modem->get_mode() == MODE_IFKP)
    +				ifkp_rx_text->addstr(Macroset);
    +			else
    +				ReceiveText->addstr(Macroset);
     		}
     	}
     }
    @@ -3297,12 +3724,15 @@ void MACROTEXT::saveMacroFile()
     								 _("Save macro file"),
     								 _("Fldigi macro definition file\t*.{mdf}"),
     								 deffilename.c_str());
    -	if (p) {
    -		string sp = p;
    -		if (sp.rfind(".mdf") == string::npos) sp.append(".mdf");
    -		saveMacros(sp.c_str());
    -		progStatus.LastMacroFile = sp;
    -	}
    +	if (!p) return;
    +	if (!*p) return;
    +
    +	string sp = p;
    +	if (sp.empty()) return;
    +	if (sp.rfind(".mdf") == string::npos) sp.append(".mdf");
    +	saveMacros(sp.c_str());
    +	progStatus.LastMacroFile = sp;
    +
     }
     
     void MACROTEXT::savecurrentMACROS(std::string &s, size_t &i, size_t endbracket)
    @@ -3404,7 +3834,10 @@ std::string MACROTEXT::expandMacro(std::string &s, bool recurse = false)
     		expanded.erase(idx, 2);
     		expanded.append("^r");
     	}
    -	
    +
    +	if (!TransmitON && !Rx_cmds.empty())
    +		Fl::add_timeout(0, rx_que_continue);
    +
     	return expanded;
     }
     
    @@ -3464,44 +3897,66 @@ static void set_button(Fl_Button* button, bool value)
     void MACROTEXT::timed_execute()
     {
     	queue_reset();
    -	TransmitText->clear();
    +	if (active_modem->get_mode() == MODE_IFKP)
    +		ifkp_tx_text->clear();
    +	else
    +		TransmitText->clear();
     	if (!rx_only) {
     		text2send = expandMacro(exec_string);
    -		TransmitText->add_text(text2send);
    +		if (active_modem->get_mode() == MODE_IFKP)
    +			ifkp_tx_text->add_text(text2send);
    +		else
    +			TransmitText->add_text(text2send);
     		exec_string.clear();
     		active_modem->set_stopflag(false);
     		start_tx();
     	}
     }
     
    +bool wait_execute = false;
    +
     void MACROTEXT::execute(int n)
     {
    +	while (wait_execute) { MilliSleep(10); }
    +	wait_execute = true;
    +
     	mNbr = n;
     	text2send = expandMacro(text[n]);
    -	
    +
     	if (timed_exec) {
     		progStatus.repeatMacro = -1;
     		exec_string = text[n];
     		timed_exec = false;
     		startTimedExecute(name[n]);
    +		wait_execute = false;
     		return;
     	}
    -	
    +
    +	trx_mode mode = active_modem->get_mode();
    +
     	if (!rx_only) {
    -		if (progStatus.repeatMacro == -1)
    -			TransmitText->add_text( text2send );
    -		else {
    +		if (progStatus.repeatMacro == -1) {
    +			if (mode == MODE_IFKP) {
    +				ifkp_tx_text->add_text( text2send );
    +			} else {
    +				TransmitText->add_text( text2send );
    +			}
    +		} else {
     			size_t p = std::string::npos;
     			text2send = text[n];
     			while ((p = text2send.find('<')) != std::string::npos)
     				text2send[p] = '[';
     			while ((p = text2send.find('>')) != std::string::npos)
     				text2send[p] = ']';
    -			TransmitText->add_text( text2send );
    +			if (mode == MODE_IFKP) {
    +				ifkp_tx_text->add_text( text2send );
    +			} else {
    +				TransmitText->add_text( text2send );
    +			}
     		}
     	}
     	text2send.clear();
    -	
    +
     	if (ToggleTXRX) {
     		text2send.clear();
     		if (!wf->xmtrcv->value()) {
    @@ -3510,27 +3965,31 @@ void MACROTEXT::execute(int n)
     				Fl::add_timeout(idleTime, idleTimer);
     		} else
     			REQ(set_button, wf->xmtrcv, false);
    +		wait_execute = false;
     		return;
     	}
     	if (useWait && waitTime > 0) {
     		Fl::add_timeout(waitTime, finishWait);
     		useWait = false;
    +		wait_execute = false;
     		return;
     	}
     	if (useTune && tuneTime > 0) {
     		trx_tune();
     		Fl::add_timeout(tuneTime, finishTune);
     		useTune = false;
    +		wait_execute = false;
     		return;
     	}
     	if ( TransmitON ) {
     		if (macro_idle_on && idleTime > 0)
     			Fl::add_timeout(idleTime, idleTimer);
    -		
    +
     		active_modem->set_stopflag(false);
     		start_tx();
     		TransmitON = false;
     	}
    +	wait_execute = false;
     }
     
     void MACROTEXT::repeat(int n)
    @@ -3564,7 +4023,7 @@ static std::string mtext =
     ";
     
     void MACROTEXT::saveMacros(const std::string& fname) {
    -	
    +
     	std::string work;
     	std::string output;
     	char temp[200];
    @@ -3583,7 +4042,7 @@ void MACROTEXT::saveMacros(const std::string& fname) {
     		output.append(work).append("\n");
     	}
     	UTF8_writefile(fname.c_str(), output);
    -	
    +
     	changed = false;
     }
     
    diff --git a/src/misc/record_loader.cxx b/src/misc/record_loader.cxx
    index fd777622..3344e566 100644
    --- a/src/misc/record_loader.cxx
    +++ b/src/misc/record_loader.cxx
    @@ -60,7 +60,8 @@ int RecordLoaderInterface::LoadAndRegister()
     	std::string filnam = storage_filename().first;
     
     	time_t cntTim = time(NULL);
    -	LOG_INFO("Opening:%s", filnam.c_str());
    +	if (bMOREINFO)
    +		LOG_INFO("Opening:%s", filnam.c_str());
     
     	std::ifstream ifs( filnam.c_str() );
     
    @@ -93,8 +94,10 @@ int RecordLoaderInterface::LoadAndRegister()
     		}
     	}
     	ifs.close();
    -	LOG_INFO( "Read:%s with %d records in %d seconds",
    -		filnam.c_str(), static_cast(nbRec), static_cast( time(NULL) - cntTim ) );
    +	if (bMOREINFO)
    +		LOG_INFO( "Read:%s with %d records in %d seconds",
    +			filnam.c_str(), static_cast(nbRec),
    +			static_cast( time(NULL) - cntTim ) );
     	return nbRec ;
     }
     
    @@ -219,7 +222,9 @@ std::pair< std::string, bool > RecordLoaderInterface::storage_filename(bool crea
     
     	// Second try with a file maybe installed by "make install".
     	std::string filnam_inst = PKGDATADIR "/" + base_filename();
    -	LOG_INFO("Errno=%s with %s. Trying %s", strerror(errno), filnam_data.c_str(), filnam_inst.c_str() );
    +	if (bMOREINFO)
    +		LOG_INFO("Errno=%s with %s. Trying %s",
    +			strerror(errno), filnam_data.c_str(), filnam_inst.c_str() );
     	ifs.open( filnam_inst.c_str() );
     	if( ifs )
     	{
    @@ -449,7 +454,9 @@ void DerivedRecordLst::cbGuiUpdate()
     		double timeout=600.0;
     		// Consider truncating the HTTP header.
     		int res = fetch_http_gui(url, reply, timeout );
    -		LOG_INFO("Loaded %s : %d chars. res=%d", url.c_str(), (int)reply.size(), res );
    +		if (bMOREINFO)
    +			LOG_INFO("Loaded %s : %d chars. res=%d",
    +				url.c_str(), (int)reply.size(), res );
     		if( ! res )
     		{
     			int ok = fl_choice2(
    @@ -526,7 +533,8 @@ void DerivedRecordLst::cbGuiReset()
     			fl_alert("Cannot erase installed data file %s", stofil );
     			continue ;
     		} else {
    -			LOG_INFO("Erasing %s", stofil );
    +			if (bMOREINFO)
    +				LOG_INFO("Erasing %s", stofil );
     			int res = ::remove( stofil );
     			if( ( res != 0 ) && ( res != ENOENT ) ) {
     				fl_alert("Error erasing data file %s:%s", stofil, strerror(errno) );
    diff --git a/src/misc/socket.cxx b/src/misc/socket.cxx
    index b9be9bac..03ab025d 100644
    --- a/src/misc/socket.cxx
    +++ b/src/misc/socket.cxx
    @@ -59,12 +59,14 @@
     #include 
     #include 
     #include 
    +#include 
     
     //#undef NDEBUG
     #include "debug.h"
     
     #include "socket.h"
     
    +
     #if HAVE_GETADDRINFO && !defined(AI_NUMERICSERV)
     #  define AI_NUMERICSERV 0
     #endif
    @@ -665,9 +667,11 @@ void Socket::bind(void)
     #else
     		;
     #endif
    -	if (::bind(sockfd, ainfo->ai_addr, ainfo->ai_addrlen) == -1)
    +	if (::bind(sockfd, ainfo->ai_addr, ainfo->ai_addrlen) == -1) {
    +		if(errno != EADDRINUSE) // EADDRINUSE == 48
     		throw SocketException(errno, "bind");
     }
    +}
     
     ///
     /// Binds the socket to the address associated with the object
    @@ -801,6 +805,30 @@ Socket Socket::accept1(void)
     
     	return s;
     }
    +///
    +/// Accepts a connection
    +///
    +/// The socket must already have been bound to an address via a call to the bind
    +/// method.
    +///
    +/// @return A Socket instance pointer for the accepted connection
    +///
    +Socket * Socket::accept2(void)
    +{
    +	listen();
    +
    +	// wait for fd to become readable
    +	if (nonblocking && ((timeout.tv_sec > 0) || (timeout.tv_usec > 0)))
    +		if (!wait(0))
    +			throw SocketException(ETIMEDOUT, "select");
    +
    +	int r;
    +	if ((r = ::accept(sockfd, NULL, 0)) == -1)
    +		return (Socket *)0;
    +	set_close_on_exec(true, r);
    +
    +	return new Socket(r);
    +}
     
     ///
     /// Connects the socket to the address that is associated with the object
    @@ -813,6 +841,20 @@ void Socket::connect(void)
     	if (::connect(sockfd, ainfo->ai_addr, ainfo->ai_addrlen) == -1)
     		throw SocketException(errno, "connect");
     }
    +///
    +/// Connects the socket to the address that is associated with the object
    +/// Return connect state (T/F)
    +///
    +bool Socket::connect1(void)
    +{
    +#ifndef NDEBUG
    +	LOG_DEBUG("Connecting to %s", address.get_str(ainfo).c_str());
    +#endif
    +	if (::connect(sockfd, ainfo->ai_addr, ainfo->ai_addrlen) == -1) {
    +		return false;
    +	}
    +	return true;
    +}
     
     ///
     /// Set socket to allow for broadcasting.
    @@ -875,8 +917,14 @@ size_t Socket::send(const void* buf, size_t len)
     				shutdown(sockfd, SHUT_WR);
     				throw SocketException(errno, "send");
     			} else if (r == -1) {
    -				if (errno != EAGAIN)
    +				switch(errno) {
    +					case EAGAIN:
    +					case ENOTCONN:
    + 				    case EBADF:
    +						break;
    +					default:
     					throw SocketException(errno, "send");
    +				}
     				r = 0;
     			}
     		}
    diff --git a/src/misc/status.cxx b/src/misc/status.cxx
    index 0f969d62..47b7d1c7 100644
    --- a/src/misc/status.cxx
    +++ b/src/misc/status.cxx
    @@ -78,6 +78,7 @@ status progStatus = {
     	false,				// bool Rig_Log_UI;
     	false,				// bool Rig_Contest_UI;
     	false,				// bool DOCKEDSCOPE;
    +	false,				// bool tbar_is_docked;
     	50,					// int RxTextHeight;
     	WMIN/2,				// int tiled_group_x;
     	false,				// bool show_channels;
    @@ -110,13 +111,14 @@ status progStatus = {
     	200,				// int		tile_w;
     	90,					// int		tile_y;
     	150,				// int		tile_h;
    +	0.5,				// double	tile_y_ratio;
     	0.5,				// double	fsq_ratio;
    +	0.5,				// double	ifkp_ratio;
     	false,				// bool LOGenabled
     	5.0,				// double sldrSquelchValue
     	5.0,				// double sldrPwrSquelchValue
     	true,				// bool afconoff
     	true,				// bool sqlonoff
    -	false,				// bool pwrsqlonoff
     	50,					// int	scopeX;
     	50,					// int	scopeY;
     	false,				// bool	scopeVisible;
    @@ -196,14 +198,20 @@ status progStatus = {
     	progdefaults.busyChannelSeconds,
     	progdefaults.kpsql_attenuation,
     	progdefaults.csma_enabled,
    +	progdefaults.kiss_tcp_io,
    +	progdefaults.kiss_tcp_listen,
    +    progdefaults.kpsql_enabled,
    +    progdefaults.kiss_io_modem_change_inhibit,
     	true,
     	0.0,
    +	progdefaults.psk8DCDShortFlag,
     
     	"CQ",				// string browser_search;
     
     	false,				// meters
     
     	false,				// fsq_rx_abort
    +	false,				// ifkp_rx_abort
     
     	false				// bool bLastStateRead;
     };
    @@ -249,9 +257,11 @@ void status::saveLastState()
     		tile_w = text_panel->w();
     		tile_y = progdefaults.rxtx_swap ? TransmitText->h() : ReceiveText->h();
     		tile_h = text_panel->h();
    +		tile_y_ratio = 1.0 * tile_y / text_group->h();
     		if (text_panel->w() != ReceiveText->w())
     			tile_x = mvgroup->w();
     		fsq_ratio = 1.0 * fsq_rx_text->h() / fsq_group->h();
    +		ifkp_ratio = 1.0 * ifkp_rx_text->h() / ifkp_group->h();
     	}
     
     	VIEWERvisible = dlgViewer->visible();
    @@ -263,14 +273,11 @@ void status::saveLastState()
     		VIEWERheight = dlgViewer->h();
     	}
     
    -	scopeVisible = false;
    -	if (scopeview && scopeview->visible()) {
    -		scopeVisible = true;
    -		scopeX = scopeview->x();
    -		scopeY = scopeview->y();
    -		scopeW = scopeview->w();
    -		scopeH = scopeview->h();
    -	}
    +	scopeVisible = scopeview->visible();
    +	scopeX = scopeview->x();
    +	scopeY = scopeview->y();
    +	scopeW = scopeview->w();
    +	scopeH = scopeview->h();
     
     	contestiatones = progdefaults.contestiatones;
     	contestiabw = progdefaults.contestiabw;
    @@ -318,6 +325,10 @@ void status::saveLastState()
     	busyChannelSeconds     = progdefaults.busyChannelSeconds;
         kpsql_attenuation      = progdefaults.kpsql_attenuation;
     	csma_enabled           = progdefaults.csma_enabled;
    +	kiss_tcp_io            = progdefaults.kiss_tcp_io;
    +	kiss_tcp_listen        = progdefaults.kiss_tcp_listen;
    +    kpsql_enabled          = progdefaults.kpsql_enabled;
    +    kiss_io_modem_change_inhibit = progdefaults.kiss_io_modem_change_inhibit;
     	squelch_value = 0;
     
     	Fl_Preferences spref(HomeDir.c_str(), "w1hkj.com", PACKAGE_TARNAME);
    @@ -327,11 +338,12 @@ void status::saveLastState()
     
     	spref.set("mode_name", mode_info[lastmode].sname);
     	spref.set("squelch_enabled", sqlonoff);
    -	spref.set("pwr_squelch_enabled", pwrsqlonoff);
     	spref.set("squelch_level", sldrSquelchValue);
     	spref.set("pwr_squelch_level", sldrPwrSquelchValue);
     	spref.set("afc_enabled", afconoff);
     
    +	spref.set("psk8DCDShortFlag", psk8DCDShortFlag);
    +
     	spref.set("log_enabled", LOGenabled);
     
     	spref.set("wf_carrier", carrier);
    @@ -360,6 +372,7 @@ if (!bWF_only) {
     	spref.set("rigcontest_ui", Rig_Contest_UI);
     	spref.set("noriglog", NO_RIGLOG);
     	spref.set("docked_scope", DOCKEDSCOPE);
    +	spref.set("tbar_is_docked", tbar_is_docked);
     
     	spref.set("rigctl_x", rigX);
     	spref.set("rigctl_y", rigY);
    @@ -384,7 +397,9 @@ if (!bWF_only) {
     	spref.set("tile_y", tile_y);
     	spref.set("tile_w", tile_w);
     	spref.set("tile_h", tile_h);
    +	spref.set("tile_y_ratio", tile_y_ratio);
     	spref.set("fsq_ratio", fsq_ratio);
    +	spref.set("ifkp_ratio", ifkp_ratio);
     
     	spref.set("scope_visible", scopeVisible);
     	spref.set("scope_x", scopeX);
    @@ -465,7 +480,7 @@ if (!bWF_only) {
     		spref.set("kiss_dual_port_enabled", kiss_dual_port_enabled);
     	}
     
    -	if(override_data_io_enabled != DISABLED_IO)
    +	if(!override_data_io_enabled)
     		spref.set("data_io_enabled", data_io_enabled);
     
     	spref.set("ax25_decode_enabled", ax25_decode_enabled);
    @@ -473,6 +488,11 @@ if (!bWF_only) {
     	spref.set("busyChannelSeconds", busyChannelSeconds);
     	spref.set("kpsql_attenuation", kpsql_attenuation);
     	spref.set("csma_enabled", csma_enabled);
    +	spref.set("kiss_tcp_io",         kiss_tcp_io);
    +	spref.set("kiss_tcp_listen",     kiss_tcp_listen);
    +    spref.set("kpsql_enabled",       kpsql_enabled);
    +    spref.set("kiss_io_modem_change_inhibit", kiss_io_modem_change_inhibit);
    +
     	spref.set("browser_search", browser_search.c_str());
     
     	spref.set("meters", meters);
    @@ -510,7 +530,6 @@ void status::loadLastState()
     	}
     
     	spref.get("squelch_enabled", i, sqlonoff); sqlonoff = i;
    -	spref.get("pwr_squelch_enabled", i, pwrsqlonoff); pwrsqlonoff = i;
     	spref.get("squelch_level", i, sldrSquelchValue); sldrSquelchValue = i;
     	spref.get("pwr_squelch_level", i, sldrPwrSquelchValue); sldrPwrSquelchValue = i;
     	spref.get("afc_enabled", i, afconoff); afconoff = i;
    @@ -553,7 +572,7 @@ void status::loadLastState()
     	if (mainW > Fl::w()) mainW = Fl::w();
     
     	spref.get("main_h", mainH, mainH);
    -	if (mainH < HMIN) mainH = HMIN;
    +//	if (mainH < HMIN) mainH = HMIN;
     	if (mainH > Fl::w()) mainH = Fl::h();
     
     	spref.get("wf_ui", i, WF_UI); WF_UI = i;
    @@ -561,6 +580,7 @@ void status::loadLastState()
     	spref.get("rigcontest_ui", i, Rig_Contest_UI); Rig_Contest_UI = i;
     	spref.get("noriglog", i, NO_RIGLOG); NO_RIGLOG = i;
     	spref.get("docked_scope", i, DOCKEDSCOPE); DOCKEDSCOPE = i;
    +	spref.get("tbar_is_docked", i, tbar_is_docked); tbar_is_docked = i;
     
     	spref.get("rigctl_x", rigX, rigX);
     	spref.get("rigctl_y", rigY, rigY);
    @@ -585,7 +605,9 @@ void status::loadLastState()
     	spref.get("tile_y", tile_y, tile_y);
     	spref.get("tile_w", tile_w, tile_w);
     	spref.get("tile_h", tile_h, tile_h);
    +	spref.get("tile_y_ratio", tile_y_ratio, tile_y_ratio);
     	spref.get("fsq_ratio", fsq_ratio, fsq_ratio);
    +	spref.get("ifkp_ratio", ifkp_ratio, ifkp_ratio);
     
     	spref.get("scope_visible", i, scopeVisible); scopeVisible = i;
     	spref.get("scope_x", scopeX, scopeX);
    @@ -691,7 +713,7 @@ void status::loadLastState()
     		spref.get("kiss_dual_port_enabled", i, kiss_dual_port_enabled); kiss_dual_port_enabled     = i;
     	}
     
    -	if(override_data_io_enabled != DISABLED_IO)
    +	if(!override_data_io_enabled)
     		spref.get("data_io_enabled", i, data_io_enabled); data_io_enabled = i;
     
     	spref.get("ax25_decode_enabled",    i, ax25_decode_enabled);    ax25_decode_enabled = i;
    @@ -699,6 +721,12 @@ void status::loadLastState()
     	spref.get("busyChannelSeconds",     i, busyChannelSeconds);     busyChannelSeconds  = i;
     	spref.get("kpsql_attenuation",      i, kpsql_attenuation);      kpsql_attenuation   = i;
     	spref.get("csma_enabled",           i, csma_enabled);           csma_enabled        = i;
    +	spref.get("kiss_tcp_io",            i, kiss_tcp_io);            kiss_tcp_io         = i;
    +	spref.get("kiss_tcp_listen",        i, kiss_tcp_listen);        kiss_tcp_listen     = i;
    +    spref.get("kpsql_enabled",          i, kpsql_enabled);          kpsql_enabled       = i;
    +    spref.get("kiss_io_modem_change_inhibit", i, kiss_io_modem_change_inhibit); kiss_io_modem_change_inhibit = i;
    +
    +	spref.get("psk8DCDShortFlag",       i, psk8DCDShortFlag);       psk8DCDShortFlag    = i;
     
     	memset(strbuff, 0, sizeof(strbuff));
     	spref.get("browser_search", strbuff, browser_search.c_str(), sizeof(strbuff) - 1);
    @@ -810,13 +838,13 @@ void status::initLastState()
     		data_io_enabled = ARQ_IO;
     		progdefaults.data_io_enabled = ARQ_IO;
     		progStatus.data_io_enabled = ARQ_IO;
    -		pwrsqlonoff = false;
    +		kpsql_enabled = false;
     	}
     
     	btnSQL->value(sqlonoff);
    -	btnPSQL->value(pwrsqlonoff);
    +	btnPSQL->value(kpsql_enabled);
     
    -	if(pwrsqlonoff)
    +	if(kpsql_enabled)
     		sldrSquelch->value(sldrPwrSquelchValue);
     	else
     		sldrSquelch->value(sldrSquelchValue);
    @@ -864,6 +892,8 @@ void status::initLastState()
     	cntKPSQLAttenuation->value(kpsql_attenuation);
     	progdefaults.kpsql_attenuation = kpsql_attenuation;
     
    +	kiss_io_set_button_state(0);
    +
     	if (bWF_only)
     		fl_digi_main->resize(mainX, mainY, mainW, Hmenu + Hwfall + Hstatus);
     	else if (bHAB) {
    @@ -887,7 +917,8 @@ void status::initLastState()
     
     	if (scopeview) {
     		scopeview->resize(scopeX, scopeY, scopeW, scopeH);
    -		if (scopeVisible == true)
    +		digiscope->resize(0,0,scopeW,scopeH);
    +		if (scopeVisible)
     			scopeview->show();
     	}
     
    diff --git a/src/misc/xmlrpc.cxx b/src/misc/xmlrpc.cxx
    index 884e9849..98dfe62b 100644
    --- a/src/misc/xmlrpc.cxx
    +++ b/src/misc/xmlrpc.cxx
    @@ -40,19 +40,18 @@
     #include 
     #include 
     #include 
    -
     #include 
     
    -#include 
    -#include 
    -#include 
    +#include "threads.h"
    +
    +class XmlRpcImpl;
     
     #include "globals.h"
     #include "configuration.h"
     #ifdef HAVE_VALUES_H
     #	include 
     #endif
    -#include "threads.h"
    +
     #include "modem.h"
     #include "trx.h"
     #include "fl_digi.h"
    @@ -197,9 +196,9 @@ struct XmlRpcImpl : public XmlRpcServer
     	/// BEWARE IT IS CALLED FROM ANOTHER THREAD.
     	void close()
     	{
    -		LOG_INFO("Stopping XML-RPC server");
     		exit();
     		shutdown();
    +		LOG_INFO("XMLRPC server loop terminated");
     	}
     };
     
    @@ -213,8 +212,8 @@ struct rpc_method
     typedef list methods_t;
     static methods_t* methods = 0;
     
    -static pthread_t* server_thread;
    -static pthread_mutex_t* server_mutex;
    +pthread_t* server_thread;
    +pthread_mutex_t* server_mutex;
     
     XML_RPC_Server* XML_RPC_Server::inst = 0;
     
    @@ -1004,13 +1003,14 @@ public:
     			return;
     		}
     
    -		if (progdefaults.chkUSERIGCATis)
    -			rigCAT_setmode(s);
    -#if USE_HAMLIB
    -		else if (progdefaults.chkUSEHAMLIBis)
    -			hamlib_setmode(s == "LSB" ? RIG_MODE_LSB : RIG_MODE_USB);
    -#endif
    -		else if (progdefaults.chkUSEXMLRPCis)
    +//		if (progdefaults.chkUSERIGCATis)
    +//			rigCAT_setmode(s);
    +//#if USE_HAMLIB
    +//		else if (progdefaults.chkUSEHAMLIBis)
    +//			hamlib_setmode(s == "LSB" ? RIG_MODE_LSB : RIG_MODE_USB);
    +//#endif
    +//		else 
    +//		if (progdefaults.chkUSEXMLRPCis)
     			REQ(static_cast(&waterfall::USB), wf, s == "USB");
     
     		*retval = xmlrpc_c::value_nil();
    @@ -1571,6 +1571,83 @@ public:
     	}
     };
     
    +//----------------------------------------------------------------------
    +// flmsg i/o
    +//----------------------------------------------------------------------
    +bool flmsg_online = false;
    +void flmsg_defeat(void *)
    +{
    +	flmsg_online = false;
    +}
    +
    +class Main_flmsg_online : public xmlrpc_c::method
    +{
    +public:
    +	Main_flmsg_online()
    +	{
    +		_signature = "n:n";
    +		_help = "flmsg online indication";
    +	}
    +	void execute(const xmlrpc_c::paramList& params, xmlrpc_c::value* retval)
    +	{
    +		XMLRPC_LOCK;
    +		flmsg_online = true;
    +		Fl::remove_timeout(flmsg_defeat);
    +		Fl::add_timeout(0.5, flmsg_defeat);
    +	}
    +};
    +
    +string flmsg_data;
    +
    +class Main_flmsg_available : public xmlrpc_c::method
    +{
    +public:
    +	Main_flmsg_available()
    +	{
    +		_signature = "n:n";
    +		_help = "flmsg data available";
    +	}
    +	void execute(const xmlrpc_c::paramList& params, xmlrpc_c::value* retval)
    +	{
    +		XMLRPC_LOCK;
    +		int data_ready = (int)flmsg_data.size();
    +		*retval = xmlrpc_c::value_int(data_ready);
    +	}
    +};
    +
    +class Main_flmsg_transfer : public xmlrpc_c::method
    +{
    +public:
    +	Main_flmsg_transfer()
    +	{
    +		_signature = "n:n";
    +		_help = "data transfer to flmsg";
    +	}
    +	void execute(const xmlrpc_c::paramList& params, xmlrpc_c::value* retval)
    +	{
    +		XMLRPC_LOCK;
    +		string tempstr = flmsg_data;
    +		*retval = xmlrpc_c::value_string(tempstr);
    +		flmsg_data.clear();
    +	}
    +};
    +
    +class Main_flmsg_squelch : public xmlrpc_c::method
    +{
    +public:
    +	Main_flmsg_squelch()
    +	{
    +		_signature = "b:n";
    +		_help = "Returns the squelch state.";
    +	}
    +	void execute(const xmlrpc_c::paramList& params, xmlrpc_c::value* retval)
    +	{
    +		*retval = xmlrpc_c::value_boolean(active_modem->get_metric() > progStatus.sldrSquelchValue);
    +	}
    +};
    +
    +//----------------------------------------------------------------------
    +
     class Main_run_macro : public xmlrpc_c::method
     {
     public:
    @@ -1647,12 +1724,30 @@ public:
     static string xmlchars;
     bool xmltest_char_available;
     static size_t pxmlchar = 0;
    +static char xml_status_msg[50];
     int xmltest_char()
     {
    -	if (pxmlchar >= xmlchars.length() ) return -3;
    +	if (xmlchars.empty() || !xmltest_char_available)
    +		return 0;
    +	if (pxmlchar >= xmlchars.length() ) {
    +		xmlchars.clear();
    +		pxmlchar = 0;
    +		xmltest_char_available = false;
    +		return -3;
    +	}
    +	snprintf(xml_status_msg, sizeof(xml_status_msg), "%d%% sent",
    +		100*pxmlchar/xmlchars.length());
    +	put_status(xml_status_msg, 1.0);
     	return xmlchars[pxmlchar++] & 0xFF;
     }
     
    +void reset_xmlchars()
    +{
    +	xmlchars.clear();
    +	pxmlchar = 0;
    +	xmltest_char_available = false;
    +}
    +
     int number_of_samples( string s)
     {
     	active_modem->XMLRPC_CPS_TEST = true;
    @@ -2855,6 +2950,25 @@ public:
     	}
     };
     
    +class Text_add_tx_queu : public xmlrpc_c::method
    +{
    +public:
    +	Text_add_tx_queu()
    +	{
    +		_signature = "n:s";
    +		_help = "Adds a string to the TX transmit queu.";
    +	}
    +	void execute(const xmlrpc_c::paramList& params, xmlrpc_c::value* retval)
    +	{
    +		XMLRPC_LOCK;
    +		xmlchars = params.getString(0);
    +		xmltest_char_available = true;
    +		pxmlchar = 0;
    +		*retval = xmlrpc_c::value_nil();
    +	}
    +};
    +
    +
     class Text_add_tx : public xmlrpc_c::method
     {
     public:
    @@ -3311,192 +3425,198 @@ struct Navtex_send_message : public xmlrpc_c::method
     
     // method list: ELEM_(class_name, "method_name")
     #undef ELEM_
    -#define METHOD_LIST														\
    -ELEM_(Fldigi_list, "fldigi.list")									\
    -ELEM_(Fldigi_name, "fldigi.name")									\
    -ELEM_(Fldigi_version_struct, "fldigi.version_struct")			\
    -ELEM_(Fldigi_version_string, "fldigi.version")					\
    -ELEM_(Fldigi_name_version, "fldigi.name_version")					\
    -ELEM_(Fldigi_config_dir, "fldigi.config_dir")						\
    -ELEM_(Fldigi_terminate, "fldigi.terminate")						\
    +#define METHOD_LIST                                                    \
    +ELEM_(Fldigi_list, "fldigi.list")                                      \
    +ELEM_(Fldigi_name, "fldigi.name")                                      \
    +ELEM_(Fldigi_version_struct, "fldigi.version_struct")                  \
    +ELEM_(Fldigi_version_string, "fldigi.version")                         \
    +ELEM_(Fldigi_name_version, "fldigi.name_version")                      \
    +ELEM_(Fldigi_config_dir, "fldigi.config_dir")                          \
    +ELEM_(Fldigi_terminate, "fldigi.terminate")                            \
     \
    -ELEM_(Modem_get_name, "modem.get_name")							\
    -ELEM_(Modem_get_names, "modem.get_names")							\
    -ELEM_(Modem_get_id, "modem.get_id")								\
    -ELEM_(Modem_get_max_id, "modem.get_max_id")						\
    -ELEM_(Modem_set_by_name, "modem.set_by_name")						\
    -ELEM_(Modem_set_by_id, "modem.set_by_id")							\
    +ELEM_(Modem_get_name, "modem.get_name")                                \
    +ELEM_(Modem_get_names, "modem.get_names")                              \
    +ELEM_(Modem_get_id, "modem.get_id")                                    \
    +ELEM_(Modem_get_max_id, "modem.get_max_id")                            \
    +ELEM_(Modem_set_by_name, "modem.set_by_name")                          \
    +ELEM_(Modem_set_by_id, "modem.set_by_id")                              \
     \
    -ELEM_(Modem_set_carrier, "modem.set_carrier")						\
    -ELEM_(Modem_inc_carrier, "modem.inc_carrier")						\
    -ELEM_(Modem_get_carrier, "modem.get_carrier")						\
    +ELEM_(Modem_set_carrier, "modem.set_carrier")                          \
    +ELEM_(Modem_inc_carrier, "modem.inc_carrier")                          \
    +ELEM_(Modem_get_carrier, "modem.get_carrier")                          \
     \
    -ELEM_(Modem_get_afc_sr, "modem.get_afc_search_range")				\
    -ELEM_(Modem_set_afc_sr, "modem.set_afc_search_range")				\
    -ELEM_(Modem_inc_afc_sr, "modem.inc_afc_search_range")				\
    +ELEM_(Modem_get_afc_sr, "modem.get_afc_search_range")                  \
    +ELEM_(Modem_set_afc_sr, "modem.set_afc_search_range")                  \
    +ELEM_(Modem_inc_afc_sr, "modem.inc_afc_search_range")                  \
     \
    -ELEM_(Modem_get_bw, "modem.get_bandwidth")							\
    -ELEM_(Modem_set_bw, "modem.set_bandwidth")							\
    -ELEM_(Modem_inc_bw, "modem.inc_bandwidth")							\
    +ELEM_(Modem_get_bw, "modem.get_bandwidth")                             \
    +ELEM_(Modem_set_bw, "modem.set_bandwidth")                             \
    +ELEM_(Modem_inc_bw, "modem.inc_bandwidth")                             \
     \
    -ELEM_(Modem_get_quality, "modem.get_quality")						\
    -ELEM_(Modem_search_up, "modem.search_up")							\
    -ELEM_(Modem_search_down, "modem.search_down")						\
    +ELEM_(Modem_get_quality, "modem.get_quality")                          \
    +ELEM_(Modem_search_up, "modem.search_up")                              \
    +ELEM_(Modem_search_down, "modem.search_down")                          \
     \
    -ELEM_(Modem_olivia_set_bandwidth, "modem.olivia.set_bandwidth")	\
    -ELEM_(Modem_olivia_get_bandwidth, "modem.olivia.get_bandwidth")	\
    -ELEM_(Modem_olivia_set_tones, "modem.olivia.set_tones")			\
    -ELEM_(Modem_olivia_get_tones, "modem.olivia.get_tones")			\
    +ELEM_(Modem_olivia_set_bandwidth, "modem.olivia.set_bandwidth")        \
    +ELEM_(Modem_olivia_get_bandwidth, "modem.olivia.get_bandwidth")        \
    +ELEM_(Modem_olivia_set_tones, "modem.olivia.set_tones")                \
    +ELEM_(Modem_olivia_get_tones, "modem.olivia.get_tones")                \
     \
    -ELEM_(Main_get_status1, "main.get_status1")						\
    -ELEM_(Main_get_status2, "main.get_status2")						\
    +ELEM_(Main_get_status1, "main.get_status1")                            \
    +ELEM_(Main_get_status2, "main.get_status2")                            \
     \
    -ELEM_(Main_get_sb, "main.get_sideband")							\
    -ELEM_(Main_set_sb, "main.set_sideband")							\
    -ELEM_(Main_get_wf_sideband, "main.get_wf_sideband")				\
    -ELEM_(Main_set_wf_sideband, "main.set_wf_sideband")				\
    -ELEM_(Main_get_freq, "main.get_frequency")						\
    -ELEM_(Main_set_freq, "main.set_frequency")						\
    -ELEM_(Main_inc_freq, "main.inc_frequency")						\
    +ELEM_(Main_get_sb, "main.get_sideband")                                \
    +ELEM_(Main_set_sb, "main.set_sideband")                                \
    +ELEM_(Main_get_wf_sideband, "main.get_wf_sideband")                    \
    +ELEM_(Main_set_wf_sideband, "main.set_wf_sideband")                    \
    +ELEM_(Main_get_freq, "main.get_frequency")                             \
    +ELEM_(Main_set_freq, "main.set_frequency")                             \
    +ELEM_(Main_inc_freq, "main.inc_frequency")                             \
     \
    -ELEM_(Main_get_afc, "main.get_afc")								\
    -ELEM_(Main_set_afc, "main.set_afc")								\
    -ELEM_(Main_toggle_afc, "main.toggle_afc")							\
    +ELEM_(Main_get_afc, "main.get_afc")                                    \
    +ELEM_(Main_set_afc, "main.set_afc")                                    \
    +ELEM_(Main_toggle_afc, "main.toggle_afc")                              \
     \
    -ELEM_(Main_get_sql, "main.get_squelch")							\
    -ELEM_(Main_set_sql, "main.set_squelch")							\
    -ELEM_(Main_toggle_sql, "main.toggle_squelch")						\
    +ELEM_(Main_get_sql, "main.get_squelch")                                \
    +ELEM_(Main_set_sql, "main.set_squelch")                                \
    +ELEM_(Main_toggle_sql, "main.toggle_squelch")                          \
     \
    -ELEM_(Main_get_sql_level, "main.get_squelch_level")				\
    -ELEM_(Main_set_sql_level, "main.set_squelch_level")				\
    -ELEM_(Main_inc_sql_level, "main.inc_squelch_level")				\
    +ELEM_(Main_get_sql_level, "main.get_squelch_level")                    \
    +ELEM_(Main_set_sql_level, "main.set_squelch_level")                    \
    +ELEM_(Main_inc_sql_level, "main.inc_squelch_level")                    \
     \
    -ELEM_(Main_get_rev, "main.get_reverse")							\
    -ELEM_(Main_set_rev, "main.set_reverse")							\
    -ELEM_(Main_toggle_rev, "main.toggle_reverse")						\
    +ELEM_(Main_get_rev, "main.get_reverse")                                \
    +ELEM_(Main_set_rev, "main.set_reverse")                                \
    +ELEM_(Main_toggle_rev, "main.toggle_reverse")                          \
     \
    -ELEM_(Main_get_lock, "main.get_lock")								\
    -ELEM_(Main_set_lock, "main.set_lock")								\
    -ELEM_(Main_toggle_lock, "main.toggle_lock")						\
    +ELEM_(Main_get_lock, "main.get_lock")                                  \
    +ELEM_(Main_set_lock, "main.set_lock")                                  \
    +ELEM_(Main_toggle_lock, "main.toggle_lock")                            \
     \
    -ELEM_(Main_get_txid, "main.get_txid")								\
    -ELEM_(Main_set_txid, "main.set_txid")								\
    -ELEM_(Main_toggle_txid, "main.toggle_txid")						\
    +ELEM_(Main_get_txid, "main.get_txid")                                  \
    +ELEM_(Main_set_txid, "main.set_txid")                                  \
    +ELEM_(Main_toggle_txid, "main.toggle_txid")                            \
     \
    -ELEM_(Main_get_rsid, "main.get_rsid")								\
    -ELEM_(Main_set_rsid, "main.set_rsid")								\
    -ELEM_(Main_toggle_rsid, "main.toggle_rsid")						\
    +ELEM_(Main_get_rsid, "main.get_rsid")                                  \
    +ELEM_(Main_set_rsid, "main.set_rsid")                                  \
    +ELEM_(Main_toggle_rsid, "main.toggle_rsid")                            \
     \
    -ELEM_(Main_get_trx_status, "main.get_trx_status")					\
    -ELEM_(Main_tx, "main.tx")											\
    -ELEM_(Main_tune, "main.tune")										\
    -ELEM_(Main_rsid, "main.rsid")										\
    -ELEM_(Main_rx, "main.rx")											\
    -ELEM_(Main_rx_tx, "main.rx_tx")									\
    -ELEM_(Main_rx_only, "main.rx_only")								\
    -ELEM_(Main_abort, "main.abort")									\
    +ELEM_(Main_get_trx_status, "main.get_trx_status")                      \
    +ELEM_(Main_tx, "main.tx")                                              \
    +ELEM_(Main_tune, "main.tune")                                          \
    +ELEM_(Main_rsid, "main.rsid")                                          \
    +ELEM_(Main_rx, "main.rx")                                              \
    +ELEM_(Main_rx_tx, "main.rx_tx")                                        \
    +ELEM_(Main_rx_only, "main.rx_only")                                    \
    +ELEM_(Main_abort, "main.abort")                                        \
     \
    -ELEM_(Main_get_trx_state, "main.get_trx_state")					\
    -ELEM_(Main_get_tx_timing, "main.get_tx_timing")					\
    -ELEM_(Main_get_char_rates, "main.get_char_rates")					\
    -ELEM_(Main_get_char_timing, "main.get_char_timing")				\
    -ELEM_(Main_set_rig_name, "main.set_rig_name")						\
    -ELEM_(Main_set_rig_frequency, "main.set_rig_frequency")			\
    -ELEM_(Main_set_rig_modes, "main.set_rig_modes")					\
    -ELEM_(Main_set_rig_mode, "main.set_rig_mode")						\
    -ELEM_(Main_get_rig_modes, "main.get_rig_modes")					\
    -ELEM_(Main_get_rig_mode, "main.get_rig_mode")						\
    -ELEM_(Main_set_rig_bandwidths, "main.set_rig_bandwidths")		\
    -ELEM_(Main_set_rig_bandwidth, "main.set_rig_bandwidth")			\
    -ELEM_(Main_get_rig_bandwidth, "main.get_rig_bandwidth")			\
    -ELEM_(Main_get_rig_bandwidths, "main.get_rig_bandwidths")		\
    +ELEM_(Main_get_trx_state, "main.get_trx_state")                        \
    +ELEM_(Main_get_tx_timing, "main.get_tx_timing")                        \
    +ELEM_(Main_get_char_rates, "main.get_char_rates")                      \
    +ELEM_(Main_get_char_timing, "main.get_char_timing")                    \
    +ELEM_(Main_set_rig_name, "main.set_rig_name")                          \
    +ELEM_(Main_set_rig_frequency, "main.set_rig_frequency")                \
    +ELEM_(Main_set_rig_modes, "main.set_rig_modes")                        \
    +ELEM_(Main_set_rig_mode, "main.set_rig_mode")                          \
    +ELEM_(Main_get_rig_modes, "main.get_rig_modes")                        \
    +ELEM_(Main_get_rig_mode, "main.get_rig_mode")                          \
    +ELEM_(Main_set_rig_bandwidths, "main.set_rig_bandwidths")              \
    +ELEM_(Main_set_rig_bandwidth, "main.set_rig_bandwidth")                \
    +ELEM_(Main_get_rig_bandwidth, "main.get_rig_bandwidth")                \
    +ELEM_(Main_get_rig_bandwidths, "main.get_rig_bandwidths")              \
     \
    -ELEM_(Main_run_macro, "main.run_macro")							\
    -ELEM_(Main_get_max_macro_id, "main.get_max_macro_id")			\
    +ELEM_(Main_run_macro, "main.run_macro")                                \
    +ELEM_(Main_get_max_macro_id, "main.get_max_macro_id")                  \
     \
    -ELEM_(Rig_set_name, "rig.set_name")								\
    -ELEM_(Rig_get_name, "rig.get_name")								\
    -ELEM_(Rig_set_frequency, "rig.set_frequency")						\
    -ELEM_(Rig_set_smeter, "rig.set_smeter")							\
    -ELEM_(Rig_set_pwrmeter, "rig.set_pwrmeter")						\
    -ELEM_(Rig_set_modes, "rig.set_modes")								\
    -ELEM_(Rig_set_mode, "rig.set_mode")								\
    -ELEM_(Rig_get_modes, "rig.get_modes")								\
    -ELEM_(Rig_get_mode, "rig.get_mode")								\
    -ELEM_(Rig_set_bandwidths, "rig.set_bandwidths")					\
    -ELEM_(Rig_set_bandwidth, "rig.set_bandwidth")						\
    -ELEM_(Rig_get_freq, "rig.get_frequency")							\
    -ELEM_(Rig_get_bandwidth, "rig.get_bandwidth")						\
    -ELEM_(Rig_get_bandwidths, "rig.get_bandwidths")					\
    -ELEM_(Rig_get_notch, "rig.get_notch")								\
    -ELEM_(Rig_set_notch, "rig.set_notch")								\
    -ELEM_(Rig_take_control, "rig.take_control")						\
    -ELEM_(Rig_release_control, "rig.release_control")					\
    +ELEM_(Rig_set_name, "rig.set_name")                                    \
    +ELEM_(Rig_get_name, "rig.get_name")                                    \
    +ELEM_(Rig_set_frequency, "rig.set_frequency")                          \
    +ELEM_(Rig_set_smeter, "rig.set_smeter")                                \
    +ELEM_(Rig_set_pwrmeter, "rig.set_pwrmeter")                            \
    +ELEM_(Rig_set_modes, "rig.set_modes")                                  \
    +ELEM_(Rig_set_mode, "rig.set_mode")                                    \
    +ELEM_(Rig_get_modes, "rig.get_modes")                                  \
    +ELEM_(Rig_get_mode, "rig.get_mode")                                    \
    +ELEM_(Rig_set_bandwidths, "rig.set_bandwidths")                        \
    +ELEM_(Rig_set_bandwidth, "rig.set_bandwidth")                          \
    +ELEM_(Rig_get_freq, "rig.get_frequency")                               \
    +ELEM_(Rig_get_bandwidth, "rig.get_bandwidth")                          \
    +ELEM_(Rig_get_bandwidths, "rig.get_bandwidths")                        \
    +ELEM_(Rig_get_notch, "rig.get_notch")                                  \
    +ELEM_(Rig_set_notch, "rig.set_notch")                                  \
    +ELEM_(Rig_take_control, "rig.take_control")                            \
    +ELEM_(Rig_release_control, "rig.release_control")                      \
     \
    -ELEM_(Log_get_freq, "log.get_frequency")							\
    -ELEM_(Log_get_time_on, "log.get_time_on")							\
    -ELEM_(Log_get_time_off, "log.get_time_off")						\
    -ELEM_(Log_get_call, "log.get_call")								\
    -ELEM_(Log_get_name, "log.get_name")								\
    -ELEM_(Log_get_rst_in, "log.get_rst_in")							\
    -ELEM_(Log_get_rst_out, "log.get_rst_out")							\
    -ELEM_(Log_set_rst_in, "log.set_rst_in")							\
    -ELEM_(Log_set_rst_out, "log.set_rst_out")							\
    -ELEM_(Log_get_serial_number, "log.get_serial_number")			\
    -ELEM_(Log_set_serial_number, "log.set_serial_number")			\
    -ELEM_(Log_get_serial_number_sent, "log.get_serial_number_sent")	\
    -ELEM_(Log_get_exchange, "log.get_exchange")						\
    -ELEM_(Log_set_exchange, "log.set_exchange")						\
    -ELEM_(Log_get_state, "log.get_state")								\
    -ELEM_(Log_get_province, "log.get_province")						\
    -ELEM_(Log_get_country, "log.get_country")							\
    -ELEM_(Log_get_qth, "log.get_qth")									\
    -ELEM_(Log_get_band, "log.get_band")								\
    -ELEM_(Log_get_sb, "log.get_sideband")								\
    -ELEM_(Log_get_notes, "log.get_notes")								\
    -ELEM_(Log_get_locator, "log.get_locator")							\
    -ELEM_(Log_get_az, "log.get_az")									\
    -ELEM_(Log_clear, "log.clear")										\
    -ELEM_(Log_set_call, "log.set_call")								\
    -ELEM_(Log_set_name, "log.set_name")								\
    -ELEM_(Log_set_qth, "log.set_qth")									\
    -ELEM_(Log_set_locator, "log.set_locator")							\
    -ELEM_(Log_set_rst_in, "log.set_rst_in")							\
    -ELEM_(Log_set_rst_out, "log.set_rst_out")							\
    +ELEM_(Log_get_freq, "log.get_frequency")                               \
    +ELEM_(Log_get_time_on, "log.get_time_on")                              \
    +ELEM_(Log_get_time_off, "log.get_time_off")                            \
    +ELEM_(Log_get_call, "log.get_call")                                    \
    +ELEM_(Log_get_name, "log.get_name")                                    \
    +ELEM_(Log_get_rst_in, "log.get_rst_in")                                \
    +ELEM_(Log_get_rst_out, "log.get_rst_out")                              \
    +ELEM_(Log_set_rst_in, "log.set_rst_in")                                \
    +ELEM_(Log_set_rst_out, "log.set_rst_out")                              \
    +ELEM_(Log_get_serial_number, "log.get_serial_number")                  \
    +ELEM_(Log_set_serial_number, "log.set_serial_number")                  \
    +ELEM_(Log_get_serial_number_sent, "log.get_serial_number_sent")        \
    +ELEM_(Log_get_exchange, "log.get_exchange")                            \
    +ELEM_(Log_set_exchange, "log.set_exchange")                            \
    +ELEM_(Log_get_state, "log.get_state")                                  \
    +ELEM_(Log_get_province, "log.get_province")                            \
    +ELEM_(Log_get_country, "log.get_country")                              \
    +ELEM_(Log_get_qth, "log.get_qth")                                      \
    +ELEM_(Log_get_band, "log.get_band")                                    \
    +ELEM_(Log_get_sb, "log.get_sideband")                                  \
    +ELEM_(Log_get_notes, "log.get_notes")                                  \
    +ELEM_(Log_get_locator, "log.get_locator")                              \
    +ELEM_(Log_get_az, "log.get_az")                                        \
    +ELEM_(Log_clear, "log.clear")                                          \
    +ELEM_(Log_set_call, "log.set_call")                                    \
    +ELEM_(Log_set_name, "log.set_name")                                    \
    +ELEM_(Log_set_qth, "log.set_qth")                                      \
    +ELEM_(Log_set_locator, "log.set_locator")                              \
    +ELEM_(Log_set_rst_in, "log.set_rst_in")                                \
    +ELEM_(Log_set_rst_out, "log.set_rst_out")                              \
     \
    -ELEM_(Io_in_use, "io.in_use")	          						\
    -ELEM_(Io_enable_kiss, "io.enable_kiss")							\
    -ELEM_(Io_enable_arq, "io.enable_arq")							\
    +ELEM_(Main_flmsg_online, "main.flmsg_online")                          \
    +ELEM_(Main_flmsg_available, "main.flmsg_available")                    \
    +ELEM_(Main_flmsg_transfer, "main.flmsg_transfer")                      \
    +ELEM_(Main_flmsg_squelch, "main.flmsg_squelch")                        \
     \
    -ELEM_(Text_get_rx_length, "text.get_rx_length")					\
    -ELEM_(Text_get_rx, "text.get_rx")								\
    -ELEM_(Text_clear_rx, "text.clear_rx")							\
    -ELEM_(Text_add_tx, "text.add_tx")								\
    -ELEM_(Text_add_tx_bytes, "text.add_tx_bytes")					\
    -ELEM_(Text_clear_tx, "text.clear_tx")							\
    +ELEM_(Io_in_use, "io.in_use")                                          \
    +ELEM_(Io_enable_kiss, "io.enable_kiss")                                \
    +ELEM_(Io_enable_arq, "io.enable_arq")                                  \
     \
    -ELEM_(RXTX_get_data, "rxtx.get_data")							\
    -ELEM_(RX_get_data, "rx.get_data")								\
    -ELEM_(TX_get_data, "tx.get_data")								\
    +ELEM_(Text_get_rx_length, "text.get_rx_length")                        \
    +ELEM_(Text_get_rx, "text.get_rx")                                      \
    +ELEM_(Text_clear_rx, "text.clear_rx")                                  \
    +ELEM_(Text_add_tx, "text.add_tx")                                      \
    +ELEM_(Text_add_tx_queu, "text.add_tx_queu")                            \
    +ELEM_(Text_add_tx_bytes, "text.add_tx_bytes")                          \
    +ELEM_(Text_clear_tx, "text.clear_tx")                                  \
     \
    -ELEM_(Spot_get_auto, "spot.get_auto")								\
    -ELEM_(Spot_set_auto, "spot.set_auto")								\
    -ELEM_(Spot_toggle_auto, "spot.toggle_auto")						\
    -ELEM_(Spot_pskrep_get_count, "spot.pskrep.get_count")			\
    +ELEM_(RXTX_get_data, "rxtx.get_data")                                  \
    +ELEM_(RX_get_data, "rx.get_data")                                      \
    +ELEM_(TX_get_data, "tx.get_data")                                      \
     \
    -ELEM_(Wefax_state_string, "wefax.state_string")					\
    -ELEM_(Wefax_skip_apt, "wefax.skip_apt")							\
    -ELEM_(Wefax_skip_phasing, "wefax.skip_phasing")					\
    -ELEM_(Wefax_set_tx_abort_flag, "wefax.set_tx_abort_flag")		\
    -ELEM_(Wefax_end_reception, "wefax.end_reception")					\
    -ELEM_(Wefax_start_manual_reception, "wefax.start_manual_reception")	\
    -ELEM_(Wefax_set_adif_log, "wefax.set_adif_log")					\
    -ELEM_(Wefax_set_max_lines, "wefax.set_max_lines")					\
    -ELEM_(Wefax_get_received_file, "wefax.get_received_file")		\
    -ELEM_(Wefax_send_file, "wefax.send_file")							\
    +ELEM_(Spot_get_auto, "spot.get_auto")                                  \
    +ELEM_(Spot_set_auto, "spot.set_auto")                                  \
    +ELEM_(Spot_toggle_auto, "spot.toggle_auto")                            \
    +ELEM_(Spot_pskrep_get_count, "spot.pskrep.get_count")                  \
     \
    -ELEM_(Navtex_get_message, "navtex.get_message")					\
    -ELEM_(Navtex_send_message, "navtex.send_message")					\
    +ELEM_(Wefax_state_string, "wefax.state_string")                        \
    +ELEM_(Wefax_skip_apt, "wefax.skip_apt")                                \
    +ELEM_(Wefax_skip_phasing, "wefax.skip_phasing")                        \
    +ELEM_(Wefax_set_tx_abort_flag, "wefax.set_tx_abort_flag")              \
    +ELEM_(Wefax_end_reception, "wefax.end_reception")                      \
    +ELEM_(Wefax_start_manual_reception, "wefax.start_manual_reception")    \
    +ELEM_(Wefax_set_adif_log, "wefax.set_adif_log")                        \
    +ELEM_(Wefax_set_max_lines, "wefax.set_max_lines")                      \
    +ELEM_(Wefax_get_received_file, "wefax.get_received_file")              \
    +ELEM_(Wefax_send_file, "wefax.send_file")                              \
    +\
    +ELEM_(Navtex_get_message, "navtex.get_message")                        \
    +ELEM_(Navtex_send_message, "navtex.send_message")                      \
     
     struct rm_pred
     {
    diff --git a/src/mt63/mt63.cxx b/src/mt63/mt63.cxx
    index f428b23d..3616999f 100644
    --- a/src/mt63/mt63.cxx
    +++ b/src/mt63/mt63.cxx
    @@ -76,9 +76,10 @@ int mt63::tx_process()
     			double w2 = 2.0 * M_PI * (get_txfreq_woffset() + 31.0 * bandwidth / 64.0) / samplerate;
     			double phi1 = 0.0;
     			double phi2 = 0.0;
    -			double buff[samplerate];
    -			for (int i = 0; i < progdefaults.mt63_tone_duration; i++) {
    -				for (int j = 0; j < samplerate; j++) {
    +			double buff[512];
    +			int numsmpls = samplerate * progdefaults.mt63_tone_duration / 512;
    +			for (int i = 0; i < numsmpls; i++) {
    +				for (int j = 0; j < 512; j++) {
     					buff[j] = TONE_AMP * (progdefaults.mt63_twotones ? 0.5 : 1.0) * cos(phi1) +
     							  TONE_AMP * (progdefaults.mt63_twotones ? 0.5 : 0.0) * cos(phi2);
     					phi1 += w1;
    @@ -88,7 +89,7 @@ int mt63::tx_process()
     						buff[j] *= (1.0 - exp(-1.0 * (samplerate - j) / 40.0));
     				}
     				Fl::awake();
    -				ModulateXmtr(buff, samplerate);
    +				ModulateXmtr(buff, 512);
     			}
     		}
     		for (int i = 0; i < Tx->DataInterleave; i++) {
    diff --git a/src/navtex/navtex.cxx b/src/navtex/navtex.cxx
    index 06c3b623..22470228 100644
    --- a/src/navtex/navtex.cxx
    +++ b/src/navtex/navtex.cxx
    @@ -1,11 +1,13 @@
    +// ---------------------------------------------------------------------
     //
    -//	navtex.cxx
    +//  navtex.cxx
     //
    -// Copyright (C) 2011
    -//		Remi Chateauneu, F4ECW
    +// Copyright (C) 2011-2016
    +//      Remi Chateauneu, F4ECW
    +//      Rik van Riel, AB1KW, 
     //
    -// This file is part of fldigi.  Adapted from code contained in JNX source code 
    -// distribution.
    +// This file is part of fldigi.  Adapted from code contained in JNX
    +// source code distribution.
     //  JNX Copyright (C) Paul Lutus
     // http://www.arachnoid.com/JNX/index.html
     //
    @@ -21,7 +23,156 @@
     //
     // You should have received a copy of the GNU General Public License
     // along with this program.  If not, see .
    -// ----------------------------------------------------------------------------
    +// ---------------------------------------------------------------------
    +
    +// ---------------------------------------------------------------------
    +// Sync using multicorrelator, instead of null crossings
    +//      Rik van Riel, AB1KW, 
    +//
    +// Null crossings are somewhat noisy, and the code to keep the navtex
    +// decoder in sync with the incoming signal using null crossings was
    +// rather fragile.
    +//
    +// Use a multicorrelator instead, which relies on the averaged magnitude
    +// of the signal accumulator to sync the decoder with the incoming signal.
    +//
    +// When debugging the code, the multicorrelator mostly corrects the
    +// modem forward in time, which can be explained by the fact that a
    +// bit takes 110.25 samples, while the code uses 110. When the NAVTEX
    +// transmitter is running at exactly 100 baud, one can expect to see
    +// the decoder get adjusted 25 times a second, to make up for the
    +// difference between 11000 and 11025.
    +//
    +// When multiple signals are on the air simultaneously, the null crossing
    +// code would often lose track of the signal. The multicorrelator seems
    +// to be more stable in this situation, though of course when both signals
    +// are close in strength things do not get decoded right.
    +//
    +// The signal sampling spread of 1/6 of the width of a bit was set through
    +// trial and error. A larger spread increases the signal difference between
    +// early, prompt, and late samples, but reduces the accumulator value seen
    +// by the demodulator. A smaller spread increases the accumulator value seen,
    +// but makes it harder to lock on in noisy conditions.
    +// ---------------------------------------------------------------------
    +
    +// ---------------------------------------------------------------------
    +// low pass mark & space individually
    +//      Rik van Riel, AB1KW, 
    +//
    +// Putting individual low pass filters on mark and space seems to
    +// result in an improved ability to overcome pulse noise, and decode
    +// weaker navtex signals.
    +//
    +// I have not found any signal where the performance of the codec
    +// got worse with this change.
    +// ---------------------------------------------------------------------
    +
    +// ---------------------------------------------------------------------
    +// Correct display metric
    +//      Rik van Riel, AB1KW, 
    +//
    +// The NAVTEX display_metric() function was buggy, in that decayavg
    +// returns the decayed value, but does not store it. It always put
    +// the current value in the metric, and kept avg_ratio at 0.0.
    +//
    +// This resulted in a somewhat chaotic, and not very useful metric
    +// display. Copy over the S/N calculation from the RTTY code, because
    +// that code seems to work well.
    +
    +// Also print the S/N in Status2, like the RTTY code and other modes
    +// do.
    +
    +// Copying over the RTTY S/N code wholesale might still not be
    +// enough, since the NAVTEX wave form appears to be somewhat
    +// different from RTTY.  However, at least we have something
    +// now, and the metric used for squelch seems to work again.
    +// ---------------------------------------------------------------------
    +
    +// ---------------------------------------------------------------------
    +// Correct display metric
    +//      Rik van Riel, AB1KW, 
    +//
    +// Widen afc filter for 'jump 90 Hz' code
    +//
    +// When the NAVTEX code spots a power imbalance of more than a factor
    +// 5 between mark and space, it will shift the frequency by 90 Hz.
    +// This is reported to help with some signals.
    +//
    +// However, it breaks with some other signals, which have a different
    +// spectral distribution between mark and space, with a spectrum looking
    +// something like this:
    +//
    +//                                        *
    +//                                        *
    +//                                        *
    +//                                       **
    +//     ******                           ***
    +//    ********                         ******
    +//   **********                       ********
    +//  ********************************************
    +// **********************************************
    +//
    +// In this spectrum, mark & space have a similar amount of energy,
    +// but that is only apparent when the comparison between them is
    +// done on a wider sample than 10 Hz.
    +//
    +// Sampling 30 Hz instead seems to result in a more stable AFC.
    +// ---------------------------------------------------------------------
    +
    +// ---------------------------------------------------------------------
    +// use exact bit length
    +//      Rik van Riel, AB1KW, 
    +//
    +// With a baud rate of 100 and a sample rate of 11025, the number
    +// of bits per sample is 110.25.  Approximating this with 110 bits
    +// per sample results in the decoder continuously chasing after the
    +// signal, and losing it more easily during transient noise or
    +// interference events.
    +//
    +// Simply changing the variable type from int to double makes life
    +// a little easier on the bit tracking code.
    +//
    +// The accumulator does not seem to care that it gets an extra sample
    +// every 4 bit periods.
    +// ---------------------------------------------------------------------
    +
    +// ---------------------------------------------------------------------
    +// improvements to the multi correlator
    +//      Rik van Riel, AB1KW, 
    +//
    +// While the multi correlator for bit sync was a nice improvement over
    +// the null crossing tracking, it did lose sync too easily in the presence
    +// of transient noise or interference, and was full of magic adjustments.
    +//
    +// Replace the magic adjustments with a calculation, which makes the multi
    +// correlator able to ride out transient noise or interference, and then
    +// make a larger adjustment all at once (if needed).
    +// ---------------------------------------------------------------------
    +
    +// ---------------------------------------------------------------------
    +// use same mark/space detector as RTTY modem
    +//      Rik van Riel, AB1KW, 
    +//
    +// Switch the NAVTEX modem over to the same mark/spac decoder, with W7AY's
    +// automatic threshold correction algorithm, like the RTTY modem uses.
    +//
    +// The noise subtraction is a little different than in the RTTY modem;
    +// the algorithm used in W7AY's code seems to work a little better with
    +// the noise present at 518 kHz, when compared to the algorithm used in
    +// the RTTY modem.
    +//
    +// I have compared this detector to a correlation detector; the latter
    +// appears to be a little more sensitive, which includes higher
    +// sensitivity to noise. With a 250 Hz filter on the radio, the
    +// correlation detector might be a little bit better, while with the
    +// filter on the radio opened up to 4kHz wide, this detector appears
    +// to be more robust.
    +//
    +// On signals with a large mark/space power imbalance, or where the power
    +// distribution in one of the two throws off the automatic frequency
    +// correction, this decoder is able to handle signals that neither of
    +// the alternatives tested does.
    +// ---------------------------------------------------------------------
     
     #include 
     #include 
    @@ -54,6 +205,7 @@
     #include "strutil.h"
     #include "kmlserver.h"
     #include "record_loader.h"
    +#include "fftfilt.h"
     
     #include "FL/fl_ask.H"
     
    @@ -91,7 +243,7 @@ public:
     		std::string input_str ;
     		if( ! std::getline( istrm, input_str ) ) return istrm ;
     		std::stringstream str_strm( input_str );
    -		
    +
     		if( read_until_delim( m_delim, str_strm, rec.m_country                 )
     		&&  read_until_delim( m_delim, str_strm  /* Country code */            )
     		&&  read_until_delim( m_delim, str_strm, rec.m_frequency               )
    @@ -105,7 +257,7 @@ public:
     
     		&& ( rec.m_coordinates.latitude().is_lon() == false  )
     		&& ( rec.m_coordinates.longitude().is_lon() == true  )
    -		) 
    +		)
     		{
     			return istrm ;
     		}
    @@ -132,9 +284,9 @@ class NavtexCatalog : public RecordLoader< NavtexCatalog >
     	/// Tells if this is a reasonable Navtex frequency.
     	static bool freq_acceptable( double freq )
     	{
    -		return	freq_close( freq, 490.0 )
    -		||	freq_close( freq, 518.0 )
    -		||	freq_close( freq, 4209.5 );
    +		return  freq_close( freq, 490.0 )
    +		||  freq_close( freq, 518.0 )
    +		||  freq_close( freq, 4209.5 );
     	}
     
     	void Clear() {
    @@ -212,7 +364,7 @@ public:
     		bool okFreq = freq_acceptable( freq );
     
     		//LOG_INFO("Operator Maidenhead=%s lon=%lf lat=%lf okFreq=%d Origin=%c",
    -		//	maidenhead.c_str(), coo.longitude().angle(), coo.latitude().angle(), okFreq, origin );
    +		//  maidenhead.c_str(), coo.longitude().angle(), coo.latitude().angle(), okFreq, origin );
     
     		for( CatalogType::const_iterator it = m_catalog.begin(), en = m_catalog.end(); it != en ; ++it )
     		{
    @@ -255,8 +407,8 @@ public:
     		// The first message only contains a string very similar to a radio station.
     		if( (begSolStr->first < 2) && ( nxtSolStr->first > 2 ) ) {
     			//LOG_INFO("Levenshtein beg=%lf beg_name=%s next=%lf next_name=%s",
    -			//	begSolStr->first, begSolStr->second->name().c_str(),
    -			//	nxtSolStr->first, nxtSolStr->second->name().c_str() );
    +			//  begSolStr->first, begSolStr->second->name().c_str(),
    +			//  nxtSolStr->first, nxtSolStr->second->name().c_str() );
     			return & (*begSolStr->second) ;
     		}
     
    @@ -269,8 +421,8 @@ public:
     		// Now we could search for a coordinate in the message, and we will keep the station which is the closest
     		// to this coordinate. We wish to do that anyway in order to map things in KML.
     		// Possible formats are -(This is experimental):
    - 		// 67-04.0N 032-25.7E
    - 		// 47-29'30N 003-16'00W
    +		// 67-04.0N 032-25.7E
    +		// 47-29'30N 003-16'00W
     		// 6930.1N 01729.9E
     		// 48-21'45N 004-31'45W
     		// 58-37N 003-32W
    @@ -306,127 +458,8 @@ public:
     	}
     }; // NavtexCatalog
     
    -/// Explanations here: http://www.arachnoid.com/BiQuadDesigner/index.html
    -class BiQuadraticFilter {
    -public:
    -	enum Type {
    -		BANDPASS, LOWPASS, HIGHPASS, NOTCH, PEAK, LOWSHELF, HIGHSHELF
    -	};
    -private:
    -	double m_a0, m_a1, m_a2, m_b0, m_b1, m_b2;
    -	double m_x1, m_x2, y, m_y1, m_y2;
    -	double m_gain_abs;
    -	Type   m_type;
    -	double m_center_freq;
    -	double m_sample_rate;
    -	double m_Q;
    -	double m_gainDB;
    -public:
    -	BiQuadraticFilter() {}
    -
    -	BiQuadraticFilter(Type type, double center_freq, double sample_rate, double Q, double gainDB = 0.0) {
    -		configure(type, center_freq, sample_rate, Q, gainDB);
    -	}
    -
    -	void configure(Type aType, double aCenter_freq, double aSample_rate, double aQ, double aGainDB = 0.0) {
    -		m_x1 = m_x2 = m_y1 = m_y2 = 0;
    -		aQ = (aQ == 0) ? 1e-9 : aQ;
    -		m_type = aType;
    -		m_sample_rate = aSample_rate;
    -		m_Q = aQ;
    -		m_gainDB = aGainDB;
    -		reconfigure(aCenter_freq);
    -	}
    -private:
    -	/// Allows parameter change while running
    -	void reconfigure(double cf) {
    -		m_center_freq = cf;
    -		// only used for peaking and shelving filters
    -		m_gain_abs = pow(10, m_gainDB / 40);
    -		double omega = 2 * M_PI * cf / m_sample_rate;
    -		double sn = sin(omega);
    -		double cs = cos(omega);
    -		double alpha = sn / (2 * m_Q);
    -		double beta = sqrt(m_gain_abs + m_gain_abs);
    -		switch (m_type) {
    -			case BANDPASS:
    -				m_b0 = alpha;
    -				m_b1 = 0;
    -				m_b2 = -alpha;
    -				m_a0 = 1 + alpha;
    -				m_a1 = -2 * cs;
    -				m_a2 = 1 - alpha;
    -				break;
    -			case LOWPASS:
    -				m_b0 = (1 - cs) / 2;
    -				m_b1 = 1 - cs;
    -				m_b2 = (1 - cs) / 2;
    -				m_a0 = 1 + alpha;
    -				m_a1 = -2 * cs;
    -				m_a2 = 1 - alpha;
    -				break;
    -			case HIGHPASS:
    -				m_b0 = (1 + cs) / 2;
    -				m_b1 = -(1 + cs);
    -				m_b2 = (1 + cs) / 2;
    -				m_a0 = 1 + alpha;
    -				m_a1 = -2 * cs;
    -				m_a2 = 1 - alpha;
    -				break;
    -			case NOTCH:
    -				m_b0 = 1;
    -				m_b1 = -2 * cs;
    -				m_b2 = 1;
    -				m_a0 = 1 + alpha;
    -				m_a1 = -2 * cs;
    -				m_a2 = 1 - alpha;
    -				break;
    -			case PEAK:
    -				m_b0 = 1 + (alpha * m_gain_abs);
    -				m_b1 = -2 * cs;
    -				m_b2 = 1 - (alpha * m_gain_abs);
    -				m_a0 = 1 + (alpha / m_gain_abs);
    -				m_a1 = -2 * cs;
    -				m_a2 = 1 - (alpha / m_gain_abs);
    -				break;
    -			case LOWSHELF:
    -				m_b0 = m_gain_abs * ((m_gain_abs + 1) - (m_gain_abs - 1) * cs + beta * sn);
    -				m_b1 = 2 * m_gain_abs * ((m_gain_abs - 1) - (m_gain_abs + 1) * cs);
    -				m_b2 = m_gain_abs * ((m_gain_abs + 1) - (m_gain_abs - 1) * cs - beta * sn);
    -				m_a0 = (m_gain_abs + 1) + (m_gain_abs - 1) * cs + beta * sn;
    -				m_a1 = -2 * ((m_gain_abs - 1) + (m_gain_abs + 1) * cs);
    -				m_a2 = (m_gain_abs + 1) + (m_gain_abs - 1) * cs - beta * sn;
    -				break;
    -			case HIGHSHELF:
    -				m_b0 = m_gain_abs * ((m_gain_abs + 1) + (m_gain_abs - 1) * cs + beta * sn);
    -				m_b1 = -2 * m_gain_abs * ((m_gain_abs - 1) + (m_gain_abs + 1) * cs);
    -				m_b2 = m_gain_abs * ((m_gain_abs + 1) + (m_gain_abs - 1) * cs - beta * sn);
    -				m_a0 = (m_gain_abs + 1) - (m_gain_abs - 1) * cs + beta * sn;
    -				m_a1 = 2 * ((m_gain_abs - 1) - (m_gain_abs + 1) * cs);
    -				m_a2 = (m_gain_abs + 1) - (m_gain_abs - 1) * cs - beta * sn;
    -				break;
    -		}
    -		/// Prescale filter constants
    -		m_b0 /= m_a0;
    -		m_b1 /= m_a0;
    -		m_b2 /= m_a0;
    -		m_a1 /= m_a0;
    -		m_a2 /= m_a0;
    -	}
    -public:
    -	/// Perform one filtering step
    -	double filter(double x) {
    -		y = m_b0 * x + m_b1 * m_x1 + m_b2 * m_x2 - m_a1 * m_y1 - m_a2 * m_y2;
    -		m_x2 = m_x1;
    -		m_x1 = x;
    -		m_y2 = m_y1;
    -		m_y1 = y;
    -		return (y);
    -	}
    -};
    -
     static const unsigned char code_to_ltrs[128] = {
    -	//0	1	2	3	4	5	6	7	8	9	a	b	c	d	e	f
    +	//0 1   2   3   4   5   6   7   8   9   a   b   c   d   e   f
     	'_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', // 0
     	'_', '_', '_', '_', '_', '_', '_', 'J', '_', '_', '_', 'F', '_', 'C', 'K', '_', // 1
     	'_', '_', '_', '_', '_', '_', '_', 'W', '_', '_', '_', 'Y', '_', 'P', 'Q', '_', // 2
    @@ -438,7 +471,7 @@ static const unsigned char code_to_ltrs[128] = {
     };
     
     static const unsigned char code_to_figs[128] = {
    -	//0	1	2	3	4	5	6	7	8	9	a	b	c	d	e	f
    +	//0 1   2   3   4   5   6   7   8   9   a   b   c   d   e   f
     	'_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', // 0
     	'_', '_', '_', '_', '_', '_', '_', '\'', '_', '_', '_', '!', '_', ':', '(', '_', // 1
     	'_', '_', '_', '_', '_', '_', '_', '2', '_', '_', '_', '6', '_', '0', '1', '_', // 2
    @@ -514,6 +547,20 @@ public:
     		return -code;
     	}
     
    +	int bytes_to_code(int *pos) {
    +		int code = 0;
    +		int i;
    +
    +		for (i = 0; i < 7; i++)
    +			code |= ((pos[i] > 0) << i);
    +		return code;
    +	}
    +
    +	int bytes_to_char(int *pos, int shift) {
    +		int code = bytes_to_code(pos);
    +		return code_to_char(code, shift);
    +	}
    +
     	// http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetNaive
     	/// Counting set bits, Brian Kernighan's way
     	static bool check_bits(int v) {
    @@ -525,6 +572,19 @@ public:
     		//printf("check_bits %d %d %c\n", bc, (int)code_to_ltrs[v], code_to_ltrs[v] );
     		return bc == 4;
     	}
    +
    +	// Is there a valid character in the next 7 ints?
    +	bool valid_char_at(int *pos) {
    +		int count = 0;
    +		int i;
    +
    +		for (i = 0; i < 7; i++)
    +			if (pos[i] > 0)
    +				count++;
    +
    +		return (count == 4);
    +	}
    +
     };
     
     /// This is temporary, to manipulate a multi-line string.
    @@ -589,9 +649,9 @@ private:
     				default  : if( chrSeen ) {
     						   if( wasDelim ) {
     							  newStr.append(new_line);
    -					   	   } else if( wasSpace ) {
    +						   } else if( wasSpace ) {
     							  newStr.push_back(' ');
    -					   	}
    +						}
     					   }
     					   wasDelim = false ;
     					   wasSpace = false ;
    @@ -631,7 +691,7 @@ public:
     
     		if (qlen >= header_len) {
     			const char * comp = & (*this)[ qlen - header_len ];
    -			if( 
    +			if(
     				(comp[0] == 'Z') &&
     				(comp[1] == 'C') &&
     				(comp[2] == 'Z') &&
    @@ -641,14 +701,14 @@ public:
     				isalnum(comp[6]) &&
     				isdigit(comp[7]) &&
     				isdigit(comp[8]) &&
    -				// (comp[9] == '\r') ) 
    +				// (comp[9] == '\r') )
     				(strchr( "\n\r", comp[9] ) ) ) {
     
     				/// This returns the garbage before the valid header.
     				// Garbage because the trailer could not be read, but maybe header OK.
     				ccir_message msg_cut(
     					substr( 0, size() - header_len ),
    -				       	m_origin,
    +						m_origin,
     					m_subject,
     					m_number );
     				m_origin  = comp[5];
    @@ -757,7 +817,7 @@ public:
     	} // display
     }; // ccir_message
     
    -static const int deviation_f = 90;
    +static const int deviation_f = 85;
     
     static const double dflt_center_freq = 1000.0 ;
     
    @@ -767,17 +827,16 @@ class navtex ;
     class navtex_implementation {
     
     	enum State {
    -		NOSIGNAL, SYNC_SETUP, SYNC1, SYNC2, READ_DATA
    +		NOSIGNAL, SYNC_SETUP, SYNC, READ_DATA
     	};
     
     	static const char * state_to_str( State s ) {
     		switch( s ) {
     			case NOSIGNAL  : return "NOSIGNAL";
     			case SYNC_SETUP: return "SYNC_SETUP";
    -			case SYNC1	 : return "SYNC1";
    -			case SYNC2	 : return "SYNC2";
    +			case SYNC   : return "SYNC";
     			case READ_DATA : return "READ_DATA";
    -			default		: return "Unknown" ;
    +			default     : return "Unknown" ;
     		}
     	}
     
    @@ -797,47 +856,47 @@ class navtex_implementation {
     
     	double                          m_metric ;
     
    -	CCIR476				m_ccir476;
    +	CCIR476             m_ccir476;
     	typedef std::list sync_chrs_type ;
    -	sync_chrs_type                  m_sync_chrs;
     	ccir_message                    m_curr_msg ;
     
    -	int					m_c1, m_c2, m_c3;
    -	static const int                 m_zero_crossings_divisor = 4;
    -	std::vector                 m_zero_crossings ;
    -	long                             m_zero_crossing_count;
    -	double				 m_message_time ;
    -	double				 m_signal_accumulator ;
    -	double				 m_mark_f, m_space_f;
    -	double				 m_audio_average ;
    -	double				 m_audio_average_tc;
    -	double				 m_audio_minimum ;
    -	double				 m_time_sec;
    +	double               m_message_time ;
    +	double               m_early_accumulator ;
    +	double               m_prompt_accumulator ;
    +	double               m_late_accumulator ;
    +	double               m_mark_f, m_space_f;
    +	double               m_audio_average ;
    +	double               m_audio_average_tc;
    +	double               m_audio_minimum ;
    +	double               m_time_sec;
     
    -	double				 m_baud_rate ;
    -	double				 m_baud_error;
    -	int					m_sample_rate ;
    -	bool				   m_averaged_mark_state;
    -	int					m_bit_duration ;
    -	bool				   m_old_mark_state;
    -	BiQuadraticFilter	  m_biquad_mark;
    -	BiQuadraticFilter	  m_biquad_space;
    -	BiQuadraticFilter	  m_biquad_lowpass;
    -	int					m_bit_sample_count, m_half_bit_sample_count;
    -	State				  m_state;
    -	int					m_sample_count;
    -	int					m_next_event_count ;
    -	int					m_bit_count;
    -	int					m_code_bits;
    -	bool				   m_shift ;
    -	bool				   m_pulse_edge_event;
    -	int					m_error_count;
    -	int					m_valid_count;
    -	double				 m_sync_delta;
    -	bool				   m_alpha_phase ;
    -	bool				   m_header_found ;
    +	double               m_baud_rate ;
    +	int                 m_sample_rate ;
    +	int			m_averaged_mark_state;
    +	int                 m_bit_duration ;
    +	fftfilt					*m_mark_lowpass;
    +	fftfilt					*m_space_lowpass;
    +	double					m_mark_phase;
    +	double					m_space_phase;
    +	double                  m_bit_sample_count, m_half_bit_sample_count;
    +	State                 m_state;
    +	int                 m_sample_count;
    +	double                  m_next_early_event;
    +	double                  m_next_prompt_event;
    +	double                  m_next_late_event;
    +	double                  m_average_early_signal;
    +	double                  m_average_prompt_signal;
    +	double                  m_average_late_signal;
    +	std::vector	m_bit_values;
    +	int			m_bit_cursor;
    +	bool                   m_shift ;
    +	bool                   m_pulse_edge_event;
    +	int                 m_error_count;
    +	bool                   m_alpha_phase ;
    +	bool                   m_header_found ;
    +	char snrmsg[80];
     	// filter method related
    -	double				 m_center_frequency_f ;
    +	double               m_center_frequency_f ;
     
     	navtex_implementation( const navtex_implementation & );
     	navtex_implementation();
    @@ -852,12 +911,13 @@ public:
     		m_time_sec = 0.0 ;
     		m_state = NOSIGNAL;
     		m_message_time = 0.0 ;
    -		m_signal_accumulator = 0;
    +		m_early_accumulator = 0;
    +		m_prompt_accumulator = 0;
    +		m_late_accumulator = 0;
     		m_audio_average = 0;
    -		m_audio_minimum = 256;
    +		m_audio_minimum = 0.15;
     		m_sample_rate = the_sample_rate;
     		m_bit_duration = 0;
    -		m_next_event_count = 0;
     		m_shift = false;
     		m_alpha_phase = false;
     		m_header_found = false;
    @@ -866,19 +926,25 @@ public:
     		// this value must never be zero and bigger than 10.
     		m_baud_rate = 100;
     		double m_bit_duration_seconds = 1.0 / m_baud_rate;
    -		m_bit_sample_count = (int) (m_sample_rate * m_bit_duration_seconds + 0.5);
    +		m_bit_sample_count = m_sample_rate * m_bit_duration_seconds;
     		m_half_bit_sample_count = m_bit_sample_count / 2;
    -		m_pulse_edge_event = false;
    +		// A narrower spread between signals allows the modem to
    +		// center on the pulses better, but a wider spread makes
    +		// more robust under noisy conditions. 1/5 seems to work.
    +		m_next_early_event = 0;
    +		m_next_prompt_event = m_bit_sample_count / 5;
    +		m_next_late_event = m_bit_sample_count * 2 / 5;
    +		m_average_early_signal = 0;
    +		m_average_prompt_signal = 0;
    +		m_average_late_signal = 0;
     		m_error_count = 0;
    -		m_valid_count = 0;
     		m_sample_count = 0;
    -		m_next_event_count = 0;
    -		m_zero_crossing_count = 0;
    -		/// Maybe m_bit_sample_count is not a multiple of m_zero_crossings_divisor.
    -		m_zero_crossings.resize( ( m_bit_sample_count + m_zero_crossings_divisor - 1 ) / m_zero_crossings_divisor, 0 );
    -		m_sync_delta = 0;
    -		m_old_mark_state = false;
    -		m_averaged_mark_state = false ;
    +		// keep 1 second worth of bit values for decoding
    +		m_bit_values.resize(m_baud_rate);
    +		m_bit_cursor = 0;
    +
    +		m_mark_lowpass = 0;
    +		m_space_lowpass = 0;
     
     		set_filter_values();
     		configure_filters();
    @@ -895,15 +961,19 @@ private:
     		double qv = m_center_frequency_f + (4.0 * 1000 / m_center_frequency_f);
     		m_mark_f = qv + deviation_f;
     		m_space_f = qv - deviation_f;
    +		m_mark_phase = 0;
    +		m_space_phase = 0;
     	}
     
     	void configure_filters() {
    -		const double mark_space_filter_q = 6 * m_center_frequency_f / 1000.0;
    -		m_biquad_mark.configure(BiQuadraticFilter::BANDPASS, m_mark_f, m_sample_rate, mark_space_filter_q);
    -		m_biquad_space.configure(BiQuadraticFilter::BANDPASS, m_space_f, m_sample_rate, mark_space_filter_q);
    -		static const double lowpass_filter_f = 140.0;
    -		static const double invsqr2 = 1.0 / sqrt(2);
    -		m_biquad_lowpass.configure(BiQuadraticFilter::LOWPASS, lowpass_filter_f, m_sample_rate, invsqr2);
    +		const int filtlen = 512;
    +		if (m_mark_lowpass) delete m_mark_lowpass;
    +		m_mark_lowpass = new fftfilt(m_baud_rate/m_sample_rate, filtlen);
    +		m_mark_lowpass->rtty_filter(m_baud_rate/m_sample_rate);
    +
    +		if (m_space_lowpass) delete m_space_lowpass;
    +		m_space_lowpass = new fftfilt(m_baud_rate/m_sample_rate, filtlen);
    +		m_space_lowpass->rtty_filter(m_baud_rate/m_sample_rate);
     	}
     
     	void set_state(State s) {
    @@ -978,74 +1048,273 @@ private:
     		}
     	}
     
    -	// two phases: alpha and rep
    -	// marked during sync by code_alpha and code_rep
    -	// then for data: rep phase character is sent first,
    -	// then, three chars later, same char is sent in alpha phase
    -	bool process_char(int code) {
    -		bool success = CCIR476::check_bits(code);
    -		int chr = -1;
    -		// force phasing with the two phasing characters
    -		if (code == code_rep) {
    -			m_alpha_phase = false;
    -		} else if (code == code_alpha) {
    -			m_alpha_phase = true;
    +	// The rep character is transmitted 5 characters (35 bits) ahead of
    +	// the alpha character.
    +	int fec_offset(int offset) {
    +		return offset - 35;
    +	}
    +
    +	// Flip the sign of the smallest (least certain) bit in a character;
    +	// hopefully this will result in the right valid character.
    +	void flip_smallest_bit(int *pos) {
    +		int minimum = INT_MAX;
    +		int smallest_bit = -1;
    +		int i;
    +
    +		for (i = 0; i < 7; i++) {
    +			if (abs(pos[i]) < minimum) {
    +				minimum = abs(pos[i]);
    +				smallest_bit = i;
    +			}
     		}
    -		if (!m_alpha_phase) {
    -			m_c1 = m_c2;
    -			m_c2 = m_c3;
    -			m_c3 = code;
    -		} else { // alpha channel
    -			bool strict = false ;
    -			if (strict) {
    -				if (success && m_c1 == code) {
    -					chr = code;
    -				}
    -			} else {
    -				if (success) {
    -					chr = code;
    -				} else if (CCIR476::check_bits(m_c1)) {
    -					chr = m_c1;
    -					LOG_DEBUG("FEC replacement: %x -> %x", code, m_c1);
    +
    +		pos[smallest_bit] = -pos[smallest_bit];
    +	}
    +
    +	// Try to find a position in the bit stream with:
    +	// - the largest number of valid characters, and
    +	// - with rep (duplicate) characters in the right locations
    +	// This way the code can sync up with an incoming signal after
    +	// the initial alpha/rep synchronisation
    +	//
    +	// http://www.arachnoid.com/JNX/index.html
    +	// "NAUTICAL" becomes:
    +	// rep alpha rep alpha N alpha A alpha U N T A I U C T A I L C blank A blank L
    +	int find_alpha_characters(void) {
    +		int best_offset = 0;
    +		int best_score = 0;
    +		int offset, i;
    +
    +		// With 7 bits per character, and interleaved rep & alpha
    +		// characters, the first alpha character with a corresponding
    +		// rep in the stream can be in any of 14 locations
    +		for (offset = 35; offset < (35 + 14); offset++) {
    +			int score = 0;
    +			int reps = 0;
    +			int limit = m_bit_values.size() - 7;
    +
    +			// Search for the largest sequence of valid characters
    +			for (i = offset; i < limit; i += 7) {
    +				if (m_ccir476.valid_char_at(&m_bit_values[i])) {
    +					int ri = fec_offset(i);
    +					int code = m_ccir476.bytes_to_code(&m_bit_values[i]);
    +					int rep = m_ccir476.bytes_to_code(&m_bit_values[ri]);
    +
    +					// This character is valid
    +					score++;
    +
    +					// Does it match its rep?
    +					if (code == rep) {
    +						// This offset is wrong, rep
    +						// and alpha are spaced odd
    +						if (code == code_alpha ||
    +						    code == code_rep) {
    +							score = 0;
    +							break;
    +						}
    +						reps++;
    +					} else if (code == code_alpha) {
    +						// Is there a matching rep to
    +						// this alpha?
    +						int ri = i - 7;
    +						int rep = m_ccir476.bytes_to_code(&m_bit_values[ri]);
    +						if (rep == code_rep) {
    +							reps++;
    +						}
    +					}
     				}
     			}
    -			if (chr == -1) {
    -				LOG_DEBUG("Fail all options: %x %x", code, m_c1); 
    -			} else {
    -				switch (chr) {
    -					case code_rep:
    -						break;
    -					case code_alpha:
    -						break;
    -					case code_beta:
    -						break;
    -					case code_char32:
    -						break;
    -					case code_ltrs:
    -						m_shift = false;
    -						break;
    -					case code_figs:
    -						m_shift = true;
    -						break;
    -					default:
    -						chr = m_ccir476.code_to_char(chr, m_shift);
    -						if (chr < 0) {
    -							LOG_INFO(_("Missed this code: %x"), abs(chr));
    -						} else {
    -							filter_print(chr);
    -							process_messages(chr);
    -						}
    -						break;
    -				} // switch
     
    -			} // if test != -1
    -		} // alpha channel
    +			// the most valid characters, with at least 3 FEC reps
    +			if (reps > 3 && score + reps > best_score) {
    +				best_score = score + reps;
    +				best_offset = offset;
    +			}
    +		}
     
    -		// alpha/rep phasing
    -		m_alpha_phase = !m_alpha_phase;
    +		// m_bit_values fits 14 characters; if there are at least
    +		// 9 good ones, tell the caller where they start
    +		if (best_score > 8)
    +			return best_offset;
    +		else
    +			return -1;
    +	}
    +
    +	// Turns accumulator values (estimates of whether a bit is 1 or 0)
    +	// into navtex messages
    +	void handle_bit_value(int accumulator) {
    +		int buffersize = m_bit_values.size();
    +		int i, offset = 0;
    +
    +		// Store the received value in the bit stream
    +		for (i = 0; i < buffersize - 1; i++) {
    +			m_bit_values[i] = m_bit_values[i+1];
    +		}
    +		m_bit_values[buffersize - 1] = accumulator;
    +		if (m_bit_cursor > 0)
    +			m_bit_cursor--;
    +
    +		// Find the most likely location where the message starts
    +		if (m_state == SYNC) {
    +			offset = find_alpha_characters();
    +			if (offset >= 0) {
    +				set_state(READ_DATA);
    +				m_bit_cursor = offset;
    +				m_alpha_phase = true;
    +			} else
    +				set_state(SYNC_SETUP);
    +		}
    +
    +		// Process 7-bit characters as they come in,
    +		// skipping rep (duplicate) characters
    +		if (m_state == READ_DATA) {
    +			if (m_bit_cursor < buffersize - 7) {
    +				if (m_alpha_phase) {
    +					int ret = process_bytes(m_bit_cursor);
    +					m_error_count -= ret;
    +					if (m_error_count > 5)
    +						set_state(SYNC_SETUP);
    +					if (m_error_count < 0)
    +						m_error_count = 0;
    +				}
    +				m_alpha_phase = !m_alpha_phase;
    +				m_bit_cursor += 7;
    +			}
    +		}
    +	}
    +
    +	// Turn a series of 7 bit confidence values into a character
    +	//
    +	// 1 on successful decode of the alpha character
    +	// 0 on unmodified FEC replacement
    +	// -1 on soft failure (FEC calculation)
    +	// -2 on hard failure
    +	int process_bytes(int m_bit_cursor) {
    +		int code = m_ccir476.bytes_to_code(&m_bit_values[m_bit_cursor]);
    +		int success = 0;
    +
    +		if (m_ccir476.check_bits(code)) {
    +			LOG_DEBUG("valid code : %x (%c)", code, m_ccir476.code_to_char(code, m_shift));
    +			success = 1;
    +			goto decode;
    +		}
    +
    +		if (fec_offset(m_bit_cursor) < 0)
    +			return -1;
    +
    +		// The alpha (primary) character received was not correct.
    +		// Try the rep (duplicate) copy of the character, and some
    +		// permutations to see if the correct character can be found.
    +		{
    +			int i, calc, avg[7];
    +			// Rep is 5 characters before alpha.
    +			int reppos = fec_offset(m_bit_cursor);
    +			int rep = m_ccir476.bytes_to_code(&m_bit_values[reppos]);
    +			if (CCIR476::check_bits(rep)) {
    +				// Current code is probably code_alpha.
    +				// Skip decoding to avoid switching phase.
    +				if (rep == code_rep)
    +					return 0;
    +				LOG_DEBUG("FEC replacement: %x -> %x (%c)", code, rep, m_ccir476.code_to_char(rep, m_shift));
    +				code = rep;
    +				goto decode;
    +			}
    +
    +			// Neither alpha or rep are valid. Check whether
    +			// the average of the two is a valid character.
    +			for (i = 0; i < 7; i++) {
    +				int a = m_bit_values[m_bit_cursor + i];
    +				int r = m_bit_values[rep + i];
    +				avg[i] = a + r;
    +			}
    +
    +			calc = m_ccir476.bytes_to_code(avg);
    +			if (CCIR476::check_bits(calc)) {
    +				LOG_DEBUG("FEC calculation: %x & %x -> %x (%c)", code, rep, calc, m_ccir476.code_to_char(calc, m_shift));
    +				code = calc;
    +				success = -1;
    +				goto decode;
    +			}
    +
    +			// Flip the lowest confidence bit in alpha.
    +			flip_smallest_bit(&m_bit_values[m_bit_cursor]);
    +			calc = m_ccir476.bytes_to_code(&m_bit_values[m_bit_cursor]);
    +			if (CCIR476::check_bits(calc)) {
    +				LOG_DEBUG("FEC calculation: %x & %x -> %x (%c)", code, rep, calc, m_ccir476.code_to_char(calc, m_shift));
    +				code = calc;
    +				success = -1;
    +				goto decode;
    +			}
    +
    +			// Flip the lowest confidence bit in rep.
    +			flip_smallest_bit(&m_bit_values[reppos]);
    +			calc = m_ccir476.bytes_to_code(&m_bit_values[reppos]);
    +			if (CCIR476::check_bits(calc)) {
    +				LOG_DEBUG("FEC calculation: %x & %x -> %x (%c)", code, rep, calc, m_ccir476.code_to_char(calc, m_shift));
    +				code = calc;
    +				success = -1;
    +				goto decode;
    +			}
    +
    +			// Try flipping the bit with the lowest confidence
    +			// in the average of alpha & rep.
    +			flip_smallest_bit(avg);
    +			calc = m_ccir476.bytes_to_code(avg);
    +			if (CCIR476::check_bits(calc)) {
    +				LOG_DEBUG("FEC calculation: %x & %x -> %x (%c)", code, rep, calc, m_ccir476.code_to_char(calc, m_shift));
    +				code = calc;
    +				success = -1;
    +				goto decode;
    +			}
    +
    +			LOG_DEBUG("decode fail %x, %x", code, rep);
    +			return -2;
    +		}
    +
    +	decode:
    +		process_char(code);
     		return success;
     	}
     
    +	bool process_char(int chr) {
    +		static int last_char = 0;
    +		switch (chr) {
    +			case code_rep:
    +				// This code should run in alpha phase, but
    +				// it just received two rep characters. Fix
    +				// the rep/alpha phase, so FEC works again.
    +				if (last_char == code_rep) {
    +					LOG_DEBUG("fixing rep/alpha sync");
    +					m_alpha_phase = false;
    +				}
    +				break;
    +			case code_alpha:
    +				break;
    +			case code_beta:
    +				break;
    +			case code_char32:
    +				break;
    +			case code_ltrs:
    +				m_shift = false;
    +				break;
    +			case code_figs:
    +				m_shift = true;
    +				break;
    +			default:
    +				chr = m_ccir476.code_to_char(chr, m_shift);
    +				if (chr < 0) {
    +					LOG_INFO(_("Missed this code: %x"), abs(chr));
    +				} else {
    +					filter_print(chr);
    +					process_messages(chr);
    +				}
    +				break;
    +			} // switch
    +
    +		last_char = chr;
    +		return true;
    +	}
    +
     	void filter_print(int c) {
     		if (c == char_bell) {
     			/// TODO: It should be a beep, but French navtex displays a quote.
    @@ -1057,20 +1326,24 @@ private:
     
     	void compute_metric(void)
     	{
    -		static double avg_ratio = 0.0 ;
    -		static const double width_f = 10.0 ;
    -       		double numer_mark = wf->powerDensity(m_mark_f, width_f);
    -       		double numer_space = wf->powerDensity(m_space_f, width_f);
    -       		double numer_mid = wf->powerDensity(m_center_frequency_f, width_f);
    -       		double denom = wf->powerDensity(m_center_frequency_f, 2 * deviation_f) + 1e-10;
    +		static double sigpwr = 0.0 ;
    +		static double noisepwr = 0.0;
    +		double delta = m_baud_rate/8.0;
    +		double np = wf->powerDensity(m_center_frequency_f, delta) * 3000 / delta;
    +		double sp =
    +			wf->powerDensity(m_mark_f, delta) +
    +				wf->powerDensity(m_space_f, delta) + 1e-10;
    +		double snr;
     
    -		double ratio = ( numer_space + numer_mark + numer_mid ) / denom ;
    +		sigpwr = decayavg ( sigpwr, sp, sp > sigpwr ? 2 : 8);
    +		noisepwr = decayavg ( noisepwr, np, 16 );
    +		snr = 10*log10(sigpwr / noisepwr);
     
    -		/// The only power in this band should come from the signal.
    -       		m_metric = 100 * decayavg( avg_ratio, ratio, 20 );
    -
    -		// LOG_INFO("m_metric=%lf",m_metric);
    +		snprintf(snrmsg, sizeof(snrmsg), "s/n %3.0f dB", snr);
    +		put_Status2(snrmsg);
    +		m_metric = CLAMP((3000 / delta) * (sigpwr/noisepwr), 0.0, 100.0);
     		m_ptr_navtex->display_metric(m_metric);
    +
     	}
     
     	void process_afc() {
    @@ -1086,9 +1359,9 @@ private:
     		static int cnt_read_data = 0 ;
     		/// This centers the carrier where the activity is the strongest.
     		static const int bw[][2] = {
    -			{ -deviation_f - 2, -deviation_f + 8 },
    -			{  deviation_f - 8,  deviation_f + 2 } };
    -       		double max_carrier = wf->powerDensityMaximum( 2, bw );
    +			{ -deviation_f - 10, -deviation_f + 5 },
    +			{  deviation_f - 5,  deviation_f + 10 } };
    +		double max_carrier = wf->powerDensityMaximum( 2, bw );
     
     		/// Do not change the frequency too quickly if an image is received.
     		double next_carr = 0.0 ;
    @@ -1105,8 +1378,8 @@ private:
     			} else {
     				lingering_state = m_state ;
     				/// Maybe this is the phasing signal, so we recenter.
    -				double pwr_left = wf->powerDensity ( max_carrier - deviation_f, 10 );
    -				double pwr_right = wf->powerDensity( max_carrier + deviation_f, 10 );
    +				double pwr_left = wf->powerDensity ( max_carrier - deviation_f, 30 );
    +				double pwr_right = wf->powerDensity( max_carrier + deviation_f, 30 );
     				static const double ratio_left_right = 5.0 ;
     				if( pwr_left > ratio_left_right * pwr_right ) {
     					max_carrier -= deviation_f ;
    @@ -1120,8 +1393,7 @@ private:
     			case SYNC_SETUP:
     				next_carr = max_carrier ;
     				break;
    -			case SYNC1:
    -			case SYNC2:
    +			case SYNC:
     				next_carr = decayavg( m_center_frequency_f, max_carrier, 1 );
     				break;
     			case READ_DATA:
    @@ -1145,6 +1417,48 @@ private:
     		}
     	}
     
    +	// The signal is sampled at three points: early, prompt, and late.
    +	// The prompt event is where the signal is decoded, while early and
    +	// late are only used to adjust the time of the sampling to match
    +	// the incoming signal.
    +	//
    +	// The early event happens 1/5 bit period before the prompt event,
    +	// and the late event 1/5 bit period later. If the incoming signal
    +	// peaks early, it means the decoder is late. That is, if the early
    +	// signal is "too large", decoding should to happen earlier.
    +	//
    +	// Attempt to center the signal so the accumulator is at its
    +	// maximum deviation at the prompt event. If the bit is decoded
    +	// too early or too late, the code is more sensitive to noise,
    +	// and less likely to decode the signal correctly.
    +	void process_multicorrelator() {
    +		// Adjust the sampling period once every 8 bit periods.
    +		if (m_sample_count % (int)(m_bit_sample_count * 8))
    +			return;
    +
    +		// Calculate the slope between early and late signals
    +		// to align the logic sampling with the received signal
    +		double slope = m_average_late_signal - m_average_early_signal;
    +
    +		if (m_average_prompt_signal < m_average_early_signal &&
    +		    m_average_prompt_signal < m_average_late_signal)
    +			// At a signal minimum. Get out quickly.
    +			slope /= 2;
    +		else if (m_average_prompt_signal > m_average_late_signal &&
    +			 m_average_prompt_signal > m_average_late_signal)
    +			// Limit the adjustment, to ride out noise
    +			slope /= 128;
    +		else
    +			slope /= 32;
    +
    +		if (slope) {
    +			m_next_early_event += slope;
    +			m_next_prompt_event += slope;
    +			m_next_late_event += slope;
    +			LOG_DEBUG("adjusting by %1.2f, early %1.1f, prompt %1.1f, late %1.1f", slope, m_average_early_signal, m_average_prompt_signal, m_average_late_signal);
    +		}
    +	}
    +
     	/* A NAVTEX message is built on SITOR collective B-mode and consists of:
     	* a phasing signal of at least ten seconds
     	* the four characters "ZCZC" that identify the end of phasing
    @@ -1165,97 +1479,137 @@ public:
     		process_afc();
     		process_timeout();
     		for( int i =0; i < nb_samples; ++i ) {
    +			int n_out;
    +			cmplx z, zmark, zspace, *zp_mark, *zp_space;
    +
     			short v = static_cast(32767 * data[i]);
     
     			m_time_sec = m_sample_count / m_sample_rate ;
    +
     			double dv = v;
    +			z = cmplx(dv, dv);
     
    -			// separate mark and space by narrow filtering
    -			double mark_level = m_biquad_mark.filter(dv);
    -			double space_level = m_biquad_space.filter(dv);
    +			zmark = mixer(m_mark_phase, m_mark_f, z);
    +			m_mark_lowpass->run(zmark, &zp_mark);
     
    -			double mark_abs = fabs(mark_level);
    -			double space_abs = fabs(space_level);
    +			zspace = mixer(m_space_phase, m_space_f, z);
    +			n_out = m_space_lowpass->run(zspace, &zp_space);
    +
    +			if (n_out)
    +				process_fft_output(zp_mark, zp_space, n_out);
    +		}
    +	}
    +
    +private:
    +	cmplx mixer(double &phase, double f, cmplx in)
    +	{
    +		cmplx z = cmplx( cos(phase), sin(phase)) * in;
    +
    +		phase -= TWOPI * f / m_sample_rate;
    +		if (phase < -TWOPI) phase += TWOPI;
    +
    +		return z;
    +	}
    +
    +	// noise average decays fast down, slow up
    +	double noise_decay(double avg, double value) {
    +		int divisor;
    +		if (value < avg)
    +			divisor = m_bit_sample_count / 4;
    +		else
    +			divisor = m_bit_sample_count * 48;
    +		return decayavg(avg, value, divisor);
    +	}
    +
    +	// envelope average decays fast up, slow down
    +	double envelope_decay(double avg, double value) {
    +		int divisor;
    +		if (value > avg)
    +			divisor = m_bit_sample_count / 4;
    +		else
    +			divisor = m_bit_sample_count * 16;
    +		return decayavg(avg, value, divisor);
    +	}
    +
    +	void process_fft_output(cmplx *zp_mark, cmplx *zp_space, int samples) {
    +		// envelope & noise levels for mark & space, respectively
    +		static double mark_env = 0, space_env = 0;
    +		static double mark_noise = 0, space_noise = 0;
    +
    +		for (int i = 0; i < samples; i++) {
    +			double mark_abs = abs(zp_mark[i]);
    +			double space_abs = abs(zp_space[i]);
    +
    +			process_multicorrelator();
     
     			m_audio_average += (std::max(mark_abs, space_abs) - m_audio_average) * m_audio_average_tc;
     
     			m_audio_average = std::max(.1, m_audio_average);
     
    -			// produce difference of absolutes of mark and space
    -			double diffabs = (mark_abs - space_abs);
    +			// determine noise floor & envelope for mark & space
    +			mark_env = envelope_decay(mark_env, mark_abs);
    +			mark_noise = noise_decay(mark_noise, mark_abs);
     
    -			diffabs /= m_audio_average;
    +			space_env = envelope_decay(space_env, space_abs);
    +			space_noise = noise_decay(space_noise, space_abs);
     
    -			// now low-pass the resulting difference
    -			double logic_level = m_biquad_lowpass.filter(diffabs);
    +			double noise_floor = (space_noise + mark_noise) / 2;
     
    +			// clip mark & space to envelope & floor
    +			mark_abs = min(mark_abs, mark_env);
    +			mark_abs = max(mark_abs, noise_floor);
    +
    +			space_abs = min(space_abs, space_env);
    +			space_abs = max(space_abs, noise_floor);
    +
    +			// mark-space discriminator with automatic threshold
    +			// correction, see:
    +			// http://www.w7ay.net/site/Technical/ATC/
    +			double logic_level =
    +				(mark_abs - noise_floor) * (mark_env - noise_floor) -
    +				(space_abs - noise_floor) * (space_env - noise_floor) -
    +				0.5 * ( (mark_env - noise_floor) * (mark_env - noise_floor) -
    +					 (space_env - noise_floor) * (space_env - noise_floor));
    +
    +			// the accumulator hits max when mark_state flips sign
     			bool mark_state = (logic_level > 0);
    -			m_signal_accumulator += (mark_state) ? 1 : -1;
    -			m_bit_duration++;
    +			m_early_accumulator += (mark_state) ? 1 : -1;
    +			m_prompt_accumulator += (mark_state) ? 1 : -1;
    +			m_late_accumulator += (mark_state) ? 1 : -1;
     
    -			// adjust signal synchronization over time
    -			// by detecting zero crossings
    -			if (mark_state != m_old_mark_state) {
    -				// a valid bit duration must be longer than bit duration / 2
    -				if ((m_bit_duration % m_bit_sample_count) > m_half_bit_sample_count) {
    -					// create a relative index for this zero crossing
    -					assert( m_sample_count - m_next_event_count + m_bit_sample_count * 8 >= 0 );
    -					size_t index = size_t((m_sample_count - m_next_event_count + m_bit_sample_count * 8) % m_bit_sample_count);
    -
    -					// TODO: This never happened so could be replaced by assert() for speed-up.
    -					// Size = m_bit_sample_count / m_zero_crossings_divisor
    -					if( index / m_zero_crossings_divisor >= m_zero_crossings.size() ) {
    -						LOG_ERROR("index=%d m_zero_crossings_divisor=%d m_zero_crossings.size()=%d\n",
    -								(int)index, m_zero_crossings_divisor, (int)m_zero_crossings.size() );
    -						LOG_ERROR("m_sample_count=%d m_next_event_count=%d m_bit_sample_count=%d\n",
    -						m_sample_count, m_next_event_count, m_bit_sample_count );
    -						exit(EXIT_FAILURE);
    -					}
    -
    -					m_zero_crossings.at( index / m_zero_crossings_divisor )++;
    -				}
    -				m_bit_duration = 0;
    -			}
    -			m_old_mark_state = mark_state;
    -			if (m_sample_count % m_bit_sample_count == 0) {
    -				m_zero_crossing_count++;
    -				static const int zero_crossing_samples = 16;
    -				if (m_zero_crossing_count >= zero_crossing_samples) {
    -					int best = 0;
    -					int index = 0;
    -					// locate max zero crossing
    -					for (size_t i = 0; i < m_zero_crossings.size(); i++) {
    -						int q = m_zero_crossings[i];
    -						m_zero_crossings[i] = 0;
    -						if (q > best) {
    -							best = q;
    -							index = i;
    -						}
    -					}
    -					if (best > 0) { // if there is a basis for choosing
    -						// create a signed correction value
    -						index *= m_zero_crossings_divisor;
    -						index = ((index + m_half_bit_sample_count) % m_bit_sample_count) - m_half_bit_sample_count;
    -						// limit loop gain
    -						double dbl_idx = (double)index / 8.0 ;
    -						// m_sync_delta is a temporary value that is
    -						// used once, then reset to zero
    -						m_sync_delta = dbl_idx;
    -						// m_baud_error is persistent -- used by baud error label
    -						m_baud_error = dbl_idx;
    -					}
    -					m_zero_crossing_count = 0;
    -				}
    +			// An average of the magnitude of the accumulator
    +			// is taken at the sample point, as well as a quarter
    +			// bit before and after. This allows the code to see
    +			// the best time to sample the signal without relying
    +			// on (noisy) null crossings.
    +			if (m_sample_count >= m_next_early_event) {
    +				m_average_early_signal = decayavg(
    +						m_average_early_signal,
    +						fabs(m_early_accumulator), 64);
    +				m_next_early_event += m_bit_sample_count;
    +				m_early_accumulator = 0;
     			}
     
    -			// flag the center of signal pulses
    -			m_pulse_edge_event = m_sample_count >= m_next_event_count;
    +			if (m_sample_count >= m_next_late_event) {
    +				m_average_late_signal = decayavg(
    +						m_average_late_signal,
    +						fabs(m_late_accumulator), 64);
    +				m_next_late_event += m_bit_sample_count;
    +				m_late_accumulator = 0;
    +			}
    +
    +			// the end of a signal pulse
    +			// the accumulator should be at maximum deviation
    +			m_pulse_edge_event = m_sample_count >= m_next_prompt_event;
     			if (m_pulse_edge_event) {
    -				m_averaged_mark_state = (m_signal_accumulator > 0) ^ m_ptr_navtex->get_reverse();
    -				m_signal_accumulator = 0;
    -				// set new timeout value, include zero crossing correction
    -				m_next_event_count = m_sample_count + m_bit_sample_count + (int) (m_sync_delta + 0.5);
    -				m_sync_delta = 0;
    +				m_average_prompt_signal = decayavg(
    +						m_average_prompt_signal,
    +						fabs(m_prompt_accumulator), 64);
    +				m_next_prompt_event += m_bit_sample_count;
    +				m_averaged_mark_state = m_prompt_accumulator;
    +				if (m_ptr_navtex->get_reverse())
    +					m_averaged_mark_state = -m_averaged_mark_state;
    +				m_prompt_accumulator = 0;
     			}
     
     			if (m_audio_average < m_audio_minimum) {
    @@ -1267,79 +1621,14 @@ public:
     			switch (m_state) {
     				case NOSIGNAL: break;
     				case SYNC_SETUP:
    -					m_bit_count = -1;
    -					m_code_bits = 0;
     					m_error_count = 0;
    -					m_valid_count = 0;
     					m_shift = false;
    -					m_sync_chrs.clear();
    -					set_state(SYNC1);
    -					break;
    -				// scan indefinitely for valid bit pattern
    -				case SYNC1:
    -					if (m_pulse_edge_event) {
    -						m_code_bits = (m_code_bits >> 1) | ( m_averaged_mark_state ? 64 : 0);
    -						if (CCIR476::check_bits(m_code_bits)) {
    -							m_sync_chrs.push_back(m_code_bits);
    -							m_bit_count = 0;
    -							m_code_bits = 0;
    -							set_state(SYNC2);
    -						}
    -					}
    -					break;
    -				//  sample and validate bits in groups of 7
    -				case SYNC2:
    -					// find any bit alignment that produces a valid character
    -					// then test that synchronization in subsequent groups of 7 bits
    -					if (m_pulse_edge_event) {
    -						m_code_bits = (m_code_bits >> 1) | ( m_averaged_mark_state ? 64 : 0);
    -						m_bit_count++;
    -						if (m_bit_count == 7) {
    -							if (CCIR476::check_bits(m_code_bits)) {
    -								m_sync_chrs.push_back(m_code_bits);
    -								m_code_bits = 0;
    -								m_bit_count = 0;
    -								m_valid_count++;
    -								// successfully read 4 characters?
    -								if (m_valid_count == 4) {
    -									for( sync_chrs_type::const_iterator it = m_sync_chrs.begin(), en = m_sync_chrs.end(); it != en; ++it ) {
    -										process_char(*it);
    -									}
    -									set_state(READ_DATA);
    -								}
    -							} else { // failed subsequent bit test
    -								m_code_bits = 0;
    -								m_bit_count = 0;
    -								// LOG_INFO("restarting sync");
    -								set_state(SYNC_SETUP);
    -							}
    -						}
    -					}
    +					set_state(SYNC);
     					break;
    +				case SYNC:
     				case READ_DATA:
    -					if (m_pulse_edge_event) {
    -						m_code_bits = (m_code_bits >> 1) | ( m_averaged_mark_state ? 64 : 0);
    -						m_bit_count++;
    -						if (m_bit_count == 7) {
    -							if (m_error_count > 0) {
    -								LOG_DEBUG("Error count: %d", m_error_count);
    -							}
    -							if (process_char(m_code_bits)) {
    -								if (m_error_count > 0) {
    -									m_error_count--;
    -								}
    -							} else {
    -								m_error_count++;
    -								if (m_error_count > 2) {
    -									LOG_DEBUG("Returning to sync");
    -									set_state(SYNC_SETUP);
    -								}
    -							}
    -							m_bit_count = 0;
    -							m_code_bits = 0;
    -						}
    -					}
    -					break;
    +					if (m_pulse_edge_event)
    +						handle_bit_value(m_averaged_mark_state);
     			}
     
     			m_sample_count++;
    diff --git a/src/olivia/olivia.cxx b/src/olivia/olivia.cxx
    index 79671275..e83ccdb0 100644
    --- a/src/olivia/olivia.cxx
    +++ b/src/olivia/olivia.cxx
    @@ -105,6 +105,8 @@ void olivia::rx_flush()
     
     void olivia::send_tones()
     {
    +	if (!progdefaults.olivia_start_tones) return;
    +
     	double freqa, freqb;
     	tone_bw = bandwidth;
     	tone_midfreq = txbasefreq;
    diff --git a/src/psk/psk.cxx b/src/psk/psk.cxx
    index 5ab3b50d..fa9e4943 100644
    --- a/src/psk/psk.cxx
    +++ b/src/psk/psk.cxx
    @@ -51,6 +51,8 @@
     #include "Viewer.h"
     #include "macros.h"
     
    +#include "confdialog.h"
    +
     extern waterfall *wf;
     
     // Change the following for DCD low pass filter adjustment
    @@ -80,17 +82,6 @@ extern waterfall *wf;
     #define K13_POLY1	016461 // 7473
     #define K13_POLY2	012767 // 5623
     
    -// Poorly performing code: Do not use
    -#define K9		9
    -#define K9_POLY1	0677 // 447
    -#define K9_POLY2	0515 // 333
    -
    -// df=18 : correct up to 8 bits
    -#define	K15		15
    -#define	K15_POLY1	044735 // 18909
    -#define	K15_POLY2	063057 // 26159
    -
    -
     // df=19 : correct up to 9 bits
     #define	K16		16
     #define	K16_POLY1	0152711 // 54729
    @@ -101,7 +92,7 @@ extern waterfall *wf;
     //  - One of the bits is still known with 100% certianty.
     //  - Only up to 1 bit can be in error
     static cmplx graymapped_8psk_pos[] = {
    -	//				 Degrees  Bits In  Mapped Soft-Symbol
    +	//			Degrees  Bits In  Mapped Soft-Symbol
     	cmplx (1.0, 0.0),         // 0   | 0b000  | 025,000,025
     	cmplx (0.7071, 0.7071),   // 45  | 0b001  | 000,025,230
     	cmplx (-0.7071, 0.7071),  // 135 | 0b010  | 025,255,025
    @@ -164,6 +155,12 @@ void psk::tx_init(SoundBase *sc)
     	vphase = 0;
     	maxamp = 0;
     
    +	double bw2 = 6.0 * bandwidth;
    +	double flo = (get_txfreq_woffset() - bw2);
    +	if (flo <= 0) flo = 0;
    +	double fhi = (get_txfreq_woffset() + bw2);
    +	if (fhi >= 0.48*samplerate) fhi = 0.48*samplerate;
    +	xmtfilt->init_bandpass (127, 1, flo/samplerate, fhi/samplerate);
     }
     
     void psk::rx_init()
    @@ -190,7 +187,6 @@ void psk::rx_init()
     	else sigsearch = 0;
     	put_MODEstatus(mode);
     	resetSN_IMD();
    -	imdValid = false;
     	afcmetric = 0.0;
     	// interleaver, split incoming bit stream into two, one late by one bit
     	rxbitstate = 0;
    @@ -234,6 +230,9 @@ psk::~psk()
     	}
     	if (snfilt) delete snfilt;
     	if (imdfilt) delete imdfilt;
    +	if (e0_filt) delete e0_filt;
    +	if (e1_filt) delete e1_filt;
    +	if (e2_filt) delete e2_filt;
     
     	if (pskviewer) delete pskviewer;
     	if (evalpsk) delete evalpsk;
    @@ -244,6 +243,8 @@ psk::~psk()
     	if (Txinlv) delete Txinlv;
     
     	if (vestigial_sfft) delete vestigial_sfft;
    +
    +	if (xmtfilt) delete xmtfilt;
     }
     
     psk::psk(trx_mode pskmode) : modem()
    @@ -365,6 +366,26 @@ psk::psk(trx_mode pskmode) : modem()
     			break;
     
     	// 8psk modes with FEC
    +		case MODE_8PSK125FL:
    +			symbollen = 128;
    +			idepth = 384; // 1024 milliseconds
    +			flushlength = 38;
    +			samplerate = 16000;
    +			_8psk = true;
    +			dcdbits = 128;
    +			vestigial = true;
    +			cap |= CAP_REV;
    +			break;
    +		case MODE_8PSK250FL: // 250 baud | 375 bits/sec @ 1/2 Rate FEC
    +			symbollen = 64;
    +			idepth = 512; // 682 milliseconds
    +			flushlength = 47;
    +			samplerate = 16000;
    +			_8psk = true;
    +			dcdbits = 256;
    +			vestigial = true;
    +			cap |= CAP_REV;
    +			break;
     		case MODE_8PSK125F:
     			symbollen = 128;
     			idepth = 384; // 1024 milliseconds
    @@ -723,6 +744,9 @@ psk::psk(trx_mode pskmode) : modem()
     
     	snfilt = new Cmovavg(16);
     	imdfilt = new Cmovavg(16);
    +	e0_filt = new Cmovavg(dcdbits / 2);
    +	e1_filt = new Cmovavg(dcdbits / 2);
    +	e2_filt = new Cmovavg(dcdbits / 2);
     
     	if (_disablefec) {
     		enc = NULL;
    @@ -732,7 +756,7 @@ psk::psk(trx_mode pskmode) : modem()
     		enc = new encoder(K, POLY1, POLY2);
     		dec = new viterbi(K, POLY1, POLY2);
     
    -	} else if (_pskr || mode == MODE_8PSK1200F || PSKviterbi) {
    +	} else if (_pskr || PSKviterbi) {
     		// FEC for BPSK. Use a 2nd Viterbi decoder for comparison.
     		// Set decode size to 4 since some characters can be as small
     		// as 3 bits long. This minimises intercharacters decoding
    @@ -743,27 +767,26 @@ psk::psk(trx_mode pskmode) : modem()
     		dec2 = new viterbi(PSKR_K, PSKR_POLY1, PSKR_POLY2);
     		dec2->setchunksize(4);
     
    -	} else if (_puncturing) { 
    -		// Use the FEC code best suited for puncturing
    -		enc = new encoder(K13, K13_POLY1, K13_POLY2);
    -		dec = new viterbi(K13, K13_POLY1, K13_POLY2);
    -		// long constraint length codes require long traceback
    -		dec->settraceback (PATHMEM); 
    -		dec->setchunksize(4);
    -		dec2 = new viterbi(K13, K13_POLY1, K13_POLY2);
    -		dec2->settraceback (PATHMEM);
    -		dec2->setchunksize(4);
    -
    -	} else if (_xpsk || _8psk || _16psk) { 
    -		// Use the code with the best FEC capabilities
    +	} else if (mode == MODE_8PSK125F || mode == MODE_8PSK250F) {
     		enc = new encoder(K16, K16_POLY1, K16_POLY2);
     		dec = new viterbi(K16, K16_POLY1, K16_POLY2);
    -		// long constraint length codes require long traceback
    -		dec->settraceback (PATHMEM); 
     		dec->setchunksize(4);
    -		dec2 = new viterbi(K16, K16_POLY1, K16_POLY2);
    -		dec2->settraceback (PATHMEM);
    +		dec2 = new viterbi(K13, K16_POLY1, K16_POLY2);
     		dec2->setchunksize(4);
    +
    +	} else if (_xpsk || _8psk || _16psk) {
    +		enc = new encoder(K13, K13_POLY1, K13_POLY2);
    +		dec = new viterbi(K13, K13_POLY1, K13_POLY2);
    +		dec->setchunksize(4);
    +		// Second viterbi decoder is only needed when modem has an odd number of bits/symbol.
    +		if ( _8psk && !_puncturing ) { // (punctured 8psk has 3-real bits + 1-punctured bit per transmitted symbol)
    +			dec2 = new viterbi(K13, K13_POLY1, K13_POLY2);
    +			dec2->setchunksize(4);
    +		}
    +		if (_puncturing) { // punctured codes benefit from a longer traceback
    +			dec->settraceback(K13 * 16);
    +			if (dec2) dec2->settraceback(K13 * 16);
    +		}
     	}
     
     	// Interleaver. For PSKR to maintain constant time delay between bits,
    @@ -773,7 +796,7 @@ psk::psk(trx_mode pskmode) : modem()
     
     	Txinlv = new interleave (isize, idepth, INTERLEAVE_FWD);
     	Rxinlv = new interleave (isize, idepth, INTERLEAVE_REV);
    -	Rxinlv2 = new interleave (isize, idepth, INTERLEAVE_REV);
    +	if (dec2) Rxinlv2 = new interleave (isize, idepth, INTERLEAVE_REV);
     
     	bitshreg = 0;
     	rxbitstate = 0;
    @@ -819,6 +842,9 @@ psk::psk(trx_mode pskmode) : modem()
     		vestigial_sfft = new sfft(sfft_size, bin - 5, bin + 6); // 11 bins
     		for (int i = 0; i < 11; i++) sfft_bins[i] = cmplx(0,0);
     	}
    +
    +	xmtfilt = new C_FIR_filter();
    +
     }
     
     //=============================================================================
    @@ -962,6 +988,13 @@ void psk::rx_pskr(unsigned char symbol)
     		//			fecmet2 = -9999.0;
     		//			return;
     		//		}
    +		// XPSK and 16PSK have even number of bits/symbol
    +		// Punctured 8PSK has even number of bits/symbol (3 real + 1 punctured)
    +		// so bit order known: can use only one decoder to reduce CPU usage
    +		if ( _xpsk || _16psk || (_8psk && _puncturing) ) {
    +			fecmet2 = -9999.0;
    +			return;
    +		}
     		// copy to avoid scrambling symbolpair for the next bit
     		twosym[0] = symbolpair[0];
     		twosym[1] = symbolpair[1];
    @@ -1044,6 +1077,10 @@ int waitcount = 0;
     
     void psk::findsignal()
     {
    +	put_Status1("");
    +	put_Status2("");
    +	put_status("");
    +
     	int ftest, f1, f2;
     
     	if (sigsearch > 0) {
    @@ -1106,9 +1143,9 @@ void psk::vestigial_afc() {
     	std::setprecision(2); std::setw(5);
     	for (i = 0; i < 11; i++) if (abs(sfft_bins[i]) > 2.0*avg) break;
     	if (i < 11) {
    -//		std::cout	<< "bin: " << i 
    +//		std::cout	<< "bin: " << i
     //					<< ", freq offset: " << (i - 5)*samplerate/16384.0
    -//					<< ", amp: " << abs(sfft_bins[i]) 
    +//					<< ", amp: " << abs(sfft_bins[i])
     //					<< ", avg: " << avg << "\n";
     		if (i != 5) {
     			frequency -= 1.0*(i-5)*samplerate/sfft_size;
    @@ -1156,7 +1193,6 @@ void psk::afc()
     		phaseafc();
     }
     
    -
     void psk::rx_symbol(cmplx symbol, int car)
     {
     	int n;
    @@ -1213,22 +1249,26 @@ void psk::rx_symbol(cmplx symbol, int car)
     	// simple low pass filter for quality of signal
     	double decay = SQLDECAY;
     	double attack = SQLDECAY;
    +	double cval = cos(n*phase);
    +	double sval = sin(n*phase);
    +
     	if (_8psk) {
     		attack *= 2;
     		decay *= 4;
     	}
    +
     	if (_pskr) {
    -		attack *= 2;
     		decay *= 10;
    -	}
    +		quality = cmplx(
    +			decayavg(quality.real(), cval, decay),
    +			decayavg(quality.imag(), sval, decay));
    +	} else
    +		quality = cmplx(
    +			decayavg(quality.real(), cval, cval > quality.real() ? attack : decay),
    +			decayavg(quality.imag(), sval, sval > quality.real() ? attack : decay));
     
    -	double cval = cos(n*phase);
    -	double sval = sin(n*phase);
    -
    -	quality = cmplx(
    -					decayavg(quality.real(), cval, cval > quality.real() ? attack : decay),
    -					decayavg(quality.imag(), sval, sval > quality.real() ? attack : decay));
     	metric = 100.0 * norm(quality);
    +	if (_pskr && (averageamp < 3e-5)) metric = 0;
     
     	if (progdefaults.Pskmails2nreport && (mailserver || mailclient)) {
     		//s2n reporting: rescale depending on mode, clip after scaling
    @@ -1259,8 +1299,7 @@ void psk::rx_symbol(cmplx symbol, int car)
     	dcdshreg = ( dcdshreg << (symbits+1) ) | bits;
     
     	int set_dcdON = -1; // 1 sets DCD on ; 0 sets DCD off ; -1 does neither (no-op)
    -	imdValid = false;
    -	//printf("\n%.8X", dcdshreg);
    +
     	switch (dcdshreg) {
     
     			// bpsk DCD on
    @@ -1312,7 +1351,7 @@ void psk::rx_symbol(cmplx symbol, int car)
     			if (!_disablefec) break;
     			set_dcdON = 0;
     			break;
    -		
    +
     		case 0x10410410:	// xpsk DCD on (with FEC enabled)
     			if (_pskr) break;
     			if (_qpsk) break;
    @@ -1322,7 +1361,7 @@ void psk::rx_symbol(cmplx symbol, int car)
     			if (_disablefec) break;
     			set_dcdON = 1;
     			break;
    - 
    +
     		case 0x00000000:	// bpsk DCD off.  x,8,16psk DCD on (with FEC disabled).
     			if (_pskr) break;
     			if (_xpsk || _8psk || _16psk) {
    @@ -1341,11 +1380,12 @@ void psk::rx_symbol(cmplx symbol, int car)
     			}
     	}
     
    +	displaysn = false;
     	if ( 1 == set_dcdON ) {
    +		displaysn = true;
     		dcd = true;
     		acquire = 0;
     		quality = cmplx (1.0, 0.0);
    -		imdValid = true;
     		if (progdefaults.Pskmails2nreport && (mailserver || mailclient))
     			s2n_sum = s2n_sum2 = s2n_ncount = 0.0;
     		//printf("\n DCD ON!!");
    @@ -1379,7 +1419,7 @@ void psk::rx_symbol(cmplx symbol, int car)
     				phasequality = (phasequality + lastphasequality) / 2; // Differential modem: average probabilities between current and previous symbols
     				lastphasequality = phasequality;
     				int soft_qualityerror = static_cast(128 - (128 * phasequality)) ;
    -				
    +
     				if (soft_qualityerror > 255-25) // Prevent soft-bit wrap-around (crossing of value 128)
     					softpuncture = true;
     				else if (soft_qualityerror < 128/3) // First 1/3 of phase delta is considered a perfect signal
    @@ -1387,8 +1427,8 @@ void psk::rx_symbol(cmplx symbol, int car)
     				else if (soft_qualityerror > 128 - (128/8) ) // Last 1/8 of phase delta triggers a puncture
     					softpuncture = true;
     				else
    -					soft_qualityerror /= 2; // Scale the FEC error to prevent premature cutoff 
    -			
    +					soft_qualityerror /= 2; // Scale the FEC error to prevent premature cutoff
    +
     
     				if (softpuncture) {
     					for(int i=0; irun(m_Energy[0]);
    +	e1 = e1_filt->run(m_Energy[1]);
    +	e2 = e2_filt->run(m_Energy[2]);
     
    -	if (m_Energy[1])
    -		snratio = snfilt->run(m_Energy[0]/m_Energy[1]);
    +	if (((e0 - e1) > 0) && (e1 > 0))
    +		snratio = (e0 - e1) / e1;
     	else
    -		snratio = snfilt->run(1.0);
    +		snratio = 1000.0;
     
    -	if (m_Energy[0] && imdValid)
    -		imdratio = imdfilt->run(m_Energy[2]/m_Energy[0]);
    +	if (((e0 - e1) > 0) && ((e2 - e1) > 0) )
    +		imdratio = (e2 - e1) / (e0 - e1);
     	else
    -		imdratio = imdfilt->run(0.001);
    +		imdratio = 0.001;
     
     }
     
    @@ -1451,19 +1497,30 @@ void psk::update_syncscope()
     
     	display_metric(metric);
     
    -	memset(msg1, 0, sizeof(msg1));
    -	memset(msg2, 0, sizeof(msg2));
    +	if (displaysn) {
    +		memset(msg1, 0, sizeof(msg1));
    +		memset(msg2, 0, sizeof(msg2));
     
    -	s2n = 10.0*log10( snratio );
    -	snprintf(msg1, sizeof(msg1)-1, "s/n %2d dB", (int)(floor(s2n)));
    +		s2n = 10.0*log10( snratio );
    +		snprintf(msg1, sizeof(msg1), "s/n %2.0f dB", s2n);
     
    -	imd = 10.0*log10( imdratio );
    -	snprintf(msg2, sizeof(msg2)-1, "imd %3d dB", (int)(floor(imd)));
    +		imd = 10.0*log10( imdratio );
    +		snprintf(msg2, sizeof(msg2), "imd %2.0f dB", imd);
     
    -	if (imdValid) {
    -		put_Status1(msg1, progdefaults.StatusTimeout, progdefaults.StatusDim ? STATUS_DIM : STATUS_CLEAR);
    -		put_Status2(msg2, progdefaults.StatusTimeout, progdefaults.StatusDim ? STATUS_DIM : STATUS_CLEAR);
    +		put_Status1(	msg1,
    +						progdefaults.StatusTimeout,
    +						progdefaults.StatusDim ? STATUS_DIM : STATUS_CLEAR);
    +		put_Status2(	msg2,
    +						progdefaults.StatusTimeout,
    +						progdefaults.StatusDim ? STATUS_DIM : STATUS_CLEAR);
     	}
    +
    +//static char msg3[50];
    +//memset(msg3, 0, sizeof(msg3));
    +//snprintf(msg3, sizeof(msg3), "%10.3f, %10.3f, %10.3f",
    +//e0, e1, e2);
    +//put_status(msg3);
    +
     }
     
     char bitstatus[100];
    @@ -1656,6 +1713,14 @@ int psk::rx_process(const double *buf, int len)
     // transmit processes
     //=====================================================================
     
    +void psk::transmit(double *buf, int len)
    +{
    +//	if (btn_imd_on->value())
    +		for (int i = 0; i < len; i++) xmtfilt->Irun(buf[i], buf[i]);
    +
    +	ModulateXmtr(buf, len);
    +}
    +
     #define SVP_MASK 0xF
     #define SVP_COUNT (SVP_MASK + 1)
     
    @@ -1725,8 +1790,11 @@ void psk::tx_carriers()
     			} else {
     				outbuf[i] = (ival * cos(phaseacc[car]) + qval * sin(phaseacc[car])) / numcarriers;
     			}
    -			if (maxamp < fabs(outbuf[i]))
    -				maxamp = fabs(outbuf[i]);
    +// create an imd value
    +			double maxmag = xmtimd->value();
    +			if (btn_imd_on->value())
    +				if (fabs(outbuf[i]) > maxmag)
    +					outbuf[i] = maxmag * (outbuf[i] < 0 ? -1 : 1);
     
     			phaseacc[car] += delta[car];
     			if (phaseacc[car] > TWOPI) phaseacc[car] -= TWOPI;
    @@ -1746,11 +1814,16 @@ void psk::tx_carriers()
     		}
     	}
     
    +	maxamp = 0;
    +	for (int i = 0; i < symbollen; i++)
    +		if (maxamp < fabs(outbuf[i])) maxamp = fabs(outbuf[i]);
    +	maxamp *= 1.02;
     	if (maxamp) {
    -		for (int i = 0; i < symbollen; i++) outbuf[i] *= (0.9 * maxamp);
    +		for (int i = 0; i < symbollen; i++)
    +			outbuf[i] /= maxamp;
     	}
     
    -	ModulateXmtr(outbuf, symbollen);
    +	transmit(outbuf, symbollen);
     }
     
     void psk::tx_symbol(int sym)
    @@ -2033,11 +2106,17 @@ void psk::tx_flush()
     		for (int i=0; i to clear bit accumulators on both Tx and Rx ends.
     		}
    +
     		int symbol;
     		if (_16psk) symbol = 8;
     		else if (_8psk) symbol = 4;
     		else symbol = 2;
    -		for (int i = 0; i < dcdbits; i++)
    +
    +		int _dcdbits = dcdbits - 1;
    +		if(progStatus.psk8DCDShortFlag)
    +			_dcdbits  = 32/(symbits - 1);
    +
    +		for (int i = 0; i <= _dcdbits; i++) // DCD window is only 32-bits wide
     			tx_symbol(symbol); // 0 degrees
     							   // Standard BPSK postamble
     							   // DCD off sequence (unmodulated carrier)
    @@ -2059,6 +2138,12 @@ int psk::tx_process()
     {
     	int c;
     
    +	// DCD window is only 32 bits, send a maximum of 3-times.
    +	if(progStatus.psk8DCDShortFlag) {
    +		if ( (_8psk || _xpsk || _16psk) && preamble > 96)
    +			preamble = 96;
    +	}
    +
     	if (preamble > 0) {
     		if (_pskr || ((_xpsk || _8psk || _16psk) && !_disablefec) ) {
     			if (startpreamble == true) {
    @@ -2135,7 +2220,7 @@ void psk::initSN_IMD()
     	m_NCount = 0;
     
     	COEF[0] = 2.0 * cos(TWOPI * 9 / GOERTZEL);
    -	COEF[1] = 2.0 * cos(TWOPI * 18 / GOERTZEL);
    +	COEF[1] = 2.0 * cos(TWOPI * 36 / GOERTZEL);
     	COEF[2] = 2.0 * cos(TWOPI  * 27 / GOERTZEL);
     }
     
    diff --git a/src/qrunner/qrunner.cxx b/src/qrunner/qrunner.cxx
    index 5f26ae12..55225f60 100644
    --- a/src/qrunner/qrunner.cxx
    +++ b/src/qrunner/qrunner.cxx
    @@ -47,6 +47,44 @@
     #  define QRUNNER_EAGAIN() ((errno = WSAGetLastError()) == WSAEWOULDBLOCK)
     #endif
     
    +const char *sztid[] = {
    +	"INVALID_TID",
    +	"TRX_TID",
    +	"QRZ_TID",
    +	"RIGCTL_TID",
    +	"NORIGCTL_TID",
    +	"EQSL_TID",
    +	"ADIF_RW_TID",
    +	"XMLRPC_TID",
    +	"ARQ_TID",
    +	"ARQSOCKET_TID",
    +	"MACLOGGER_TID",
    +	"KISS_TID",
    +	"KISSSOCKET_TID",
    +	"FLMAIN_TID"
    +};
    +
    +static pthread_mutex_t mlog = PTHREAD_MUTEX_INITIALIZER;
    +void qrunner_debug(int tid, const char *name)
    +{
    +	// disabled !
    +	return;
    +
    +	if (tid > ((int)sizeof(sztid)-1)) tid = 0;
    +	else tid++;
    +
    +	if (tid < 2) return;
    +
    +	pthread_mutex_lock(&mlog);
    +	FILE *fd = (FILE *)0;
    +	fd = fopen("qrunner.txt", "a");
    +	if(fd) {
    +		fprintf(fd, "%s, %s\n", sztid[tid], name);
    +		fclose(fd);
    +	}
    +	pthread_mutex_unlock(&mlog);
    +}
    +
     qrunner::qrunner()
             : attached(false), inprog(false), drop_flag(false)
     {
    @@ -101,6 +139,7 @@ void qrunner::execute(int fd, void *arg)
     
     	if (qr->inprog)
     		return;
    +
     	qr->inprog = true;
     
     	size_t n = QRUNNER_READ(fd, rbuf, FIFO_SIZE);
    @@ -113,8 +152,9 @@ void qrunner::execute(int fd, void *arg)
     	case 0:
     		break;
     	default:
    -		while (n--)
    +		while (n--) {
     			qr->fifo->execute();
    +		}
     	}
     
     	qr->inprog = false;
    diff --git a/src/rigcontrol/FreqControl.cxx b/src/rigcontrol/FreqControl.cxx
    index 40cfb9c6..6b628c59 100644
    --- a/src/rigcontrol/FreqControl.cxx
    +++ b/src/rigcontrol/FreqControl.cxx
    @@ -405,7 +405,7 @@ void cFreqControl::cancel_kb_entry(void)
     
     int cFreqControl::handle(int event)
     {
    -	static Fl_Widget* fw = NULL;
    +//	static Fl_Widget* fw = NULL;
     	int d;
     
     	switch (event) {
    @@ -415,18 +415,18 @@ int cFreqControl::handle(int event)
     	case FL_UNFOCUS:
     		return 1;
     	case FL_ENTER:
    -		fw = Fl::focus();
    -		if (fw != NULL) // if NULL then fldigi did not have focus
    -			take_focus();
    +//		fw = Fl::focus();
    +//		if (fw != NULL) // if NULL then fldigi did not have focus
    +//			take_focus();
     		break;
     	case FL_LEAVE:
    -		if (fw)
    -			fw->take_focus();
    -		if (Fl::has_timeout((Fl_Timeout_Handler)blink_point, this))
    -			cancel_kb_entry();
    -		clear_focus();
    -		updatevalue();
    -		return 1;
    +//		if (fw)
    +//			fw->take_focus();
    +//		if (Fl::has_timeout((Fl_Timeout_Handler)blink_point, this))
    +//			cancel_kb_entry();
    +//		clear_focus();
    +//		updatevalue();
    +//		return 1;
     		break;
     
     	case FL_KEYBOARD:
    diff --git a/src/rigcontrol/hamlib.cxx b/src/rigcontrol/hamlib.cxx
    index 4bb75d5d..72952642 100644
    --- a/src/rigcontrol/hamlib.cxx
    +++ b/src/rigcontrol/hamlib.cxx
    @@ -284,15 +284,14 @@ bool hamlib_init(bool bPtt)
     		return false;
     	}
     
    -	LOG_DEBUG("trying frequency request");
     	try {
     		if ( !xcvr->canGetFreq() ) need_freq = false; // getFreq will return setFreq value
     		else {
     			need_freq = true;
     			freq = xcvr->getFreq();
    -			if (freq <= 0) {
    -				xcvr->close();
    -				show_error(__func__, "Rig not responding");
    +			if ((long)freq <= 0) {
    +				xcvr->close(true);
    +				LOG_ERROR("%s","Hamlib xcvr not responding");
     				return false;
     			}
     		}
    @@ -302,12 +301,12 @@ bool hamlib_init(bool bPtt)
     		need_freq = false;
     	}
     	if (!need_freq) {
    -		xcvr->close();
    -		LOG_VERBOSE("Failed freq test");
    +		xcvr->close(true);
    +		LOG_INFO("Failed freq test");
     		return false;
     	}
     
    -	LOG_DEBUG("trying mode request");
    +	LOG_INFO("trying mode request");
     	try {
     		if ( !xcvr->canGetMode() ) need_mode = false;
     		else {
    @@ -316,13 +315,13 @@ bool hamlib_init(bool bPtt)
     		}
     	}
     	catch (const RigException& Ex) {
    -		show_error("Get Mode", Ex.what());
    +		LOG_ERROR("Get Mode %s", Ex.what());
     		need_mode = false;
     	}
     
     	try {
     		if (hamlib_ptt == true) {
    -			LOG_VERBOSE("trying PTT");
    +			LOG_INFO("trying PTT");
     			if (!xcvr->canSetPTT())
     				hamlib_ptt = false;
     			else
    @@ -330,7 +329,7 @@ bool hamlib_init(bool bPtt)
     		}
     	}
     	catch (const RigException& Ex) {
    -		show_error("Set Ptt", Ex.what());
    +		LOG_ERROR("Set Ptt %s", Ex.what());
     		hamlib_ptt = false;
     	}
     
    @@ -379,6 +378,7 @@ void hamlib_close(void)
     
     bool hamlib_active(void)
     {
    +	if (!xcvr) return false;
     	return (xcvr->isOnLine());
     }
     
    @@ -388,23 +388,24 @@ void hamlib_set_ptt(int ptt)
     		return;
     	if (!hamlib_ptt)
     		return;
    -	pthread_mutex_lock(&hamlib_mutex);
    -		try {
    -			xcvr->setPTT(ptt ? RIG_PTT_ON : RIG_PTT_OFF);
    -			hamlib_bypass = ptt ? true : false;
    -		}
    -		catch (const RigException& Ex) {
    -			show_error("Rig PTT", Ex.what());
    -			hamlib_ptt = false;
    -		}
    -	pthread_mutex_unlock(&hamlib_mutex);
    +	guard_lock hamlib(&hamlib_mutex);
    +	try {
    +		xcvr->setPTT( ptt ? 
    +			(progdefaults.hamlib_ptt_on_data ? RIG_PTT_ON_DATA : RIG_PTT_ON_MIC) :
    +			RIG_PTT_OFF );
    +		hamlib_bypass = ptt ? true : false;
    +	}
    +	catch (const RigException& Ex) {
    +		show_error("Rig PTT", Ex.what());
    +		hamlib_ptt = false;
    +	}
     }
     
     void hamlib_set_qsy(long long f)
     {
     	if (xcvr->isOnLine() == false)
     		return;
    -	pthread_mutex_lock(&hamlib_mutex);
    +	guard_lock hamlib(&hamlib_mutex);
     	double fdbl = f;
     	hamlib_qsy = false;
     	try {
    @@ -416,26 +417,26 @@ void hamlib_set_qsy(long long f)
     		show_error("QSY", Ex.what());
     		hamlib_passes = 0;
     	}
    -	pthread_mutex_unlock(&hamlib_mutex);
     }
     
     int hamlib_setfreq(long f)
     {
     	if (xcvr->isOnLine() == false)
     		return -1;
    -	pthread_mutex_lock(&hamlib_mutex);
    -		try {
    -			LOG_DEBUG("%ld", f);
    -			xcvr->setFreq(f);
    -		}
    -		catch (const RigException& Ex) {
    -			show_error("SetFreq", Ex.what());
    -			hamlib_passes = 0;
    -		}
    -	pthread_mutex_unlock(&hamlib_mutex);
    +	guard_lock hamlib(&hamlib_mutex);
    +	try {
    +		LOG_DEBUG("%ld", f);
    +		xcvr->setFreq(f);
    +	}
    +	catch (const RigException& Ex) {
    +		show_error("SetFreq", Ex.what());
    +		hamlib_passes = 0;
    +	}
     	return 1;
     }
     
    +static int hamlib_wait = 0;
    +
     int hamlib_setmode(rmode_t m)
     {
     	if (need_mode == false)
    @@ -443,39 +444,40 @@ int hamlib_setmode(rmode_t m)
     	if (xcvr->isOnLine() == false)
     		return -1;
     #if 0
    -	pthread_mutex_lock(&hamlib_mutex);
    -		try {
    -			hamlib_rmode = xcvr->getMode(hamlib_pbwidth);
    -			xcvr->setMode(m, hamlib_pbwidth);
    -			hamlib_rmode = m;
    -		}
    -		catch (const RigException& Ex) {
    -			show_error("Set Mode", Ex.what());
    -			hamlib_passes = 0;
    -		}
    -	pthread_mutex_unlock(&hamlib_mutex);
    +	guard_lock hamlib(&hamlib_mutex);
    +	try {
    +		hamlib_rmode = xcvr->getMode(hamlib_pbwidth);
    +		xcvr->setMode(m, hamlib_pbwidth);
    +		hamlib_rmode = m;
    +	}
    +	catch (const RigException& Ex) {
    +		show_error("Set Mode", Ex.what());
    +		hamlib_passes = 0;
    +	}
    +	hamlib_wait = progdefaults.hamlib_mode_delay / 100;
     #else
     	hamlib_rmode = m;
     #endif
     	return 1;
     }
     
    +// width control via hamlib is not implemented
    +
     int hamlib_setwidth(pbwidth_t w)
     {
     	if (xcvr->isOnLine() == false)
     		return -1;
     #if 0
    -	pthread_mutex_lock(&hamlib_mutex);
    -		try {
    -			hamlib_rmode = xcvr->getMode(hamlib_pbwidth);
    -			xcvr->setMode(hamlib_rmode, w);
    -			hamlib_pbwidth = w;
    -		}
    -		catch (const RigException& Ex) {
    -			show_error("Set Width", Ex.what());
    -			hamlib_passes = 0;
    -		}
    -	pthread_mutex_unlock(&hamlib_mutex);
    +	guard_lock hamlib(&hamlib_mutex);
    +	try {
    +		hamlib_rmode = xcvr->getMode(hamlib_pbwidth);
    +		xcvr->setMode(hamlib_rmode, w);
    +		hamlib_pbwidth = w;
    +	}
    +	catch (const RigException& Ex) {
    +		show_error("Set Width", Ex.what());
    +		hamlib_passes = 0;
    +	}
     #endif
     	return 1;
     }
    @@ -490,83 +492,72 @@ pbwidth_t hamlib_getwidth()
     	return hamlib_pbwidth;
     }
     
    +bool hamlib_USB()
    +{
    +	if (hamlib_wait) return wf->USB();
    +	bool islsb = false;
    +	if (progdefaults.HamlibSideband == SIDEBAND_RIG) {
    +		islsb = (hamlib_rmode == RIG_MODE_LSB ||
    +				 hamlib_rmode == RIG_MODE_PKTLSB ||
    +				 hamlib_rmode == RIG_MODE_ECSSLSB);
    +		if (hamlib_rmode == RIG_MODE_CW) {
    +			if (progdefaults.hamlib_cw_islsb) islsb = true;
    +			else islsb = false;
    +		}
    +		if (hamlib_rmode == RIG_MODE_CWR) {
    +			if (progdefaults.hamlib_cw_islsb) islsb = false;
    +			else islsb = true;
    +		}
    +		if (hamlib_rmode == RIG_MODE_RTTY) {
    +			if (progdefaults.hamlib_rtty_isusb) islsb = false;
    +			else islsb = true;
    +		}
    +		if (hamlib_rmode == RIG_MODE_RTTYR) {
    +			if (progdefaults.hamlib_rtty_isusb) islsb = true;
    +			else islsb = false;
    +		}
    +	} else if (progdefaults.HamlibSideband == SIDEBAND_LSB)
    +		islsb = true;
    +	return !islsb;
    +}
    +
     static void *hamlib_loop(void *args)
     {
     	SET_THREAD_ID(RIGCTL_TID);
     
     	long int freq = 0L;
     	rmode_t  numode = RIG_MODE_USB;
    -	bool freqok = false, modeok = false;
    -
     	dl_fldigi::hbtint::rig_set_mode(modeString(numode));
    +
     	for (;;) {
     		MilliSleep(100);
     		if (hamlib_exit)
     			break;
     		if (hamlib_bypass)
     			continue;
    -// hamlib locked while accessing hamlib serial i/o
    -		pthread_mutex_lock(&hamlib_mutex);
    -
    -		if (need_freq) {
    -			freq_t f;
    -			try {
    -				f = xcvr->getFreq();
    -				freq = (long int) f;
    -				freqok = true;
    -			}
    -			catch (const RigException& Ex) {
    -				show_error(__func__, "Rig not responding: freq");
    -				freqok = false;
    -			}
    -		}
    -#if 0
    -		if (hamlib_exit)
    -			break;
    -
    -		if (need_mode && hamlib_rmode == numode) {
    -			try {
    -				numode = xcvr->getMode(hamlib_pbwidth);
    -				modeok = true;
    -			}
    -			catch (const RigException& Ex) {
    -				show_error(__func__, "Rig not responding: mode");
    -				modeok = false;
    -			}
    -		}
    -#endif
    -		pthread_mutex_unlock(&hamlib_mutex);
    -
    -		if (hamlib_exit)
    -			break;
    -		if (hamlib_bypass)
    +		if (hamlib_wait) {
    +			hamlib_wait--;
     			continue;
    -
    -		if (freqok && freq && (freq != hamlib_freq)) {
    -			hamlib_freq = freq;
    -			show_frequency(hamlib_freq);
    -			wf->rfcarrier(hamlib_freq);
     		}
     
    -		if (freqok && freq)
    -			dl_fldigi::hbtint::rig_set_freq(freq);
    -
    -		if (modeok && (hamlib_rmode != numode)) {
    -			hamlib_rmode = numode;
    -			show_mode(modeString(numode));
    -			if (progdefaults.HamlibSideband != SIDEBAND_RIG)
    -				wf->USB(progdefaults.HamlibSideband == SIDEBAND_USB);
    -			else
    -				wf->USB(!(hamlib_rmode == RIG_MODE_LSB ||
    -					  hamlib_rmode == RIG_MODE_CWR ||
    -					  hamlib_rmode == RIG_MODE_PKTLSB ||
    -					  hamlib_rmode == RIG_MODE_ECSSLSB ||
    -					  hamlib_rmode == RIG_MODE_RTTY));
    -			dl_fldigi::hbtint::rig_set_mode(modeString(numode));
    +		{
    +			guard_lock hamlib(&hamlib_mutex);
    +			if (need_freq) {
    +				freq_t f;
    +				try {
    +					f = xcvr->getFreq();
    +					freq = (long int) f;
    +					if (freq == 0) continue;
    +					hamlib_freq = freq;
    +					show_frequency(hamlib_freq);
    +					wf->rfcarrier(hamlib_freq);
    +					dl_fldigi::hbtint::rig_set_freq(freq);
    +				}
    +				catch (const RigException& Ex) {
    +					show_error(__func__, "Rig not responding: freq");
    +				}
    +			}
     		}
    -
    -		if (hamlib_exit)
    -			break;
     	}
     
     	hamlib_closed = true;
    diff --git a/src/rigcontrol/norig.cxx b/src/rigcontrol/norig.cxx
    new file mode 100644
    index 00000000..7fe1d180
    --- /dev/null
    +++ b/src/rigcontrol/norig.cxx
    @@ -0,0 +1,120 @@
    +// ----------------------------------------------------------------------------
    +// norig.cxx
    +//
    +// Copyright (C) 2016
    +//		Dave Freese, W1HKJ
    +//
    +// This file is part of fldigi.
    +//
    +// Fldigi 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.
    +//
    +// Fldigi 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 fldigi.  If not, see .
    +// ----------------------------------------------------------------------------
    +
    +#include 
    +
    +#include 
    +#include 
    +#include 
    +#include 
    +#include 
    +#include 
    +
    +#ifdef RIGCATTEST
    +	#include "rigCAT.h"
    +#else
    +	#include "fl_digi.h"
    +	#include "misc.h"
    +	#include "configuration.h"
    +#endif
    +
    +#include "rigsupport.h"
    +#include "rigxml.h"
    +#include "trx.h"
    +#include "serial.h"
    +#include "rigio.h"
    +#include "debug.h"
    +#include "threads.h"
    +#include "qrunner.h"
    +#include "confdialog.h"
    +#include "status.h"
    +
    +//----------------------------------------------------------------------
    +// functions used when no xcvr control is in use
    +//----------------------------------------------------------------------
    +
    +long long noCAT_getfreq() {
    +	return progStatus.noCATfreq;
    +}
    +
    +void noCAT_setfreq(long long f)
    +{
    +	progStatus.noCATfreq = f;
    +	wf->rfcarrier(f);
    +}
    +
    +std::string noCAT_getmode()
    +{
    +	return progStatus.noCATmode;
    +}
    +
    +void noCAT_setmode(const std::string &md)
    +{
    +	progStatus.noCATmode = md;
    +	if (ModeIsLSB(md))
    +		wf->USB(false);
    +	else
    +		wf->USB(true);
    +}
    +
    +std::string noCAT_getwidth()
    +{
    +	return progStatus.noCATwidth;
    +}
    +
    +void noCAT_setwidth(const std::string &w)
    +{
    +	progStatus.noCATwidth = w;
    +	show_bw(w);
    +}
    +
    +void noCAT_setPTT(bool val)
    +{
    +	rigio.SetPTT(val); // always execute the h/w ptt if enabled
    +}
    +
    +void noCAT_init()
    +{
    +	qso_setFreq(progStatus.noCATfreq);
    +	wf->rfcarrier(progStatus.noCATfreq);
    +	init_NoRig_RigDialog();
    +
    +	qso_opMODE->value(progStatus.noCATmode.c_str());
    +
    +	chkUSEHAMLIB->value(0);
    +	chkUSEHAMLIB->redraw();
    +	btnInitHAMLIB->labelcolor(FL_BLACK);
    +	btnInitHAMLIB->redraw_label();
    +
    +	chkUSEXMLRPC->value(0);
    +	chkUSEXMLRPC->redraw();
    +	btnInitXMLRPC->labelcolor(FL_BLACK);
    +	btnInitXMLRPC->redraw_label();
    +
    +	chkUSERIGCAT->value(0);
    +	chkUSERIGCAT->redraw();
    +	btnInitRIGCAT->labelcolor(FL_BLACK);
    +	btnInitRIGCAT->redraw_label();
    +
    +	return;
    +}
    +
    diff --git a/src/rigcontrol/ptt.cxx b/src/rigcontrol/ptt.cxx
    index 2dda9749..368c6fa1 100644
    --- a/src/rigcontrol/ptt.cxx
    +++ b/src/rigcontrol/ptt.cxx
    @@ -9,6 +9,8 @@
     // Copyright (C) 2009
     //		Diane Bruce, VA3DB
     //
    +// Added gpio for PTT (Lior KK6BWA)
    +//
     // This file is part of fldigi.  Adapted from code contained in gmfsk source code
     // distribution.
     //  gmfsk Copyright (C) 2001, 2002, 2003
    @@ -60,6 +62,8 @@
     #include "re.h"
     #include "debug.h"
     
    +#include "fl_digi.h"
    +
     LOG_FILE_SOURCE(debug::LOG_RIGCONTROL);
     
     using namespace std;
    @@ -104,6 +108,9 @@ void PTT::reset(ptt_t dev)
     	case PTT_TTY:
     		open_tty();
     		break;
    +	case PTT_GPIO:
    +		open_gpio();
    +		break;
     	default:
     		break; // nothing to open
     	}
    @@ -113,10 +120,8 @@ void PTT::reset(ptt_t dev)
     void PTT::set(bool ptt)
     {
     // add milliseconds - no audio to clear virtual audio card used by Flex systems
    -	if (ptt && progdefaults.PTT_off_delay)
    +	if (!ptt && progdefaults.PTT_off_delay)
     		MilliSleep(progdefaults.PTT_off_delay);
    -	if (!ptt && progdefaults.PTT_on_delay)
    -		MilliSleep(progdefaults.PTT_on_delay);
     
     	if (active_modem == cw_modem &&
     	    ((progdefaults.useCWkeylineRTS) || progdefaults.useCWkeylineDTR == true))
    @@ -124,6 +129,7 @@ void PTT::set(bool ptt)
     
     	switch (pttdev) {
     	case PTT_NONE: default:
    +		noCAT_setPTT(ptt);
     		break;
     #if USE_HAMLIB
     	case PTT_HAMLIB:
    @@ -136,6 +142,9 @@ void PTT::set(bool ptt)
     	case PTT_TTY:
     		set_tty(ptt);
     		break;
    +	case PTT_GPIO:
    +		set_gpio(ptt);
    +		break;
     #if HAVE_PARPORT
     	case PTT_PARPORT:
     		set_parport(ptt);
    @@ -147,6 +156,11 @@ void PTT::set(bool ptt)
     		break;
     #endif
     	}
    +	if (ptt && progdefaults.PTT_on_delay)
    +		MilliSleep(progdefaults.PTT_on_delay);
    +
    +	if (ptt) start_tx_timer();
    +	else     stop_tx_timer();
     }
     
     void PTT::close_all(void)
    @@ -157,6 +171,9 @@ void PTT::close_all(void)
     	case PTT_TTY:
     		close_tty();
     		break;
    +	case PTT_GPIO:
    +		close_gpio();
    +		break;
     #if HAVE_PARPORT
     	case PTT_PARPORT:
     		close_parport();
    @@ -173,6 +190,38 @@ void PTT::close_all(void)
     	pttfd = -1;
     }
     
    +//-------------------- gpio port PTT --------------------//
    +void PTT::open_gpio(void)
    +{
    +}
    +
    +void PTT::close_gpio(void)
    +{
    +}
    +
    +void PTT::set_gpio(bool ptt)
    +{
    +#define VALUE_MAX 30 
    +	static const char s_values_str[] = "01";
    +
    +	char path[VALUE_MAX];
    +
    +	snprintf(path, VALUE_MAX, "/sys/class/gpio/gpio%d/value", progdefaults.GPIOPort);
    +	int fd = open(path, O_WRONLY);
    +	if (-1 == fd) {
    +		LOG_ERROR("Failed to open gpio (%s) value for writing!\n", path);
    +		return;
    +	}
    +
    +	if (1 != write(fd, &s_values_str[ ptt ? 1 : 0], 1)) {
    +		LOG_ERROR("Failed to write value!\n");
    +		return;
    +	}
    +
    +	close(fd);
    +
    +}
    +
     //-------------------- serial port PTT --------------------//
     
     void PTT::open_tty(void)
    diff --git a/src/rigcontrol/rigclass.cxx b/src/rigcontrol/rigclass.cxx
    index f2b661c7..4a759f64 100644
    --- a/src/rigcontrol/rigclass.cxx
    +++ b/src/rigcontrol/rigclass.cxx
    @@ -50,6 +50,8 @@ Rig::Rig(rig_model_t rig_model)
     
     Rig::~Rig()
     {
    +	LOG_INFO("Rig destroy %p", rig);
    +	if (!rig) return;
     	close();
     }
     
    @@ -58,7 +60,7 @@ void Rig::init(rig_model_t rig_model)
     	close();
     	if ((rig = rig_init(rig_model)) == NULL)
     		throw RigException ("Could not initialize rig");
    -	LOG_VERBOSE("Initialised rig model %d: %s", rig_model, getName());
    +	LOG_INFO("Initialised rig model %d: %s", rig_model, getName());
     }
     
     const char *Rig::getName()
    @@ -78,9 +80,11 @@ void Rig::open(void)
     		throw RigException(err);
     }
     
    -void Rig::close(void)
    +void Rig::close(bool abort)
     {
    -	if (rig) {
    +	if (abort)
    +		rig = NULL;
    +	else if (rig) {
     		rig_close(rig);
     		rig_cleanup(rig);
     		rig = NULL;
    @@ -209,7 +213,7 @@ void Rig::setConf(token_t token, const char *val)
     }
     void Rig::setConf(const char *name, const char *val)
     {
    -	LOG_VERBOSE("setting \"%s\" to \"%s\"", name, val);
    +	LOG_INFO("setting \"%s\" to \"%s\"", name, val);
     	int err = rig_set_conf(rig, tokenLookup(name), val);
     	if (err != RIG_OK)
     		throw RigException(name, err);
    diff --git a/src/rigcontrol/rigio.cxx b/src/rigcontrol/rigio.cxx
    index ae38383f..9fe48836 100644
    --- a/src/rigcontrol/rigio.cxx
    +++ b/src/rigcontrol/rigio.cxx
    @@ -58,14 +58,11 @@ static pthread_t		rigCAT_thread;
     
     static bool			rigCAT_exit = false;
     static bool			rigCAT_open = false;
    -static bool			rigCAT_bypass = false;
     
     static string		sRigWidth = "";
     static string		sRigMode = "";
     static long long	llFreq = 0;
     
    -static bool nonCATrig = false;
    -
     static void *rigCAT_loop(void *args);
     
     #define RXBUFFSIZE 2000
    @@ -89,11 +86,19 @@ bool sendCommand (string s, int retnbr, int waitval)
     			numread * (9 + progdefaults.RigCatStopbits) *
     			1000.0 / rigio.Baud() );
     
    -	LOG_DEBUG("%s", str2hex(s.data(), s.length()));
    +	if (xmlrig.debug)
    +		LOG_INFO("%s",
    +			xmlrig.ascii ? s.c_str() : str2hex(s.data(), s.length()));
    +
    +	if (xmlrig.noserial) {
    +		memset(replybuff, 0, RXBUFFSIZE + 1);
    +		numread = 0;
    +		return true;
    +	}
     
     	retval = rigio.WriteBuffer((unsigned char *)s.c_str(), numwrite);
     	if (retval <= 0)
    -		LOG_VERBOSE("Write error %d", retval);
    +		LOG_ERROR("Write error %d", retval);
     
     	if (retnbr == 0) return true;
     
    @@ -115,7 +120,9 @@ bool sendCommand (string s, int retnbr, int waitval)
     		replybuff[numread] = retbuf[0];
     		numread++;
     	}
    -	LOG_DEBUG("reply %s", str2hex(replybuff, numread));
    +	if (xmlrig.debug)
    +		LOG_INFO("reply %s",
    +			xmlrig.ascii ? (const char *)(replybuff) : str2hex(replybuff, numread));
     	if (numread > retnbr) {
     		memmove(replybuff, replybuff + numread - retnbr, retnbr);
     		numread = retnbr;
    @@ -319,27 +326,29 @@ long long fm_freqdata(DATA d, size_t p)
     
     long long rigCAT_getfreq(int retries, bool &failed, int waitval)
     {
    +	const char symbol[] = "GETFREQ";
    +	failed = false;
    +	if (rigCAT_exit || xmlrig.noserial || !xmlrig.xmlok) {
    +		failed = true;
    +		return progStatus.noCATfreq;
    +	}
    +
     	XMLIOS modeCmd;
     	list::iterator itrCmd;
     	string strCmd;
     	size_t p = 0, len1 = 0, len2 = 0, pData = 0;
     	long long f = 0;
     
    -	failed = false;
    -	if (nonCATrig) {
    -		failed = true;
    -		return progStatus.noCATfreq;
    -	}
    -
     	itrCmd = commands.begin();
     	while (itrCmd != commands.end()) {
    -		if ((*itrCmd).SYMBOL == "GETFREQ")
    +		if ((*itrCmd).SYMBOL == symbol)
     			break;
     		++itrCmd;
     	}
     
     	if (itrCmd == commands.end()) {
     		failed = true;
    +		if (xmlrig.debug) LOG_INFO("%s not defined", symbol);
     		return progStatus.noCATfreq; // get_freq command is not defined!
     	}
     
    @@ -381,7 +390,8 @@ long long rigCAT_getfreq(int retries, bool &failed, int waitval)
     			}
     // send the command
     			if ( !sendCommand(strCmd, rTemp.size, waitval) ) {
    -				LOG_VERBOSE("sendCommand failed");
    +				if (xmlrig.debug)
    +					LOG_INFO("sendCommand failed");
     				goto retry_get_freq;
     			}
     // check the pre data string
    @@ -390,7 +400,7 @@ long long rigCAT_getfreq(int retries, bool &failed, int waitval)
     			if (len1) {
     				for (size_t i = 0; i < len1; i++) {
     					if ((char)rTemp.str1[i] != (char)replybuff[i]) {
    -						LOG_VERBOSE("failed pre data string test @ %" PRIuSZ, i);
    +						LOG_ERROR("failed pre data string test @ %" PRIuSZ, i);
     						goto retry_get_freq;
     					}
     				}
    @@ -409,7 +419,7 @@ long long rigCAT_getfreq(int retries, bool &failed, int waitval)
     			if (len2) {
     				for (size_t i = 0; i < len2; i++)
     					if ((char)rTemp.str2[i] != (char)replybuff[p + i]) {
    -						LOG_VERBOSE("failed post data string test @ %d", static_cast(i));
    +						LOG_ERROR("failed post data string test @ %d", static_cast(i));
     						goto retry_get_freq;
     					}
     			}
    @@ -422,37 +432,31 @@ retry_get_freq: ;
     		}
     	}
     	if (progdefaults.RigCatVSP == false)
    -		LOG_VERBOSE("Retries failed");
    +		LOG_ERROR("%s failed", symbol);
     	failed = true;
     	return 0;
     }
     
     void rigCAT_setfreq(long long f)
     {
    -	{
    -		guard_lock ser_guard( &rigCAT_mutex );
    -		if (rigCAT_exit) return;
    +	const char symbol[] = "SETFREQ";
    +	if (rigCAT_exit || xmlrig.noserial || !xmlrig.xmlok) {
    +		progStatus.noCATfreq = f;
     	}
    +	if (rigCAT_exit || !xmlrig.xmlok) return;
    +
     	XMLIOS modeCmd;
     	list::iterator itrCmd;
     	string strCmd;
     
    -	progStatus.noCATfreq = f;
    -
    -	if (nonCATrig) {
    -		return;
    -	}
    -
    -//	LOG_DEBUG("set frequency %lld", f);
    -
     	itrCmd = commands.begin();
     	while (itrCmd != commands.end()) {
    -		if ((*itrCmd).SYMBOL == "SETFREQ")
    +		if ((*itrCmd).SYMBOL == symbol)
     			break;
     		++itrCmd;
     	}
     	if (itrCmd == commands.end()) {
    -		LOG_VERBOSE("SET_FREQ not defined");
    +		if (xmlrig.debug) LOG_INFO("%s not defined", symbol);
     		return;
     	}
     
    @@ -491,15 +495,18 @@ void rigCAT_setfreq(long long f)
     		}
     	}
     	if (progdefaults.RigCatVSP == false)
    -		LOG_VERBOSE("Retries failed");
    +		LOG_ERROR("%s failed", symbol);
     }
     
     string rigCAT_getmode()
     {
    -	{
    -		guard_lock ser_guard( &rigCAT_mutex );
    -		if (rigCAT_exit) return "";
    -	}
    +	const char symbol[] = "GETMODE";
    +
    +	if (rigCAT_exit || xmlrig.noserial || !xmlrig.xmlok)
    +		return progStatus.noCATmode;
    +
    +//	guard_lock ser_guard( &rigCAT_mutex );
    +
     	XMLIOS modeCmd;
     	list::iterator itrCmd;
     	list::iterator mode;
    @@ -507,17 +514,16 @@ string rigCAT_getmode()
     	string strCmd, mData;
     	size_t len;
     
    -	if (nonCATrig)
    -		return progStatus.noCATmode;
    -
     	itrCmd = commands.begin();
     	while (itrCmd != commands.end()) {
    -		if ((*itrCmd).SYMBOL == "GETMODE")
    +		if ((*itrCmd).SYMBOL == symbol)
     			break;
     		++itrCmd;
     	}
    -	if (itrCmd == commands.end())
    +	if (itrCmd == commands.end()) {
    +		if (xmlrig.debug) LOG_INFO("%s not defined", symbol);
     		return progStatus.noCATmode;
    +	}
     
     	modeCmd = *itrCmd;
     
    @@ -557,7 +563,7 @@ string rigCAT_getmode()
     			if (len) {
     				for (size_t i = 0; i < len; i++)
     					if ((char)rTemp.str1[i] != (char)replybuff[i]) {
    -						LOG_VERBOSE("failed pre data string test @ %" PRIuSZ, i);
    +						LOG_ERROR("failed pre data string test @ %" PRIuSZ, i);
     						goto retry_get_mode;
     					}
     				p = len;
    @@ -603,29 +609,27 @@ retry_get_mode: ;
     		}
     	}
     	if (progdefaults.RigCatVSP == false)
    -		LOG_VERBOSE("Retries failed");
    +		LOG_ERROR("%s failed", symbol);
     	return "";
     }
     
     void rigCAT_setmode(const string& md)
     {
    -	{
    -		guard_lock ser_guard( &rigCAT_mutex );
    -		if (rigCAT_exit) return;
    -	}
    +	const char symbol[] = "SETMODE";
    +
    +
    +	if (rigCAT_exit || xmlrig.noserial || !xmlrig.xmlok)
    +		progStatus.noCATmode = md;
    +
    +	if (rigCAT_exit || !xmlrig.xmlok) return;
    +
     	XMLIOS modeCmd;
     	list::iterator itrCmd;
     	string strCmd;
     
    -	progStatus.noCATmode = md;
    -
    -	if (nonCATrig) {
    -		return;
    -	}
    -
     	itrCmd = commands.begin();
     	while (itrCmd != commands.end()) {
    -		if ((*itrCmd).SYMBOL == "SETMODE")
    +		if ((*itrCmd).SYMBOL == symbol)
     			break;
     		++itrCmd;
     	}
    @@ -680,45 +684,46 @@ void rigCAT_setmode(const string& md)
     		}
     	}
     	if (progdefaults.RigCatVSP == false)
    -		LOG_VERBOSE("Retries failed");
    +		LOG_ERROR("%s failed", symbol);
     }
     
     string rigCAT_getwidth()
     {
    -	{
    -		guard_lock ser_guard( &rigCAT_mutex );
    -		if (rigCAT_exit) return "";
    -	}
    -	XMLIOS modeCmd;
    +	const char symbol[] = "GETBW";
    +
    +	if (rigCAT_exit || xmlrig.noserial || !xmlrig.xmlok)
    +		return progStatus.noCATwidth;
    +
    +	XMLIOS widthCmd;
     	list::iterator itrCmd;
     	list::iterator bw;
     	list *pbw;
     	string strCmd, mData;
     	size_t len = 0, p = 0, pData = 0;
     
    -	if (nonCATrig)
    -		return progStatus.noCATwidth;
    -
     	itrCmd = commands.begin();
     	while (itrCmd != commands.end()) {
    -		if ((*itrCmd).SYMBOL == "GETBW")
    +		if ((*itrCmd).SYMBOL == symbol)
     			break;
     		++itrCmd;
     	}
    -	if (itrCmd == commands.end())
    +	if (itrCmd == commands.end()) {
    +		if (xmlrig.debug) LOG_INFO("%s not defined", symbol);
     		return "";
    -	modeCmd = *itrCmd;
    +	}
     
    -	if ( modeCmd.str1.empty() == false)
    -		strCmd.append(modeCmd.str1);
    +	widthCmd = *itrCmd;
     
    -	if (modeCmd.str2.empty() == false)
    -		strCmd.append(modeCmd.str2);
    +	if ( widthCmd.str1.empty() == false)
    +		strCmd.append(widthCmd.str1);
     
    -	if (!modeCmd.info.size()) return "";
    +	if (widthCmd.str2.empty() == false)
    +		strCmd.append(widthCmd.str2);
    +
    +	if (!widthCmd.info.size()) return "";
     
     	for (list::iterator preply = reply.begin(); preply != reply.end(); ++preply) {
    -		if (preply->SYMBOL != modeCmd.info)
    +		if (preply->SYMBOL != widthCmd.info)
     			continue;
     
     		XMLIOS  rTemp = *preply;
    @@ -739,14 +744,18 @@ string rigCAT_getwidth()
     
     			p = 0;
     			pData = 0;
    +
     // send the command
    -			if ( !sendCommand(strCmd, rTemp.size, progdefaults.RigCatWait) ) goto retry_get_width;
    +			if ( !sendCommand(strCmd, rTemp.size, progdefaults.RigCatWait) ) {
    +				goto retry_get_width;
    +			}
    +
     // check the pre data string
     			len = rTemp.str1.size();
     			if (len) {
     				for (size_t i = 0; i < len; i++)
     					if ((char)rTemp.str1[i] != (char)replybuff[i]) {
    -						LOG_VERBOSE("failed pre data string test @ %" PRIuSZ, i);
    +						LOG_ERROR("failed pre data string test @ %" PRIuSZ, i);
     						goto retry_get_width;
     					}
     				p = pData = len;
    @@ -759,13 +768,16 @@ string rigCAT_getwidth()
     			len = rTemp.str2.size();
     			if (len) {
     				for (size_t i = 0; i < len; i++)
    -					if ((char)rTemp.str2[i] != (char)replybuff[p + i])
    +					if ((char)rTemp.str2[i] != (char)replybuff[p + i]) {
    +						LOG_ERROR("failed post data string test @ %" PRIuSZ, i);
     						goto retry_get_width;
    +					}
     			}
     // convert the data field
     			mData = "";
     			for (int i = 0; i < rTemp.data.size; i++)
     				mData += (char)replybuff[pData + i];
    +
     // new for FT100 and the ilk that use bit fields
     			if (rTemp.data.size == 1) {
     				unsigned char d = mData[0];
    @@ -774,12 +786,13 @@ string rigCAT_getwidth()
     				d &= rTemp.data.andmask;
     				mData[0] = d;
     			}
    -			if (lbws.empty() == false)
    -				pbw = &lbws;
    -			else if (lbwREPLY.empty() == false)
    +			if (!lbwREPLY.empty())
     				pbw = &lbwREPLY;
    +			else if (lbws.empty() == false)
    +				pbw = &lbws;
     			else
     				goto retry_get_width;
    +
     			bw = pbw->begin();
     			while (bw != pbw->end()) {
     				if ((*bw).BYTES == mData)
    @@ -792,32 +805,31 @@ retry_get_width: ;
     		}
     	}
     	if (progdefaults.RigCatVSP == false)
    -		LOG_VERBOSE("Retries failed");
    +		LOG_ERROR("%s failed", symbol);
     	return "";
     }
     
     void rigCAT_setwidth(const string& w)
     {
    -	{
    -		guard_lock ser_guard( &rigCAT_mutex );
    -		if (rigCAT_exit) return;
    -	}
    +	const char symbol[] = "SETBW";
    +
    +	if (rigCAT_exit || xmlrig.noserial || !xmlrig.xmlok)
    +		progStatus.noCATwidth = w;
    +
    +	if (rigCAT_exit || !xmlrig.xmlok) return;
    +
     	XMLIOS modeCmd;
     	list::iterator itrCmd;
     	string strCmd;
     
    -	if (nonCATrig) {
    -		progStatus.noCATwidth = w;
    -		return;
    -	}
    -
     	itrCmd = commands.begin();
     	while (itrCmd != commands.end()) {
    -		if ((*itrCmd).SYMBOL == "SETBW")
    +		if ((*itrCmd).SYMBOL == symbol)
     			break;
     		++itrCmd;
     	}
     	if (itrCmd == commands.end()) {
    +		if (xmlrig.debug) LOG_INFO("%s not defined", symbol);
     		progStatus.noCATwidth = w;
     		return;
     	}
    @@ -871,31 +883,32 @@ void rigCAT_setwidth(const string& w)
     			if (sendCommand(strCmd, 0, progdefaults.RigCatWait)) return;
     		}
     	}
    -	LOG_VERBOSE("Retries failed");
    +	LOG_ERROR("%s failed", symbol);
     }
     
     void rigCAT_pttON()
     {
    -	{
    -		guard_lock ser_guard( &rigCAT_mutex );
    -		if (rigCAT_exit) return;
    -	}
    +	const char symbol[] = "PTTON";
    +
    +	if (rigCAT_exit) return;
    +
     	XMLIOS modeCmd;
     	list::iterator itrCmd;
     	string strCmd;
     
     	rigio.SetPTT(1); // always execute the h/w ptt if enabled
     
    -	if (nonCATrig) return;
    -
     	itrCmd = commands.begin();
     	while (itrCmd != commands.end()) {
    -		if ((*itrCmd).SYMBOL == "PTTON")
    +		if ((*itrCmd).SYMBOL == symbol)
     			break;
     		++itrCmd;
     	}
    -	if (itrCmd == commands.end())
    +	if (itrCmd == commands.end()) {
    +		if (xmlrig.debug) LOG_INFO("%s not defined", symbol);
     		return;
    +	}
    +
     	modeCmd = *itrCmd;
     
     	if ( modeCmd.str1.empty() == false)
    @@ -927,30 +940,32 @@ void rigCAT_pttON()
     			if (sendCommand(strCmd, 0, progdefaults.RigCatWait)) return;
     		}
     	}
    -	LOG_VERBOSE("Retries failed");
    +	LOG_VERBOSE("%s failed", symbol);
     }
     
     void rigCAT_pttOFF()
     {
    -	{
    -		guard_lock ser_guard( &rigCAT_mutex );
    -		if (rigCAT_exit) return;
    -	}
    +	const char symbol[] = "PTTOFF";
    +
    +	if (rigCAT_exit) return;
    +
     	XMLIOS modeCmd;
     	list::iterator itrCmd;
     	string strCmd;
     
     	rigio.SetPTT(0); // always execute the h/w ptt if enabled
    -	if (nonCATrig) return;
     
     	itrCmd = commands.begin();
     	while (itrCmd != commands.end()) {
    -		if ((*itrCmd).SYMBOL == "PTTOFF")
    +		if ((*itrCmd).SYMBOL == symbol)
     			break;
     		++itrCmd;
     	}
    -	if (itrCmd == commands.end())
    +	if (itrCmd == commands.end()) {
    +		if (xmlrig.debug) LOG_INFO("%s not defined", symbol);
     		return;
    +	}
    +
     	modeCmd = *itrCmd;
     
     	if ( modeCmd.str1.empty() == false)
    @@ -982,22 +997,17 @@ void rigCAT_pttOFF()
     			if (sendCommand(strCmd, 0, progdefaults.RigCatWait)) return;
     		}
     	}
    -	LOG_VERBOSE("Retries failed");
    +	LOG_ERROR("%s failed", symbol);
     }
     
     void rigCAT_sendINIT(const string& icmd, int multiplier)
     {
    -	{
    -		guard_lock ser_guard( &rigCAT_mutex );
    -		if (rigCAT_exit) return;
    -	}
    +	if (rigCAT_exit) return;
    +
     	XMLIOS modeCmd;
     	list::iterator itrCmd;
     	string strCmd;
     
    -	if (nonCATrig)
    -		return;
    -
     	itrCmd = commands.begin();
     	while (itrCmd != commands.end()) {
     		if ((*itrCmd).SYMBOL == icmd)
    @@ -1037,7 +1047,7 @@ void rigCAT_sendINIT(const string& icmd, int multiplier)
     			if (sendCommand(strCmd, 0, progdefaults.RigCatInitDelay)) return;
     		}
     	}
    -	LOG_VERBOSE("Retries failed");
    +	LOG_ERROR("INIT failed");
     }
     
     void rigCAT_defaults()
    @@ -1054,6 +1064,7 @@ void rigCAT_defaults()
     	cntRigCatTimeout->value(xmlrig.timeout);
     	cntRigCatWait->value(xmlrig.write_delay);
     	cntRigCatInitDelay->value(xmlrig.init_delay);
    +//	cntRigCatWaitForDevice->value(xmlrig.wait_for_device);
     	btnRigCatEcho->value(xmlrig.echo);
     	btnRigCatCMDptt->value(xmlrig.cmdptt);
     	chkRigCatVSP->value(xmlrig.vsp);
    @@ -1074,6 +1085,7 @@ void rigCAT_restore_defaults()
     	cntRigCatTimeout->value(progdefaults.RigCatTimeout);
     	cntRigCatWait->value(progdefaults.RigCatWait);
     	cntRigCatInitDelay->value(progdefaults.RigCatInitDelay);
    +//	cntRigCatWaitForDevice->value(progdefaults.RicCatWaitForDevice);
     	btnRigCatEcho->value(progdefaults.RigCatECHO);
     	btnRigCatCMDptt->value(progdefaults.RigCatCMDptt);
     	chkRigCatVSP->value(progdefaults.RigCatVSP);
    @@ -1103,7 +1115,7 @@ void rigCAT_init_defaults()
     	progdefaults.RigCatVSP = chkRigCatVSP->value();
     }
     
    -bool rigCAT_init(bool useXML)
    +bool rigCAT_init()
     {
     
     	if (rigCAT_open == true) {
    @@ -1114,19 +1126,18 @@ bool rigCAT_init(bool useXML)
     	sRigMode = "";
     	sRigWidth = "";
     
    -	if (useXML == true) {
    -		rigCAT_init_defaults();
    -		rigio.Device(progdefaults.XmlRigDevice);
    -		rigio.Baud(progdefaults.BaudRate(progdefaults.XmlRigBaudrate));
    -		rigio.RTS(progdefaults.RigCatRTSplus);
    -		rigio.DTR(progdefaults.RigCatDTRplus);
    -		rigio.RTSptt(progdefaults.RigCatRTSptt);
    -		rigio.DTRptt(progdefaults.RigCatDTRptt);
    -		rigio.RestoreTIO(progdefaults.RigCatRestoreTIO);
    -		rigio.RTSCTS(progdefaults.RigCatRTSCTSflow);
    -		rigio.Stopbits(progdefaults.RigCatStopbits);
    +	rigCAT_init_defaults();
    +	rigio.Device(progdefaults.XmlRigDevice);
    +	rigio.Baud(progdefaults.BaudRate(progdefaults.XmlRigBaudrate));
    +	rigio.RTS(progdefaults.RigCatRTSplus);
    +	rigio.DTR(progdefaults.RigCatDTRplus);
    +	rigio.RTSptt(progdefaults.RigCatRTSptt);
    +	rigio.DTRptt(progdefaults.RigCatDTRptt);
    +	rigio.RestoreTIO(progdefaults.RigCatRestoreTIO);
    +	rigio.RTSCTS(progdefaults.RigCatRTSCTSflow);
    +	rigio.Stopbits(progdefaults.RigCatStopbits);
     
    -		LOG_VERBOSE("\n\
    +	LOG_INFO("\n\
     Serial port parameters:\n\
     device	 : %s\n\
     baudrate   : %d\n\
    @@ -1153,65 +1164,58 @@ echo	   : %c\n",
     			(rigio.RTSCTS() ? 'T' : 'F'),
     			progdefaults.RigCatECHO ? 'T' : 'F');
     
    +	if (xmlrig.noserial == false && xmlrig.xmlok) {
     		if (rigio.OpenPort() == false) {
    -			LOG_VERBOSE("Cannot open serial port %s", rigio.Device().c_str());
    -			nonCATrig = true;
    -			init_NoRig_RigDialog();
    -			return false;
    +			LOG_ERROR("Cannot open serial port %s", rigio.Device().c_str());
    +			xmlrig.xmlok = true;
     		}
    -		sRigMode = "";
    -		sRigWidth = "";
    +	}
     
    -		nonCATrig = false;
    -		rigCAT_sendINIT("INIT", progdefaults.RigCatInitDelay);
    +	sRigMode = "";
    +	sRigWidth = "";
     
    -// must be able to get frequency 3 times in sequence or serial port might
    -// be shared with another application (flrig)
    -		bool failed = false;
    -		for (int i = 1; i <= 5; i++) {
    -			rigCAT_getfreq(1, failed, progdefaults.RigCatInitDelay);
    -			if (failed) break;
    -			LOG_INFO("Passed serial port test # %d", i);
    -//			MilliSleep(50);
    +	if (xmlrig.wait_for_device) {
    +		int delay = xmlrig.wait_for_device / 10;
    +		while (delay) {
    +			MilliSleep(10);
    +			if (delay % 10) Fl::awake();
    +			delay--;
     		}
    +	}
    +
    +	rigCAT_sendINIT("INIT", progdefaults.RigCatInitDelay);
    +	bool failed = false;
    +
    +	if (xmlrig.noserial)
    +		rigCAT_getfreq(1, failed, 0);
    +	else if (xmlrig.xmlok) {
    +		rigCAT_getfreq(3, failed, progdefaults.RigCatInitDelay);
     
     		if (failed) {
    -			LOG_INFO("Failed serial port test");
    -			rigio.ClosePort();
    -			nonCATrig = true;
    -			init_NoRig_RigDialog();
    -			return false;
    -		} else {
    -			nonCATrig = false;
    -			init_Xml_RigDialog();
    -		}
    -	} else { // rigcat thread just being used for the human interface
    -		nonCATrig = true;
    -		init_NoRig_RigDialog();
    -		llFreq = 0;
    -		rigCAT_bypass = false;
    -
    -		if (pthread_create(&rigCAT_thread, NULL, rigCAT_loop, NULL) < 0) {
    -			LOG_ERROR("%s", "pthread_create failed");
    -			rigio.ClosePort();
    -			return false;
    -		}
    -
    -		rigCAT_open = true;
    -		return true;
    +			LOG_ERROR("*****************Failed to read xcvr frequency");
    +			if (xmlrig.noserial == false)
    +				rigio.ClosePort();
    +			xmlrig.xmlok = false;
    +		} else
    +			LOG_INFO("Passed serial port test");
     	}
     
     	llFreq = 0;
    -	rigCAT_bypass = false;
     
     	if (pthread_create(&rigCAT_thread, NULL, rigCAT_loop, NULL) < 0) {
     		LOG_ERROR("%s", "pthread_create failed");
    -		rigio.ClosePort();
    +		if (xmlrig.xmlok && !xmlrig.noserial)
    +			rigio.ClosePort();
    +		xmlrig.xmlok = false;
     		return false;
     	}
     
    +	LOG_INFO("Created rigCAT thread");
    +
     	rigCAT_open = true;
     
    +	init_Xml_RigDialog();
    +
     	return true;
     }
     
    @@ -1235,7 +1239,6 @@ void rigCAT_close(void)
     
     	rigCAT_exit = false;
     	rigCAT_open = false;
    -	rigCAT_bypass = false;
     	wf->USB(true);
     
     }
    @@ -1251,10 +1254,8 @@ void rigCAT_set_ptt(int ptt)
     		return;
     	if (ptt) {
     		rigCAT_pttON();
    -		rigCAT_bypass = true;
     	} else{
     		rigCAT_pttOFF();
    -		rigCAT_bypass = false;
     	}
     }
     
    @@ -1271,13 +1272,12 @@ void rigCAT_set_qsy(long long f)
     }
     #endif
     
    -bool ModeIsLSB(const string& s)
    +bool ModeIsLSB(string s)
     {
    -	if (nonCATrig) {
    -		if (s == "LSB" || s == "PKTLSB" || s == "CW" || s == "RTTY")
    -			return true;
    -		return false;
    -	}
    +	if (connected_to_flrig) return !xmlrpc_USB();
    +#if USE_HAMLIB
    +	if (hamlib_active()) return !hamlib_USB();
    +#endif
     	list::iterator pM = LSBmodes.begin();
     	while (pM != LSBmodes.end() ) {
     		if (*pM == s)
    @@ -1287,6 +1287,997 @@ bool ModeIsLSB(const string& s)
     	return false;
     }
     
    +int smeter_data(DATA d, size_t p)
    +{
    +	int val = 0;
    +
    +	if (d.dtype == "BCD") {
    +		if (d.reverse == true)
    +			val = (int)(fm_bcd_be(p, d.size));
    +		else
    +			val = (int)(fm_bcd(p, d.size));
    +	} else if (d.dtype == "BINARY") {
    +		if (d.reverse == true)
    +			val = (int)(fm_binary_be(p, d.size));
    +		else
    +			val = (int)(fm_binary(p, d.size));
    +	} else if (d.dtype == "DECIMAL") {
    +		if (d.reverse == true)
    +			val = (int)(fm_decimal_be(p, d.size));
    +		else
    +			val = (int)(fm_decimal(p, d.size));
    +	}
    +
    +	size_t n;
    +	int sm1, sm2, val1, val2;
    +	for (n = 0; n < xmlrig.smeter.size() - 1; n++) {
    +		if ((val >= xmlrig.smeter[n].val) && (val < xmlrig.smeter[n+1].val)) break;
    +	}
    +	if (n == xmlrig.smeter.size() - 1) return 0;
    +	sm1 = xmlrig.smeter[n].mtr;
    +	sm2 = xmlrig.smeter[n+1].mtr;
    +	val1 = xmlrig.smeter[n].val;
    +	val2 = xmlrig.smeter[n+1].val;
    +
    +	if (val1 == val2) return 0;
    +	int mtr = sm1 + (val - val1) * (sm2 - sm1) / (val2 - val1);
    +
    +	return mtr;
    +}
    +
    +static void rigcat_set_smeter(void *data)
    +{
    +	if (pwrlevel_grp->visible()) return;
    +	if (!smeter && !pwrmeter) return;
    +
    +	if (smeter && progStatus.meters) {
    +		if (!smeter->visible()) {
    +			pwrmeter->hide();
    +			smeter->show();
    +		}
    +		int val = reinterpret_cast(data);
    +		smeter->value(val);
    +	}
    +}
    +
    +void rigCAT_get_smeter()
    +{
    +	const char symbol[] = "GET_SMETER";
    +
    +	if (rigCAT_exit || xmlrig.noserial) return;
    +
    +	XMLIOS modeCmd;
    +	list::iterator itrCmd;
    +	string strCmd;
    +	size_t p = 0, len1 = 0, len2 = 0, pData = 0;
    +	long mtr = 0;
    +
    +	itrCmd = commands.begin();
    +	while (itrCmd != commands.end()) {
    +		if ((*itrCmd).SYMBOL == symbol)
    +			break;
    +		++itrCmd;
    +	}
    +
    +	if (itrCmd == commands.end()) {
    +		if (xmlrig.debug) LOG_INFO("%s not defined", symbol);
    +		return;
    +	}
    +
    +	modeCmd = *itrCmd;
    +	if ( !modeCmd.str1.empty() ) strCmd.append(modeCmd.str1);
    +	if ( !modeCmd.str2.empty() ) strCmd.append(modeCmd.str2);
    +	if ( !modeCmd.info.size() ) return;
    +
    +	list::iterator preply;
    +
    +	for (preply = reply.begin(); preply != reply.end(); ++preply) {
    +		if (preply->SYMBOL == modeCmd.info)
    +			break;
    +	}
    +	if (preply == reply.end()) return;
    +
    +	XMLIOS  rTemp = *preply;
    +	len1 = rTemp.str1.size();
    +	len2 = rTemp.str2.size();
    +
    +	int timeout = progdefaults.RigCatTimeout;
    +	while (timeout > 50) {
    +		MilliSleep(50);
    +		Fl::awake();
    +		timeout -= 50;
    +	}
    +	if (timeout) {
    +		MilliSleep(timeout);
    +		Fl::awake();
    +	}
    +
    +// send the command
    +	if ( !sendCommand(strCmd, rTemp.size, progdefaults.RigCatWait) ) {
    +		LOG_ERROR("sendCommand failed");
    +		return;
    +	}
    +
    +// check the pre data string
    +	p = 0;
    +	pData = 0;
    +	if (len1) {
    +		for (size_t i = 0; i < len1; i++) {
    +			if ((char)rTemp.str1[i] != (char)replybuff[i]) {
    +					LOG_ERROR("failed pre data string test @ %" PRIuSZ, i);
    +					return;
    +			}
    +		}
    +		p = len1;
    +	}
    +	if (rTemp.fill1) p += rTemp.fill1;
    +	pData = p;
    +	if (rTemp.data.dtype == "BCD") {
    +		p += rTemp.data.size / 2;
    +		if (rTemp.data.size & 1) p++;
    +	} else
    +		p += rTemp.data.size;
    +// check the post data string
    +	if (rTemp.fill2) p += rTemp.fill2;
    +	if (len2) {
    +		for (size_t i = 0; i < len2; i++)
    +			if ((char)rTemp.str2[i] != (char)replybuff[p + i]) {
    +				LOG_ERROR("failed post data string test @ %d", static_cast(i));
    +				return;
    +			}
    +	}
    +// convert the data field
    +	mtr = smeter_data(rTemp.data, pData);
    +	if (xmlrig.debug) LOG_INFO("Converted %s value to %d", symbol, (int)mtr);
    +
    +	REQ(rigcat_set_smeter, reinterpret_cast(mtr));
    +}
    +
    +int pmeter_data(DATA d, size_t p)
    +{
    +	int val = 0;
    +
    +	if (d.dtype == "BCD") {
    +		if (d.reverse == true)
    +			val = (int)(fm_bcd_be(p, d.size));
    +		else
    +			val = (int)(fm_bcd(p, d.size));
    +	} else if (d.dtype == "BINARY") {
    +		if (d.reverse == true)
    +			val = (int)(fm_binary_be(p, d.size));
    +		else
    +			val = (int)(fm_binary(p, d.size));
    +	} else if (d.dtype == "DECIMAL") {
    +		if (d.reverse == true)
    +			val = (int)(fm_decimal_be(p, d.size));
    +		else
    +			val = (int)(fm_decimal(p, d.size));
    +	}
    +
    +	size_t n;
    +	int pm1, pm2, val1, val2;
    +	for (n = 0; n < xmlrig.pmeter.size() - 1; n++) {
    +		if ((val > xmlrig.pmeter[n].val) && (val <= xmlrig.pmeter[n+1].val)) break;
    +	}
    +	if (n == xmlrig.pmeter.size() - 1) return 0;
    +	pm1 = xmlrig.pmeter[n].mtr;
    +	pm2 = xmlrig.pmeter[n+1].mtr;
    +	val1 = xmlrig.pmeter[n].val;
    +	val2 = xmlrig.pmeter[n+1].val;
    +
    +	if (val1 == val2) return 0;
    +	int mtr = pm1 + (val - val1) * (pm2 - pm1) / (val2 - val1);
    +
    +	return mtr;
    +}
    +
    +static void rigcat_set_pmeter(void *data)
    +{
    +	if (pwrlevel_grp->visible()) return;
    +	if (!smeter && !pwrmeter) return;
    +
    +	if (pwrmeter && progStatus.meters) {
    +		if (!pwrmeter->visible()) {
    +			smeter->hide();
    +			pwrmeter->show();
    +		}
    +		int val = reinterpret_cast(data);
    +		pwrmeter->value(val);
    +	}
    +}
    +
    +void rigCAT_get_pwrmeter()
    +{
    +	const char symbol[] = "GET_PWRMETER";
    +
    +	if (rigCAT_exit || xmlrig.noserial) return;
    +
    +	XMLIOS modeCmd;
    +	list::iterator itrCmd;
    +	string strCmd;
    +	size_t p = 0, len1 = 0, len2 = 0, pData = 0;
    +	long mtr = 0;
    +
    +	itrCmd = commands.begin();
    +	while (itrCmd != commands.end()) {
    +		if ((*itrCmd).SYMBOL == symbol)
    +			break;
    +		++itrCmd;
    +	}
    +
    +	if (itrCmd == commands.end()) {
    +		if (xmlrig.debug) LOG_INFO("%s not defined", symbol);
    +		return;
    +	}
    +
    +	modeCmd = *itrCmd;
    +	if ( !modeCmd.str1.empty() ) strCmd.append(modeCmd.str1);
    +	if ( !modeCmd.str2.empty() ) strCmd.append(modeCmd.str2);
    +	if ( !modeCmd.info.size() ) return;
    +
    +	list::iterator preply;
    +
    +	for (preply = reply.begin(); preply != reply.end(); ++preply) {
    +		if (preply->SYMBOL == modeCmd.info)
    +			break;
    +	}
    +	if (preply == reply.end()) return;
    +
    +	XMLIOS  rTemp = *preply;
    +	len1 = rTemp.str1.size();
    +	len2 = rTemp.str2.size();
    +
    +	int timeout = progdefaults.RigCatTimeout;
    +	while (timeout > 50) {
    +		MilliSleep(50);
    +		Fl::awake();
    +		timeout -= 50;
    +	}
    +	if (timeout) {
    +		MilliSleep(timeout);
    +		Fl::awake();
    +	}
    +
    +// send the command
    +	if ( !sendCommand(strCmd, rTemp.size, progdefaults.RigCatWait) ) {
    +		LOG_ERROR("sendCommand failed");
    +		return;
    +	}
    +
    +// check the pre data string
    +	p = 0;
    +	pData = 0;
    +	if (len1) {
    +		for (size_t i = 0; i < len1; i++) {
    +			if ((char)rTemp.str1[i] != (char)replybuff[i]) {
    +					LOG_ERROR("failed pre data string test @ %" PRIuSZ, i);
    +					return;
    +			}
    +		}
    +		p = len1;
    +	}
    +	if (rTemp.fill1) p += rTemp.fill1;
    +	pData = p;
    +	if (rTemp.data.dtype == "BCD") {
    +		p += rTemp.data.size / 2;
    +		if (rTemp.data.size & 1) p++;
    +	} else
    +		p += rTemp.data.size;
    +// check the post data string
    +	if (rTemp.fill2) p += rTemp.fill2;
    +	if (len2) {
    +		for (size_t i = 0; i < len2; i++)
    +			if ((char)rTemp.str2[i] != (char)replybuff[p + i]) {
    +				LOG_ERROR("failed post data string test @ %d", static_cast(i));
    +				return;
    +			}
    +	}
    +// convert the data field
    +	mtr = pmeter_data(rTemp.data, pData);
    +	if (xmlrig.debug) LOG_INFO("Converted %s to %d", symbol, (int)mtr);
    +
    +	REQ(rigcat_set_pmeter, reinterpret_cast(mtr));
    +
    +}
    +
    +static void rigcat_notch(void *data)
    +{
    +	int val = reinterpret_cast(data);
    +	notch_frequency = val;
    +}
    +
    +int notch_data(DATA d, size_t p)
    +{
    +	int val = 0;
    +
    +	if (d.dtype == "BCD") {
    +		if (d.reverse == true)
    +			val = (int)(fm_bcd_be(p, d.size));
    +		else
    +			val = (int)(fm_bcd(p, d.size));
    +	} else if (d.dtype == "BINARY") {
    +		if (d.reverse == true)
    +			val = (int)(fm_binary_be(p, d.size));
    +		else
    +			val = (int)(fm_binary(p, d.size));
    +	} else if (d.dtype == "DECIMAL") {
    +		if (d.reverse == true)
    +			val = (int)(fm_decimal_be(p, d.size));
    +		else
    +			val = (int)(fm_decimal(p, d.size));
    +	}
    +
    +	size_t n;
    +	int ntch1, ntch2, val1, val2;
    +	for (n = 0; n < xmlrig.notch.size() - 1; n++) {
    +		if ((val > xmlrig.notch[n].val) && (val <= xmlrig.notch[n+1].val))
    +			break;
    +	}
    +	if (n == xmlrig.notch.size() - 1)
    +		return 0;
    +
    +	val1 = xmlrig.notch[n].val;
    +	val2 = xmlrig.notch[n+1].val;
    +	if (val1 == val2)
    +		return 0;
    +
    +	ntch1 = xmlrig.notch[n].mtr;
    +	ntch2 = xmlrig.notch[n+1].mtr;
    +
    +	return ntch1 + (val - val1) * (ntch2 - ntch1) / (val2 - val1);
    +}
    +
    +int notch_val(int freq)
    +{
    +	size_t n;
    +	int val1, val2, freq1, freq2;
    +	for (n = 0; n < xmlrig.notch.size() - 1; n++) {
    +		if ((freq > xmlrig.notch[n].mtr) && (freq <= xmlrig.notch[n+1].mtr))
    +			break;
    +	}
    +	if (n == xmlrig.notch.size() - 1)
    +		return 0;
    +
    +	freq1 = xmlrig.notch[n].mtr;
    +	freq2 = xmlrig.notch[n+1].mtr;
    +
    +	if (freq1 == freq2)
    +		return 0;
    +
    +	val1 = xmlrig.notch[n].val;
    +	val2 = xmlrig.notch[n+1].val;
    +
    +	return val1 + (freq - freq1) * (val2 - val1) / (freq2 - freq1);
    +
    +}
    +
    +bool rigCAT_notchON()
    +{
    +	const char symbol[] = "GET_NOTCH_ON";
    +
    +	if (rigCAT_exit) return 0;
    +
    +	XMLIOS modeCmd;
    +	list::iterator itrCmd;
    +	string strCmd;
    +	size_t len1 = 0;
    +
    +	itrCmd = commands.begin();
    +	while (itrCmd != commands.end()) {
    +		if ((*itrCmd).SYMBOL == symbol)
    +			break;
    +		++itrCmd;
    +	}
    +
    +	if (itrCmd == commands.end()) {
    +		if (xmlrig.debug) LOG_INFO("%s not defined", symbol);
    +		return 0;
    +	}
    +
    +	modeCmd = *itrCmd;
    +	if ( !modeCmd.str1.empty() ) strCmd.append(modeCmd.str1);
    +	if ( !modeCmd.str2.empty() ) strCmd.append(modeCmd.str2);
    +	if ( !modeCmd.info.size() ) return 0;
    +
    +	list::iterator preply;
    +
    +	for (preply = reply.begin(); preply != reply.end(); ++preply) {
    +		if (preply->SYMBOL == modeCmd.info)
    +			break;
    +	}
    +	if (preply == reply.end()) return 0;
    +
    +	XMLIOS  rTemp = *preply;
    +	len1 = rTemp.str1.size();
    +
    +	int timeout = progdefaults.RigCatTimeout;
    +	while (timeout > 50) {
    +		MilliSleep(50);
    +		Fl::awake();
    +		timeout -= 50;
    +	}
    +	if (timeout) {
    +		MilliSleep(timeout);
    +		Fl::awake();
    +	}
    +
    +// send the command
    +	if ( !sendCommand(strCmd, rTemp.size, progdefaults.RigCatWait) ) {
    +		LOG_ERROR("sendCommand failed");
    +		return 0;
    +	}
    +
    +	bool is_on = true;
    +	if (len1) {
    +		for (size_t i = 0; i < len1; i++) {
    +			if ((char)rTemp.str1[i] != (char)replybuff[i]) {
    +				is_on = false;
    +				break;
    +			}
    +		}
    +	} else
    +		is_on = false;
    +
    +	if (xmlrig.debug) LOG_INFO("%s is %s", symbol, is_on ? "ON" : "OFF");
    +	return is_on;
    +}
    +
    +void rigCAT_get_notch()
    +{
    +	const char symbol[] = "GET_NOTCH";
    +
    +	if (rigCAT_exit) return;
    +
    +	if (!rigCAT_notchON()) {
    +		REQ(rigcat_notch, reinterpret_cast(0));
    +		return;
    +	}
    +	XMLIOS modeCmd;
    +	list::iterator itrCmd;
    +	string strCmd;
    +	size_t p = 0, len1 = 0, len2 = 0, pData = 0;
    +	long ntch = 0;
    +
    +	itrCmd = commands.begin();
    +	while (itrCmd != commands.end()) {
    +		if ((*itrCmd).SYMBOL == symbol)
    +			break;
    +		++itrCmd;
    +	}
    +
    +	if (itrCmd == commands.end()) {
    +		if (xmlrig.debug) LOG_INFO("%s not defined", symbol);
    +		return;
    +	}
    +
    +	modeCmd = *itrCmd;
    +	if ( !modeCmd.str1.empty() ) strCmd.append(modeCmd.str1);
    +	if ( !modeCmd.str2.empty() ) strCmd.append(modeCmd.str2);
    +	if ( !modeCmd.info.size() ) return;
    +
    +	list::iterator preply;
    +
    +	for (preply = reply.begin(); preply != reply.end(); ++preply) {
    +		if (preply->SYMBOL == modeCmd.info)
    +			break;
    +	}
    +	if (preply == reply.end()) return;
    +
    +	XMLIOS  rTemp = *preply;
    +	len1 = rTemp.str1.size();
    +	len2 = rTemp.str2.size();
    +
    +	int timeout = progdefaults.RigCatTimeout;
    +	while (timeout > 50) {
    +		MilliSleep(50);
    +		Fl::awake();
    +		timeout -= 50;
    +	}
    +	if (timeout) {
    +		MilliSleep(timeout);
    +		Fl::awake();
    +	}
    +
    +// send the command
    +	if ( !sendCommand(strCmd, rTemp.size, progdefaults.RigCatWait) ) {
    +		LOG_ERROR("sendCommand failed");
    +		return;
    +	}
    +
    +// check the pre data string
    +	p = 0;
    +	pData = 0;
    +	if (len1) {
    +		for (size_t i = 0; i < len1; i++) {
    +			if ((char)rTemp.str1[i] != (char)replybuff[i]) {
    +					LOG_ERROR("failed pre data string test @ %" PRIuSZ, i);
    +					return;
    +			}
    +		}
    +		p = len1;
    +	}
    +	if (rTemp.fill1) p += rTemp.fill1;
    +	pData = p;
    +	if (rTemp.data.dtype == "BCD") {
    +		p += rTemp.data.size / 2;
    +		if (rTemp.data.size & 1) p++;
    +	} else
    +		p += rTemp.data.size;
    +// check the post data string
    +	if (rTemp.fill2) p += rTemp.fill2;
    +	if (len2) {
    +		for (size_t i = 0; i < len2; i++)
    +			if ((char)rTemp.str2[i] != (char)replybuff[p + i]) {
    +				LOG_ERROR("failed post data string test @ %d", static_cast(i));
    +				return;
    +			}
    +	}
    +// convert the data field
    +	ntch = notch_data(rTemp.data, pData);
    +	if (xmlrig.debug) LOG_INFO("%s converted to %d", symbol, (int)ntch);
    +
    +	REQ(rigcat_notch, reinterpret_cast(ntch));
    +
    +}
    +
    +void rigCAT_notch_ON()
    +{
    +	const char symbol[] = "SET_NOTCH_ON";
    +
    +	if (rigCAT_exit) return;
    +
    +	XMLIOS modeCmd;
    +	list::iterator itrCmd;
    +	string strCmd;
    +
    +	itrCmd = commands.begin();
    +	while (itrCmd != commands.end()) {
    +		if ((*itrCmd).SYMBOL == symbol)
    +			break;
    +		++itrCmd;
    +	}
    +	if (itrCmd == commands.end()) {
    +		if (xmlrig.debug) LOG_INFO("%s not defined", symbol);
    +		return;
    +	}
    +
    +	modeCmd = *itrCmd;
    +
    +	if ( modeCmd.str1.empty() == false)
    +		strCmd.append(modeCmd.str1);
    +	if (modeCmd.str2.empty() == false)
    +		strCmd.append(modeCmd.str2);
    +
    +	if (modeCmd.ok.size()) {
    +		list::iterator preply = reply.begin();
    +		while (preply != reply.end()) {
    +			if (preply->SYMBOL == modeCmd.ok) {
    +				XMLIOS  rTemp = *preply;
    +// send the command
    +				for (int n = 0; n < progdefaults.RigCatRetries; n++) {
    +					MilliSleep(50);
    +					guard_lock ser_guard( &rigCAT_mutex );
    +					if (rigCAT_exit) return;
    +					if (sendCommand(strCmd, rTemp.size, progdefaults.RigCatWait)) return;
    +				}
    +				return;
    +			}
    +			preply++;
    +		}
    +	} else {
    +		for (int n = 0; n < progdefaults.RigCatRetries; n++) {
    +			MilliSleep(50);
    +			guard_lock ser_guard( &rigCAT_mutex );
    +			if (rigCAT_exit) return;
    +			if (sendCommand(strCmd, 0, progdefaults.RigCatWait)) return;
    +		}
    +	}
    +	LOG_ERROR("%s failed", symbol);
    +}
    +
    +void rigCAT_notch_OFF()
    +{
    +	const char symbol[] = "SET_NOTCH_OFF";
    +
    +	if (rigCAT_exit) return;
    +
    +	XMLIOS modeCmd;
    +	list::iterator itrCmd;
    +	string strCmd;
    +
    +	itrCmd = commands.begin();
    +	while (itrCmd != commands.end()) {
    +		if ((*itrCmd).SYMBOL == symbol)
    +			break;
    +		++itrCmd;
    +	}
    +	if (itrCmd == commands.end()) {
    +		if (xmlrig.debug) LOG_INFO("%s not defined", symbol);
    +		return;
    +	}
    +
    +	modeCmd = *itrCmd;
    +
    +	if ( modeCmd.str1.empty() == false)
    +		strCmd.append(modeCmd.str1);
    +	if (modeCmd.str2.empty() == false)
    +		strCmd.append(modeCmd.str2);
    +
    +	if (modeCmd.ok.size()) {
    +		list::iterator preply = reply.begin();
    +		while (preply != reply.end()) {
    +			if (preply->SYMBOL == modeCmd.ok) {
    +				XMLIOS  rTemp = *preply;
    +// send the command
    +				for (int n = 0; n < progdefaults.RigCatRetries; n++) {
    +					MilliSleep(50);
    +					guard_lock ser_guard( &rigCAT_mutex );
    +					if (rigCAT_exit) return;
    +					if (sendCommand(strCmd, rTemp.size, progdefaults.RigCatWait)) return;
    +				}
    +				return;
    +			}
    +			preply++;
    +		}
    +	} else {
    +		for (int n = 0; n < progdefaults.RigCatRetries; n++) {
    +			MilliSleep(50);
    +			guard_lock ser_guard( &rigCAT_mutex );
    +			if (rigCAT_exit) return;
    +			if (sendCommand(strCmd, 0, progdefaults.RigCatWait)) return;
    +		}
    +	}
    +	LOG_ERROR("%s failed", symbol);
    +}
    +
    +void rigCAT_set_notch(int freq)
    +{
    +	const char symbol[] = "SET_NOTCH_VAL";
    +
    +	if (rigCAT_exit) return;
    +
    +	if (!freq) {
    +		rigCAT_notch_OFF();
    +		return;
    +	}
    +	rigCAT_notch_ON();
    +
    +	XMLIOS modeCmd;
    +	list::iterator itrCmd;
    +	string strCmd;
    +
    +	itrCmd = commands.begin();
    +	while (itrCmd != commands.end()) {
    +		if ((*itrCmd).SYMBOL == symbol)
    +			break;
    +		++itrCmd;
    +	}
    +	if (itrCmd == commands.end()) {
    +		if (xmlrig.debug) LOG_INFO("%s not defined", symbol);
    +		return;
    +	}
    +
    +	modeCmd = *itrCmd;
    +
    +	if ( modeCmd.str1.empty() == false)
    +		strCmd.append(modeCmd.str1);
    +
    +	string strval = "";
    +	long long int val = notch_val(freq);
    +
    +	if (modeCmd.data.size != 0) {
    +		if (modeCmd.data.dtype == "BCD") {
    +			if (modeCmd.data.reverse == true)
    +				strval = to_bcd_be(val, modeCmd.data.size);
    +		else
    +			strval = to_bcd(val, modeCmd.data.size);
    +		} else if (modeCmd.data.dtype == "BINARY") {
    +			if (modeCmd.data.reverse == true)
    +				strval = to_binary_be(val, modeCmd.data.size);
    +			else
    +				strval = to_binary(val, modeCmd.data.size);
    +		} else if (modeCmd.data.dtype == "DECIMAL") {
    +			if (modeCmd.data.reverse == true)
    +				strval = to_decimal_be(val, modeCmd.data.size);
    +			else
    +				strval = to_decimal(val, modeCmd.data.size);
    +		}
    +	}
    +	strCmd.append(strval);
    +
    +	if (modeCmd.str2.empty() == false)
    +		strCmd.append(modeCmd.str2);
    +
    +	if (modeCmd.ok.size()) {
    +		list::iterator preply = reply.begin();
    +		while (preply != reply.end()) {
    +			if (preply->SYMBOL == modeCmd.ok) {
    +				XMLIOS  rTemp = *preply;
    +// send the command
    +				for (int n = 0; n < progdefaults.RigCatRetries; n++) {
    +					MilliSleep(50);
    +					guard_lock ser_guard( &rigCAT_mutex );
    +					if (rigCAT_exit) return;
    +					if (sendCommand(strCmd, rTemp.size, progdefaults.RigCatWait)) return;
    +				}
    +				return;
    +			}
    +			preply++;
    +		}
    +	} else {
    +		for (int n = 0; n < progdefaults.RigCatRetries; n++) {
    +			MilliSleep(50);
    +			guard_lock ser_guard( &rigCAT_mutex );
    +			if (rigCAT_exit) return;
    +			if (sendCommand(strCmd, 0, progdefaults.RigCatWait)) return;
    +		}
    +	}
    +	if (progdefaults.RigCatVSP == false)
    +		LOG_ERROR("%s failed", symbol);
    +}
    +
    +int pwrlevel_data(DATA d, size_t p)
    +{
    +	int val = 0;
    +
    +	if (d.dtype == "BCD") {
    +		if (d.reverse == true)
    +			val = (int)(fm_bcd_be(p, d.size));
    +		else
    +			val = (int)(fm_bcd(p, d.size));
    +	} else if (d.dtype == "BINARY") {
    +		if (d.reverse == true)
    +			val = (int)(fm_binary_be(p, d.size));
    +		else
    +			val = (int)(fm_binary(p, d.size));
    +	} else if (d.dtype == "DECIMAL") {
    +		if (d.reverse == true)
    +			val = (int)(fm_decimal_be(p, d.size));
    +		else
    +			val = (int)(fm_decimal(p, d.size));
    +	}
    +
    +	size_t n;
    +	int pwr1, pwr2, val1, val2;
    +	for (n = 0; n < xmlrig.pwrlevel.size() - 1; n++) {
    +		if ((val > xmlrig.pwrlevel[n].val) && (val <= xmlrig.pwrlevel[n+1].val))
    +			break;
    +	}
    +	if (n == xmlrig.pwrlevel.size() - 1)
    +		return 0;
    +
    +	val1 = xmlrig.pwrlevel[n].val;
    +	val2 = xmlrig.pwrlevel[n+1].val;
    +	if (val1 == val2)
    +		return 0;
    +
    +	pwr1 = xmlrig.pwrlevel[n].mtr;
    +	pwr2 = xmlrig.pwrlevel[n+1].mtr;
    +
    +	return pwr1 + (val - val1) * (pwr2 - pwr1) / (val2 - val1);
    +}
    +
    +int pwrlevel_val(int pwr)
    +{
    +	size_t n;
    +	int val1, val2, pwr1, pwr2;
    +	for (n = 0; n < xmlrig.pwrlevel.size() - 1; n++) {
    +		if ((pwr >= xmlrig.pwrlevel[n].mtr) && (pwr <= xmlrig.pwrlevel[n+1].mtr))
    +			break;
    +	}
    +	if (n == xmlrig.pwrlevel.size() - 1)
    +		return 0;
    +
    +	pwr1 = xmlrig.pwrlevel[n].mtr;
    +	pwr2 = xmlrig.pwrlevel[n+1].mtr;
    +
    +	if (pwr1 == pwr2)
    +		return 0;
    +
    +	val1 = xmlrig.pwrlevel[n].val;
    +	val2 = xmlrig.pwrlevel[n+1].val;
    +
    +	return val1 + (pwr - pwr1) * (val2 - val1) / (pwr2 - pwr1);
    +
    +}
    +
    +// called by rigio thread
    +// must use REQ(...) to set the power level control
    +
    +static void rigCAT_update_pwrlevel(void *v)
    +{
    +	long pwr = reinterpret_cast(v);
    +	char szpwr[10];
    +	snprintf(szpwr, sizeof(szpwr), "%ld", pwr);
    +	progdefaults.mytxpower = szpwr;
    +
    +	inpMyPower->value(szpwr);
    +	pwr_level->value(pwr);
    +
    +	if (xmlrig.debug) LOG_INFO("Read power level %s", szpwr);
    +}
    +
    +void rigCAT_get_pwrlevel()
    +{
    +	const char symbol[] = "GET_PWRLEVEL";
    +
    +	if (rigCAT_exit || xmlrig.noserial || !xmlrig.xmlok) return;
    +
    +	XMLIOS modeCmd;
    +	list::iterator itrCmd;
    +	string strCmd;
    +	size_t p = 0, len1 = 0, len2 = 0, pData = 0;
    +	long pwr = 0;
    +
    +	itrCmd = commands.begin();
    +	while (itrCmd != commands.end()) {
    +		if ((*itrCmd).SYMBOL == symbol)
    +			break;
    +		++itrCmd;
    +	}
    +
    +	if (itrCmd == commands.end()) {
    +		if (xmlrig.debug) LOG_INFO("%s not defined", symbol);
    +		return;
    +	}
    +
    +	modeCmd = *itrCmd;
    +	if ( !modeCmd.str1.empty() ) strCmd.append(modeCmd.str1);
    +	if ( !modeCmd.str2.empty() ) strCmd.append(modeCmd.str2);
    +	if ( !modeCmd.info.size() ) return;
    +
    +	list::iterator preply;
    +
    +	for (preply = reply.begin(); preply != reply.end(); ++preply) {
    +		if (preply->SYMBOL == modeCmd.info)
    +			break;
    +	}
    +	if (preply == reply.end()) return;
    +
    +	XMLIOS  rTemp = *preply;
    +	len1 = rTemp.str1.size();
    +	len2 = rTemp.str2.size();
    +
    +	int timeout = progdefaults.RigCatTimeout;
    +	while (timeout > 50) {
    +		MilliSleep(50);
    +		Fl::awake();
    +		timeout -= 50;
    +	}
    +	if (timeout) {
    +		MilliSleep(timeout);
    +		Fl::awake();
    +	}
    +
    +// send the command
    +	{
    +		guard_lock ser_guard( &rigCAT_mutex );
    +		if ( !sendCommand(strCmd, rTemp.size, progdefaults.RigCatWait) ) {
    +			LOG_ERROR("sendCommand failed");
    +			return;
    +		}
    +	}
    +// check the pre data string
    +	p = 0;
    +	pData = 0;
    +	if (len1) {
    +		for (size_t i = 0; i < len1; i++) {
    +			if ((char)rTemp.str1[i] != (char)replybuff[i]) {
    +					LOG_ERROR("failed pre data string test @ %" PRIuSZ, i);
    +					return;
    +			}
    +		}
    +		p = len1;
    +	}
    +	if (rTemp.fill1) p += rTemp.fill1;
    +	pData = p;
    +	if (rTemp.data.dtype == "BCD") {
    +		p += rTemp.data.size / 2;
    +		if (rTemp.data.size & 1) p++;
    +	} else
    +		p += rTemp.data.size;
    +// check the post data string
    +	if (rTemp.fill2) p += rTemp.fill2;
    +	if (len2) {
    +		for (size_t i = 0; i < len2; i++)
    +			if ((char)rTemp.str2[i] != (char)replybuff[p + i]) {
    +				LOG_ERROR("failed post data string test @ %d", static_cast(i));
    +				return;
    +			}
    +	}
    +// convert the data field
    +	pwr = pwrlevel_data(rTemp.data, pData);
    +
    +	REQ(rigCAT_update_pwrlevel, (void *)pwr);
    +}
    +
    +void rigCAT_set_pwrlevel(int pwr)
    +{
    +	const char symbol[] = "SET_PWRLEVEL";
    +
    +	if (rigCAT_exit || !xmlrig.use_pwrlevel) return;
    +
    +	XMLIOS modeCmd;
    +	list::iterator itrCmd;
    +	string strCmd;
    +
    +	itrCmd = commands.begin();
    +	while (itrCmd != commands.end()) {
    +		if ((*itrCmd).SYMBOL == symbol)
    +			break;
    +		++itrCmd;
    +	}
    +	if (itrCmd == commands.end()) {
    +		if (xmlrig.debug) LOG_INFO("%s not defined", symbol);
    +		return;
    +	}
    +
    +	modeCmd = *itrCmd;
    +
    +	if ( modeCmd.str1.empty() == false)
    +		strCmd.append(modeCmd.str1);
    +
    +	string strval = "";
    +	int val = pwrlevel_val(pwr);
    +
    +	if (modeCmd.data.size != 0) {
    +		if (modeCmd.data.dtype == "BCD") {
    +			if (modeCmd.data.reverse == true)
    +				strval = to_bcd_be(val, modeCmd.data.size);
    +		else
    +			strval = to_bcd(val, modeCmd.data.size);
    +		} else if (modeCmd.data.dtype == "BINARY") {
    +			if (modeCmd.data.reverse == true)
    +				strval = to_binary_be(val, modeCmd.data.size);
    +			else
    +				strval = to_binary(val, modeCmd.data.size);
    +		} else if (modeCmd.data.dtype == "DECIMAL") {
    +			if (modeCmd.data.reverse == true)
    +				strval = to_decimal_be(val, modeCmd.data.size);
    +			else
    +				strval = to_decimal(val, modeCmd.data.size);
    +		}
    +	}
    +	strCmd.append(strval);
    +
    +	if (modeCmd.str2.empty() == false)
    +		strCmd.append(modeCmd.str2);
    +
    +	if (modeCmd.ok.size()) {
    +		list::iterator preply = reply.begin();
    +		while (preply != reply.end()) {
    +			if (preply->SYMBOL == modeCmd.ok) {
    +				XMLIOS  rTemp = *preply;
    +// send the command
    +				for (int n = 0; n < progdefaults.RigCatRetries; n++) {
    +					MilliSleep(50);
    +					guard_lock ser_guard( &rigCAT_mutex );
    +					if (rigCAT_exit) return;
    +					if (sendCommand(strCmd, rTemp.size, progdefaults.RigCatWait)) {
    +						if (xmlrig.debug) LOG_INFO("Power set to %s", strval.c_str());
    +						return;
    +					}
    +				}
    +				if (xmlrig.debug) LOG_ERROR("%s failed", symbol);
    +				return;
    +			}
    +			preply++;
    +		}
    +	} else {
    +		for (int n = 0; n < progdefaults.RigCatRetries; n++) {
    +			MilliSleep(50);
    +			guard_lock ser_guard( &rigCAT_mutex );
    +			if (rigCAT_exit) return;
    +			if (sendCommand(strCmd, 0, progdefaults.RigCatWait)) {
    +				if (xmlrig.debug) LOG_INFO("Power set to %s", strval.c_str());
    +				return;
    +			}
    +		}
    +	}
    +	if (progdefaults.RigCatVSP == false)
    +		if (xmlrig.debug) LOG_ERROR("%s failed", symbol);
    +}
    +
     static void *rigCAT_loop(void *args)
     {
     	SET_THREAD_ID(RIGCTL_TID);
    @@ -1296,44 +2287,56 @@ static void *rigCAT_loop(void *args)
     	bool failed;
     
     	for (;;) {
    -		MilliSleep(100);
    -
    -		{
    +		for (int i = 0; i < xmlrig.pollinterval / 10; i++) {
    +			MilliSleep(10);
     			guard_lock ser_guard( &rigCAT_mutex );
    -
     			if (rigCAT_exit == true) {
    -				LOG_INFO("%s", "Exit rigCAT loop");
    +				LOG_INFO("%s", "Exited rigCAT loop");
     				return NULL;
     			}
    -
    -			if (rigCAT_bypass == true)
    -				continue;
    -
     		}
     
    -		freq = rigCAT_getfreq(progdefaults.RigCatRetries, failed);
    +		if (trx_state == STATE_RX) {
    +			freq = rigCAT_getfreq(progdefaults.RigCatRetries, failed);
    +			if (rigCAT_exit) continue;
     
    -		if ((freq > 0) && (freq != llFreq)) {
    -			llFreq = freq;
    -			show_frequency(freq);
    -			wf->rfcarrier(freq);
    +			if ((freq > 0) && (freq != llFreq)) {
    +				llFreq = freq;
    +				show_frequency(freq);
    +				wf->rfcarrier(freq);
    +			}
    +
    +			sWidth = rigCAT_getwidth();
    +			if (rigCAT_exit) continue;
    +
    +			if (sWidth.size() && sWidth != sRigWidth) {
    +				sRigWidth = sWidth;
    +				show_bw(sWidth);
    +			}
    +
    +			sMode = rigCAT_getmode();
    +			if (rigCAT_exit) continue;
    +
    +			if (sMode.size() && sMode != sRigMode) {
    +				sRigMode = sMode;
    +				if (ModeIsLSB(sMode))
    +					wf->USB(false);
    +				else
    +					wf->USB(true);
    +				show_mode(sMode);
    +			}
    +
    +			if (xmlrig.use_pwrlevel) rigCAT_get_pwrlevel();
    +
    +			if (xmlrig.use_smeter) rigCAT_get_smeter();
    +
    +			if (xmlrig.use_notch) rigCAT_get_notch();
    +
    +		} else {
    +			if ( (trx_state == STATE_TUNE) || (trx_state == STATE_TX) )
    +				if (xmlrig.use_pwrmeter) rigCAT_get_pwrmeter();
     		}
     
    -		sWidth = rigCAT_getwidth();
    -		if (sWidth.size() && sWidth != sRigWidth) {
    -			sRigWidth = sWidth;
    -			show_bw(sWidth);
    -		}
    -
    -		sMode = rigCAT_getmode();
    -		if (sMode.size() && sMode != sRigMode) {
    -			sRigMode = sMode;
    -			if (ModeIsLSB(sMode))
    -				wf->USB(false);
    -			else
    -				wf->USB(true);
    -			show_mode(sMode);
    -		}
     	}
     
     	return NULL;
    diff --git a/src/rigcontrol/rigsupport.cxx b/src/rigcontrol/rigsupport.cxx
    index 04f61edc..a74ef5a0 100644
    --- a/src/rigcontrol/rigsupport.cxx
    +++ b/src/rigcontrol/rigsupport.cxx
    @@ -58,9 +58,9 @@ string windowTitle;
     
     vector freqlist;
     
    -const unsigned char nfields = 4;
    +const unsigned char nfields = 5;//4;
     int fwidths[nfields];
    -enum { max_rfcarrier, max_rmode, max_mode };
    +enum { max_rfcarrier, max_rmode, max_mode, max_carrier };
     
     #if !USE_HAMLIB
     
    @@ -137,16 +137,19 @@ string modeString(rmode_t m)
     void initOptionMenus()
     {
     	qso_opMODE->clear();
    +
     	list::iterator MD;
     	list *pMD = 0;
    +
     	if (lmodes.empty() == false)
     		pMD = &lmodes;
     	else if (lmodeCMD.empty() == false)
     		pMD = &lmodeCMD;
    -
    +printf("initOptionMenus()\n");
     	if (pMD) {
     		MD = pMD->begin();
     		while (MD != pMD->end()) {
    +printf("adding mode: %s\n", (*MD).SYMBOL.c_str());
     			qso_opMODE->add( (*MD).SYMBOL.c_str());
     			MD++;
     		}
    @@ -168,6 +171,7 @@ void initOptionMenus()
     	if (pBW) {
     		bw = pBW->begin();
     		while (bw != pBW->end()) {
    +printf("adding BW: %s\n", (*bw).SYMBOL.c_str());
     			qso_opBW->add( (*bw).SYMBOL.c_str());
     			bw++;
     		}
    @@ -194,13 +198,14 @@ void updateSelect()
     	}
     }
     
    -size_t updateList(long rf, int freq, string rmd, trx_mode md)
    +size_t updateList(long rf, int freq, string rmd, trx_mode md, string usage = "")
     {
     	qrg_mode_t m;
     	m.rmode = rmd;
     	m.mode = md;
     	m.rfcarrier = rf;
     	m.carrier = freq;
    +	m.usage = usage;
     
     	freqlist.push_back(m);
     	sort(freqlist.begin(), freqlist.end());
    @@ -232,12 +237,15 @@ size_t addtoList(long val)
     bool readFreqList()
     {
     	ifstream freqfile((HomeDir + "frequencies2.txt").c_str());
    -	if (!freqfile)
    +	if (!freqfile) {
    +		LOG_ERROR("Could not open %s", (HomeDir + "frequencies2.txt").c_str());
     		return false;
    +	}
     
     	string line;
     	qrg_mode_t m;
     	while (!getline(freqfile, line).eof()) {
    +		LOG_INFO("%s", line.c_str());
     		if (line[0] == '#')
     			continue;
     		istringstream is(line);
    @@ -254,32 +262,38 @@ bool readFreqList()
     
     void saveFreqList()
     {
    +	if (freqlist.empty()) return;
     
     	ofstream freqfile((HomeDir + "frequencies2.txt").c_str());
    -	if (!freqfile)
    -		return;
    -	freqfile << "# rfcarrier rig_mode carrier mode\n";
    -
    -	if (freqlist.empty()) {
    -		freqfile.close();
    +	if (!freqfile) {
    +		LOG_ERROR("Could not open %s", (HomeDir + "frequencies2.txt").c_str());
     		return;
     	}
    +	freqfile << "# rfcarrier rig_mode carrier mode usage\n";
    +
    +	copy(	freqlist.begin(),
    +			freqlist.end(),
    +			ostream_iterator(freqfile, "\n") );
     
    -	copy(freqlist.begin(), freqlist.end(),
    -	     ostream_iterator(freqfile, "\n"));
     	freqfile.close();
     }
     
    -void buildlist()
    +void build_frequencies2_list()
     {
    +	if (!freqlist.empty()) saveFreqList();
    +
    +	clearList();
     	// calculate the column widths
     	memset(fwidths, 0, sizeof(fwidths));
     	// these need to be a little wider than fl_width thinks
    -	fwidths[max_rmode] = fwidths[max_mode] = 10;
    +	fwidths[max_rmode] = fwidths[max_mode] = 
    +	fwidths[max_carrier] = fwidths[max_rfcarrier]= 15;
     
     	fwidths[max_rfcarrier] += (int)ceil(fl_width("999999.999"));
     
    -	fwidths[max_rmode] += (int)ceil(fl_width("XXXX"));
    +	fwidths[max_rmode] += (int)ceil(fl_width("XXXXXX"));
    +
    +	fwidths[max_carrier] += (int)ceil(fl_width("8888"));
     
     	// find mode with longest shortname
     	size_t s, smax = 0, mmax = 0;
    @@ -294,7 +308,7 @@ void buildlist()
     
     	if (readFreqList() == true)
     		return;
    -//	Fl::lock();
    +
     	updateList (1807000L, 1000, "USB", MODE_PSK31 );
     	updateList (3505000L, 800, "USB", MODE_CW);
     	updateList (3580000L, 1000, "USB", MODE_PSK31 );
    @@ -312,39 +326,82 @@ void buildlist()
     	updateList (28005000L, 800, "USB", MODE_CW);
     	updateList (28120000, 1000, "USB", MODE_PSK31 );
     	updateSelect();
    -//	Fl::unlock();
    +
     }
     
     int cb_qso_opMODE()
     {
    +	if (connected_to_flrig) {
    +		set_flrig_mode(qso_opMODE->value());
    +		return 0;
    +	}
     #if USE_HAMLIB
     	if (progdefaults.chkUSEHAMLIBis)
     		hamlib_setmode(mode_nums[qso_opMODE->value()]);
     	else
     #endif
    +	if (progdefaults.chkUSERIGCATis)
     		rigCAT_setmode(qso_opMODE->value());
    -	set_flrig_mode(qso_opMODE->value());
    +	else
    +		noCAT_setmode(qso_opMODE->value());
     	return 0;
     }
     
     int cb_qso_opBW()
     {
    -	if (progdefaults.chkUSERIGCATis)
    -//    if (!progdefaults.chkUSEXMLRPCis)
    +	if (connected_to_flrig)
    +		set_flrig_bw(qso_opBW->index(), -1);
    +	else if (progdefaults.chkUSERIGCATis)
     		rigCAT_setwidth(qso_opBW->value());
    -	set_flrig_bw(qso_opBW->index());
    +	else
    +		noCAT_setwidth(qso_opBW->value());
    +	return 0;
    +}
    +
    +int  cb_qso_btnBW1()
    +{
    +	qso_btnBW1->hide();
    +	qso_opBW1->hide();
    +	qso_btnBW2->show();
    +	qso_opBW2->show();
    +	return 0;
    +}
    +
    +int cb_qso_btnBW2()
    +{
    +	qso_btnBW2->hide();
    +	qso_opBW2->hide();
    +	qso_btnBW1->show();
    +	qso_opBW1->show();
    +	return 0;
    +}
    +
    +int cb_qso_opBW1()
    +{
    +//printf("opBW1 %d:%s\n", qso_opBW1->index(), qso_opBW1->value());
    +	set_flrig_bw(qso_opBW2->index(), qso_opBW1->index());
    +	return 0;
    +}
    +
    +int cb_qso_opBW2()
    +{
    +//printf("opBW2 %d:%s\n", qso_opBW2->index(), qso_opBW2->value());
    +	set_flrig_bw(qso_opBW2->index(), qso_opBW1->index());
     	return 0;
     }
     
     void sendFreq(long int f)
     {
    +	if (connected_to_flrig)
    +		set_flrig_freq(f);
     #if USE_HAMLIB
    -	if (progdefaults.chkUSEHAMLIBis)
    -		hamlib_setfreq(f);
    -	else
    +	else if (progdefaults.chkUSEHAMLIBis)
    +			hamlib_setfreq(f);
     #endif
    +	else if (progdefaults.chkUSERIGCATis)
     		rigCAT_setfreq(f);
    -	set_flrig_freq(f);
    +	else
    +		noCAT_setfreq(f);
     }
     
     void qso_movFreq(Fl_Widget* w, void *data)
    @@ -449,6 +506,15 @@ void qso_addFreq()
     	}
     }
     
    +void qso_updateEntry(int i, std::string usage)
    +{
    +	int v = i - 1;
    +	int sz = (int)freqlist.size();
    +	if ((v >= 0) && (v < sz)) {
    +		freqlist[v].usage = usage;
    +	}
    +}
    +
     void setTitle()
     {
     	if (windowTitle.empty()) return;
    @@ -462,8 +528,6 @@ bool init_Xml_RigDialog()
     {
     	LOG_DEBUG("xml rig");
     	initOptionMenus();
    -	clearList();
    -	buildlist();
     	windowTitle = xmlrig.rigTitle;
     	setTitle();
     	return true;
    @@ -475,21 +539,34 @@ bool init_NoRig_RigDialog()
     	qso_opBW->deactivate();
     	qso_opMODE->clear();
     
    +printf("init_NoRig_RigDialog()\n");
     	for (size_t i = 0; i < sizeof(modes)/sizeof(modes[0]); i++) {
    +printf("adding %s\n", modes[i].name);
     		qso_opMODE->add(modes[i].name);
     	}
    +// list of LSB type modes that various xcvrs report via flrig
     	LSBmodes.clear();
     	LSBmodes.push_back("LSB");
    -	LSBmodes.push_back("CWR");
    +	LSBmodes.push_back("LSB-D");
    +	LSBmodes.push_back("LSB-D1");
    +	LSBmodes.push_back("LSB-D2");
    +	LSBmodes.push_back("LSB-D3");
    +	LSBmodes.push_back("CW");
    +	LSBmodes.push_back("LCW");
    +	LSBmodes.push_back("CW-N");
    +	LSBmodes.push_back("CWL");
     	LSBmodes.push_back("RTTY");
    +	LSBmodes.push_back("RTTY-L");
     	LSBmodes.push_back("PKTLSB");
    +	LSBmodes.push_back("PKT-L");
    +	LSBmodes.push_back("USER-L");
    +	LSBmodes.push_back("DATA-L");
    +	LSBmodes.push_back("DATA");
    +	LSBmodes.push_back("D-LSB");
     
    -	qso_opMODE->index(0);
    +	qso_opMODE->index(3);
     	qso_opMODE->activate();
     
    -	clearList();
    -	buildlist();
    -
     	windowTitle.clear();
     	setTitle();
     
    @@ -509,8 +586,6 @@ bool init_Hamlib_RigDialog()
     		mode_names[modes[i].mode] = modes[i].name;
     		qso_opMODE->add(modes[i].name);
     	}
    -	clearList();
    -	buildlist();
     
     	windowTitle = "Hamlib ";
     	windowTitle.append(xcvr->getName());
    diff --git a/src/rigcontrol/rigxml.cxx b/src/rigcontrol/rigxml.cxx
    index 944c7f37..c32285c8 100644
    --- a/src/rigcontrol/rigxml.cxx
    +++ b/src/rigcontrol/rigxml.cxx
    @@ -44,6 +44,7 @@
     #include "confdialog.h"
     
     #include "icons.h"
    +#include "fl_digi.h"
     
     using namespace std;
     
    @@ -62,9 +63,13 @@ void parseMODEREPLY(size_t &);
     void parseTITLE(size_t &);
     void parseLSBMODES(size_t &);
     void parseDISCARD(size_t &);
    +void parseDEBUG(size_t &);
    +void parseNOSERIAL(size_t &);
    +void parseASCII(size_t &);
     
     void parseWRITE_DELAY(size_t &);
     void parseINIT_DELAY(size_t &);
    +void parseWAIT_FOR_DEVICE(size_t &);
     void parsePOST_WRITE_DELAY(size_t &);
     void parseRETRIES(size_t &);
     void parseTIMEOUT(size_t &);
    @@ -79,6 +84,12 @@ void parseDTRPTT(size_t &);
     void parseRESTORE_TIO(size_t &);
     void parseECHO(size_t &);
     void parseVSP(size_t &);
    +void parseLOGSTR(size_t &);
    +void parsePOLLINT(size_t &);
    +void parseSMETER(size_t &);
    +void parsePMETER(size_t &);
    +void parseNOTCH(size_t &);
    +void parsePWRLEVEL(size_t &);
     
     void parseIOSsymbol(size_t &);
     void parseIOSsize(size_t &);
    @@ -145,11 +156,21 @@ TAGS rigdeftags[] = {
     	{" 20000) val = 20000;
    +	xmlrig.pollinterval = val;
    +	size_t pend = tagEnd(p0);
    +	p0 = pend;
    +}
    +
    +void parseSMETER(size_t &p0) {
    +	string strmeter = getElement(p0);
    +	size_t pend = tagEnd(p0);
    +	p0 = pend;
    +	xmlrig.smeter.clear();
    +	int val, sm;
    +	size_t p = strmeter.find(",");
    +	while ( !strmeter.empty() && (p != string::npos) ) {
    +		val = atoi(&strmeter[0]);
    +		sm = atoi(&strmeter[p+1]);
    +		xmlrig.smeter.push_back(PAIR(val,sm));
    +		p = strmeter.find(";");
    +		if (p == string::npos) strmeter.clear();
    +		else {
    +			strmeter.erase(0, p+1);
    +			p = strmeter.find(",");
    +		}
    +	}
    +	xmlrig.use_smeter = true;
    +}
    +
    +void parsePMETER(size_t &p0) {
    +	string strmeter = getElement(p0);
    +	size_t pend = tagEnd(p0);
    +	p0 = pend;
    +	xmlrig.smeter.clear();
    +	int val, sm;
    +	size_t p = strmeter.find(",");
    +	while ( !strmeter.empty() && (p != string::npos) ) {
    +		val = atoi(&strmeter[0]);
    +		sm = atoi(&strmeter[p+1]);
    +		xmlrig.pmeter.push_back(PAIR(val,sm));
    +		p = strmeter.find(";");
    +		if (p == string::npos) strmeter.clear();
    +		else {
    +			strmeter.erase(0, p+1);
    +			p = strmeter.find(",");
    +		}
    +	}
    +	xmlrig.use_pwrmeter = true;
    +}
    +
    +void parseNOTCH(size_t &p0) {
    +	string strnotch = getElement(p0);
    +	size_t pend = tagEnd(p0);
    +	p0 = pend;
    +	xmlrig.notch.clear();
    +	int val, ntch;
    +	size_t p = strnotch.find(",");
    +	while ( !strnotch.empty() && (p != string::npos) ) {
    +		val = atoi(&strnotch[0]);
    +		ntch = atoi(&strnotch[p+1]);
    +		xmlrig.notch.push_back(PAIR(val,ntch));
    +		p = strnotch.find(";");
    +		if (p == string::npos) strnotch.clear();
    +		else {
    +			strnotch.erase(0, p+1);
    +			p = strnotch.find(",");
    +		}
    +	}
    +	xmlrig.use_notch = true;
    +}
    +
    +void parsePWRLEVEL(size_t &p0) {
    +	string strpwrlevel = getElement(p0);
    +	size_t pend = tagEnd(p0);
    +	p0 = pend;
    +	xmlrig.pwrlevel.clear();
    +	int val, pwr;
    +	float min = 500, max = 0;
    +	size_t p = strpwrlevel.find(",");
    +	while ( !strpwrlevel.empty() && (p != string::npos) ) {
    +		val = atoi(&strpwrlevel[0]);
    +		pwr = atoi(&strpwrlevel[p+1]);
    +		if (pwr < min) min = pwr;
    +		if (pwr > max) max = pwr;
    +		xmlrig.pwrlevel.push_back(PAIR(val,pwr));
    +		p = strpwrlevel.find(";");
    +		if (p == string::npos) strpwrlevel.clear();
    +		else {
    +			strpwrlevel.erase(0, p+1);
    +			p = strpwrlevel.find(",");
    +		}
    +	}
    +	pwr_level->range(min, max);
    +	xmlrig.use_pwrlevel = true;
    +}
    +
     //---------------------------------------------------------------------
     // Parse IOS (serial stream format) definitions
     //---------------------------------------------------------------------
    @@ -933,6 +1101,7 @@ bool readRigXML()
     		xmlfile.close();
     		if (testXML()) {
     			parseXML();
    +			xmlrig.xmlok = true;
     			return true;
     		}
     	}
    @@ -944,11 +1113,12 @@ void selectRigXmlFilename()
     	string deffilename;
     	deffilename = progdefaults.XmlRigFilename;
     	const char *p = FSEL::select(_("Open rig xml file"), _("Fldigi rig xml definition file\t*.xml"), deffilename.c_str());
    -	if (p) {
    -		progdefaults.XmlRigFilename = p;
    -		txtXmlRigFilename->value(fl_filename_name(p));
    -		loadRigXmlFile();
    -	}
    +	if (!p) return;
    +	if (!*p) return;
    +
    +	progdefaults.XmlRigFilename = p;
    +	txtXmlRigFilename->value(fl_filename_name(p));
    +	loadRigXmlFile();
     }
     
     void loadRigXmlFile(void)
    diff --git a/src/rigcontrol/serial.cxx b/src/rigcontrol/serial.cxx
    index 7f2f55a2..b37ebb51 100644
    --- a/src/rigcontrol/serial.cxx
    +++ b/src/rigcontrol/serial.cxx
    @@ -214,12 +214,12 @@ void Cserial::SetPTT(bool b)
     void Cserial::ClosePort()
     {
     	if (fd < 0) return;
    -	LOG_DEBUG("Serial port closed, fd = %d", fd);
     	if (restore_tio) {
     		ioctl(fd, TIOCMSET, &origstatus);
     		tcsetattr (fd, TCSANOW, &oldtio);
     	}
     	close(fd);
    +	LOG_INFO("Serial port closed, fd = %d", fd);
     	fd = -1;
     	return;
     }
    @@ -331,6 +331,7 @@ BOOL Cserial::OpenPort()
     		LOG_PERROR(win_error_string(errno).c_str());
     		return FALSE;
     	}
    +	LOG_INFO("COM port %s opened, handle = %d", device.c_str(), (int)hComm);
     
     	FlushBuffer();
     
    @@ -345,10 +346,15 @@ BOOL Cserial::OpenPort()
     ///////////////////////////////////////////////////////
     void Cserial::ClosePort()
     {
    -	if (hComm) {
    +	LOG_INFO("Closing COM port, handle = %d", (int)hComm);
    +
    +	if (hComm != INVALID_HANDLE_VALUE) {
     		if (restore_tio)
     			bPortReady = SetCommTimeouts (hComm, &CommTimeoutsSaved);
    -		CloseHandle(hComm);
    +		if (CloseHandle(hComm) == 0) {
    +			errno = GetLastError();
    +			LOG_PERROR(win_error_string(errno).c_str());
    +		}
     		hComm = INVALID_HANDLE_VALUE;
     	}
     	return;
    @@ -419,14 +425,7 @@ int Cserial::WriteBuffer(unsigned char *buff, int n)
     	if (WriteFile (hComm, buff, n, &nBytesWritten, NULL) == 0) {
     		errno = GetLastError();
     		LOG_PERROR(win_error_string(errno).c_str());
    -		ClosePort();
    -		OpenPort();
    -		if (WriteFile (hComm, buff, n, &nBytesWritten, NULL) == 0) {
    -			errno = GetLastError();
    -			LOG_PERROR(win_error_string(errno).c_str());
    -			ClosePort();
    -			return 0;
    -		}
    +		return 0;
     	}
     
     	return nBytesWritten;
    diff --git a/src/rigcontrol/xmlrpc_rig.cxx b/src/rigcontrol/xmlrpc_rig.cxx
    index bcc67996..780f5bf5 100644
    --- a/src/rigcontrol/xmlrpc_rig.cxx
    +++ b/src/rigcontrol/xmlrpc_rig.cxx
    @@ -45,13 +45,14 @@
     #include "qrunner.h"
     #include "debug.h"
     #include "status.h"
    +#include "icons.h"
     
    -static bool XMLRPC_DEBUG = 0;
    +LOG_FILE_SOURCE(debug::debug::LOG_XMLRPC_RIG);
     
     using namespace XmlRpc;
     using namespace std;
     
    -int xmlrpc_verbosity = 0;
    +static int xmlrpc_verbosity = 0;
     
     //======================================================================
     // flrig xmlrpc client
    @@ -83,21 +84,24 @@ void connect_to_flrig();
     
     XmlRpcClient *flrig_client = (XmlRpcClient *)0;
     
    -bool bws_posted = false;
    -bool bw_posted = false;
    -bool mode_posted = false;
    -bool modes_posted = false;
    -bool freq_posted = true;
    -
    -string xcvr_name;
    -string str_freq;
    -string mode_result;
    -XmlRpcValue modes_result;
    -XmlRpcValue bws_result;
    -XmlRpcValue bw_result;
    -XmlRpcValue notch_result;
    -
    +//----------------------------------------------------------------------
    +// declared as extern in rigsupport.h
    +//----------------------------------------------------------------------
     bool connected_to_flrig = false;
    +//----------------------------------------------------------------------
    +
    +static bool bws_posted = false;
    +static bool modes_posted = false;
    +static bool freq_posted = true;
    +
    +static string xcvr_name;
    +static string str_freq;
    +static string mode_result;
    +static XmlRpcValue modes_result;
    +static XmlRpcValue bws_result;
    +static XmlRpcValue bw_result;
    +static XmlRpcValue notch_result;
    +
     static double timeout = 2.0;
     //======================================================================
     
    @@ -107,46 +111,91 @@ void xmlrpc_rig_set_qsy(long long rfc)
     	wf->rfcarrier(rfc);
     	wf->movetocenter();
     	show_frequency(rfc);
    -if (XMLRPC_DEBUG) std::cout << "set qsy: " << rfc << "\n";
    +	LOG_INFO("set qsy: %d", (int)rfc);
     }
     
     //======================================================================
     // set / get pairs
     //======================================================================
     
    +//----------------------------------------------------------------------
    +// To prevent a FLTK library thread deadlock on MacOSX
    +//----------------------------------------------------------------------
    +static void ptt_on_off_failure(void * ptt_flag)
    +{
    +    int flag = *((int *) ptt_flag);
    +    fl_alert2("fldigi/flrig PTT %s failure", flag ? "ON" : "OFF");
    +}
    +
     //----------------------------------------------------------------------
     // push to talk
     //----------------------------------------------------------------------
    -bool wait_ptt = false; // wait for transceiver to respond
    -int  wait_ptt_timeout = 5; // 5 polls and then disable wait
    -int  ptt_state = 0;
    +static bool wait_ptt = false; // wait for transceiver to respond
    +static int  wait_ptt_timeout = 5; // 5 polls and then disable wait
    +static int  ptt_state = 0;
     
    -void set_flrig_ptt(int on) {
    -	if (!connected_to_flrig) return;
    +static int  new_ptt = -1;
    +static int  last_new_ptt = -1;
    +
    +void exec_flrig_ptt() {
    +	if (!connected_to_flrig) {
    +		new_ptt = -1;
    +		return;
    +	}
     
     	XmlRpcValue val, result;
    -	val = int(on);
    +	int resp, res;
     
    -	guard_lock flrig_lock(&mutex_flrig);
    -	if (flrig_client->execute("rig.set_ptt", val, result, timeout)) {
    -		wait_ptt = true;
    -		wait_ptt_timeout = 10;
    -		ptt_state = on;
    -if (XMLRPC_DEBUG) std::cout << "ptt: " << on << "\n";
    -	} else {
    -		wait_ptt = false;
    -		wait_ptt_timeout = 0;
    -		LOG_ERROR("%s", "rig.set_vfo failed");
    +// PTT on/off is critical 5 attempts with 10 verify reads per attempt
    +	for (int i = 0; i < 5; i++) {
    +		res = flrig_client->execute("rig.set_ptt", new_ptt, result, timeout);
    +		if (res) {
    +			for (int j = 0; j < 10; j++) {
    +				MilliSleep(20);
    +				res = flrig_client->execute("rig.get_ptt", XmlRpcValue(), result, 10);
    +				if (res) {
    +					resp = (int)result;
    +					if (resp == new_ptt) {
    +						wait_ptt = true;
    +						wait_ptt_timeout = 10;
    +						ptt_state = new_ptt;
    +						LOG_INFO("ptt %s in %d msec",
    +							ptt_state ? "ON" : "OFF",
    +							i*50 + (j + 1)*20);
    +						new_ptt = -1;
    +						return;
    +					}
    +				}
    +			}
    +		}
     	}
    +
    +	wait_ptt = false;
    +	wait_ptt_timeout = 0;
    +	LOG_ERROR("%s", "rig.set_ptt failed (3)");
    +    // FLTK thread dead lock on MacOSX. Call in main thread.
    +    // fl_alert2("fldigi/flrig PTT %s failure", new_ptt ? "ON" : "OFF");
    +    last_new_ptt = new_ptt;
    +    REQ(ptt_on_off_failure, (void *) &last_new_ptt);
    +	new_ptt = -1;
     	return;
     }
     
    +void set_flrig_ptt(int on) {
    +	guard_lock flrig_lock(&mutex_flrig);
    +	new_ptt = on;
    +}
    +
     pthread_mutex_t mutex_flrig_ptt = PTHREAD_MUTEX_INITIALIZER;
    +
     void xmlrpc_rig_show_ptt(void *data)
     {
     	guard_lock flrig_lock(&mutex_flrig_ptt);
     	int on = reinterpret_cast(data);
    -	if (wf) wf->xmtrcv->value(on);
    +	if (wf) {
    +		wf->xmtrcv->value(on);
    +		wf->xmtrcv->do_callback();
    +	}
     }
     
     void flrig_get_ptt()
    @@ -159,7 +208,7 @@ void flrig_get_ptt()
     			ptt_state = val;
     			guard_lock flrig_lock(&mutex_flrig_ptt);
     			Fl::awake(xmlrpc_rig_show_ptt, reinterpret_cast(val) );
    -if (XMLRPC_DEBUG) std::cout << "get_ptt: " << ptt_state << "\n";
    +			LOG_INFO("get_ptt: %s", ptt_state ? "ON" : "OFF");
     		} else if (wait_ptt && (val == ptt_state)) {
     			wait_ptt = false;
     			wait_ptt_timeout = 0;
    @@ -172,7 +221,7 @@ if (XMLRPC_DEBUG) std::cout << "get_ptt: " << ptt_state << "\n";
     		connected_to_flrig = false;
     		wait_ptt = false;
     		wait_ptt_timeout = 5;
    -if (XMLRPC_DEBUG) std::cout << "get_ptt failed!\n";
    +		LOG_ERROR("%s", "get_ptt failed!");
     	}
     }
     
    @@ -180,9 +229,21 @@ if (XMLRPC_DEBUG) std::cout << "get_ptt failed!\n";
     // transceiver radio frequency
     //----------------------------------------------------------------------
     
    -bool wait_freq = false; // wait for transceiver to respond
    -int  wait_freq_timeout = 5; // 5 polls and then disable wait
    -long int  xcvr_freq = 0;
    +static bool wait_freq = false; // wait for transceiver to respond
    +static int  wait_freq_timeout = 5; // 5 polls and then disable wait
    +static long int  xcvr_freq = 0;
    +
    +pthread_mutex_t mutex_flrig_freq = PTHREAD_MUTEX_INITIALIZER;
    +
    +void xmlrpc_rig_show_freq(void * fr)
    +{
    +	guard_lock flrig_lock(&mutex_flrig_freq);
    +	if (!wf) return;
    +	long freq = reinterpret_cast(fr);
    +	wf->rfcarrier(freq);
    +	wf->movetocenter();
    +	show_frequency(freq);
    +}
     
     void set_flrig_freq(long int fr)
     {
    @@ -200,21 +261,11 @@ void set_flrig_freq(long int fr)
     		wait_freq = true;
     		wait_freq_timeout = 5;
     		xcvr_freq = fr;
    -if (XMLRPC_DEBUG) std::cout << "set freq: " << xcvr_freq << "\n";
    +		Fl::awake(xmlrpc_rig_show_freq, reinterpret_cast(fr));
    +		LOG_INFO("set freq: %d", (int)fr);
     	}
     }
     
    -pthread_mutex_t mutex_flrig_freq = PTHREAD_MUTEX_INITIALIZER;
    -void xmlrpc_rig_show_freq(void * fr)
    -{
    -	guard_lock flrig_lock(&mutex_flrig_freq);
    -	if (!wf) return;
    -	long freq = reinterpret_cast(fr);
    -	wf->rfcarrier(freq);
    -	wf->movetocenter();
    -	show_frequency(freq);
    -}
    -
     void flrig_get_frequency()
     {
     	guard_lock flrig_lock(&mutex_flrig);
    @@ -228,7 +279,7 @@ void flrig_get_frequency()
     			xcvr_freq = fr;
     			guard_lock flrig_lock(&mutex_flrig_freq);
     			Fl::awake(xmlrpc_rig_show_freq, reinterpret_cast(fr));
    -if (XMLRPC_DEBUG) std::cout << "get freq: " << xcvr_freq << "\n";
    +			LOG_INFO("get freq: %d", fr);
     		} else if (wait_freq && (fr == xcvr_freq)) {
     			wait_freq = false;
     			wait_freq_timeout = 0;
    @@ -240,7 +291,7 @@ if (XMLRPC_DEBUG) std::cout << "get freq: " << xcvr_freq << "\n";
     		connected_to_flrig = false;
     		wait_freq = false;
     		wait_freq_timeout = 5;
    -if (XMLRPC_DEBUG) std::cout << "get freq failed\n";
    +		LOG_ERROR("%s", "get freq failed");
     	}
     }
     
    @@ -249,9 +300,16 @@ if (XMLRPC_DEBUG) std::cout << "get freq failed\n";
     // transceiver get modes (mode table)
     //----------------------------------------------------------------------
     
    -bool wait_mode = false; // wait for transceiver to respond
    -int  wait_mode_timeout = 5; // 5 polls and then disable wait
    -string posted_mode = "";
    +static bool wait_mode = false; // wait for transceiver to respond
    +static int  wait_mode_timeout = 5; // 5 polls and then disable wait
    +static string posted_mode = "";
    +
    +static bool wait_bw = false; // wait for transceiver to respond
    +static int  wait_bw_timeout = 5; // 5 polls and then disable wait
    +static bool need_sideband = false;
    +static string  posted_bw = "";
    +static string  posted_bw1 = "";
    +static string  posted_bw2 = "";
     
     void set_flrig_mode(const char *md)
     {
    @@ -267,14 +325,22 @@ void set_flrig_mode(const char *md)
     		wait_mode_timeout = 5;
     	} else {
     		posted_mode = md;
    +		need_sideband = true;
     		bws_posted = false;
     		wait_mode = true;
     		wait_mode_timeout = 5;
    -if (XMLRPC_DEBUG) std::cout << "set mode: " << posted_mode << "\n";
    +		LOG_INFO("set mode: %s", md);
     	}
     }
     
     pthread_mutex_t mutex_flrig_mode = PTHREAD_MUTEX_INITIALIZER;
    +static bool xml_USB = true;
    +
    +bool xmlrpc_USB()
    +{
    +	return xml_USB;
    +}
    +
     void xmlrpc_rig_post_mode(void *data)
     {
     	guard_lock flrig_lock(&mutex_flrig_mode);
    @@ -282,6 +348,7 @@ void xmlrpc_rig_post_mode(void *data)
     	string *s = reinterpret_cast(data);
     	qso_opMODE->value(s->c_str());
     	bws_posted = false;
    +	need_sideband = false;
     }
     
     void flrig_get_mode()
    @@ -292,11 +359,18 @@ void flrig_get_mode()
     		static string md;
     		md = string(res);
     		bool posted = (md == posted_mode);
    -		if (!wait_mode && !posted) {
    +		if (!wait_mode && (!posted || need_sideband)) {
     			posted_mode = md;
    -			guard_lock flrig_lock(&mutex_flrig_mode);
    +			guard_lock flrig_modelock(&mutex_flrig_mode);
    +			if (flrig_client->execute("rig.get_sideband", XmlRpcValue(), res, timeout) ) {
    +				static string sb;
    +				sb = string(res);
    +				xml_USB = (sb[0] == 'U');
    +			} else {
    +				xml_USB = true;
    +			}
     			Fl::awake(xmlrpc_rig_post_mode, reinterpret_cast(&md));
    -if (XMLRPC_DEBUG) std::cout << "get mode: " << posted_mode << "\n";
    +			LOG_INFO("get mode: %s:%s", md.c_str(), xml_USB ? "USB" : "LSB");
     		} else if (wait_mode && posted) {
     			wait_mode = false;
     			wait_mode_timeout = 0;
    @@ -308,7 +382,7 @@ if (XMLRPC_DEBUG) std::cout << "get mode: " << posted_mode << "\n";
     		connected_to_flrig = false;
     		wait_mode = false;
     		wait_freq_timeout = 0;
    -if (XMLRPC_DEBUG) std::cout << "get mode failed\n";
    +		LOG_ERROR("%s", "get mode failed");
     	}
     }
     
    @@ -329,10 +403,8 @@ void xmlrpc_rig_post_modes(void *)
     		return;
     	}
     
    -	for (int i = 0; i < nargs; i++) {
    +	for (int i = 0; i < nargs; i++)
     		qso_opMODE->add(string(modes_result[i]).c_str());
    -if (XMLRPC_DEBUG) std::cout << "post mode: " << string(modes_result[i]) << "\n";
    -}
     
     	qso_opMODE->index(0);
     	qso_opMODE->activate();
    @@ -347,7 +419,18 @@ void flrig_get_modes()
     	if (flrig_client->execute("rig.get_modes", XmlRpcValue(), modes_result, timeout) ) {
     		guard_lock flrig_lock(&mutex_flrig_modes);
     		Fl::awake(xmlrpc_rig_post_modes);
    -if (XMLRPC_DEBUG) std::cout << "get modes\n";
    +		posted_mode = posted_bw = posted_bw1 = posted_bw2 = "GETME";
    +		{
    +			int nargs = modes_result.size();
    +			static string debugstr;
    +			debugstr.assign("Mode table: ");
    +			for (int i = 0; i < nargs - 1; i++)
    +				debugstr.append(modes_result[i]).append(",");
    +			debugstr.append(modes_result[nargs-1]);
    +			LOG_INFO("%s", debugstr.c_str());
    +		}
    +	} else {
    +		LOG_ERROR("%s", "get modes failed");
     	}
     }
     
    @@ -355,139 +438,209 @@ if (XMLRPC_DEBUG) std::cout << "get modes\n";
     // transceiver get / set bandwidth
     // transceiver get bandwidth table
     //----------------------------------------------------------------------
    -bool wait_bw = false; // wait for transceiver to respond
    -int  wait_bw_timeout = 5; // 5 polls and then disable wait
    -string  posted_bw = "";
     
    -void set_flrig_bw(int bw1, int bw2)
    +void set_flrig_bw(int bw2, int bw1)
     {
     	if (!connected_to_flrig) return;
     
     	XmlRpcValue val, result;
    -	val = 256*bw2 + bw1;
    +	int ival = bw2;
    +	if (bw1 > -1) ival = 256*(bw1+128) + bw2;
    +	val = ival;
     
     	guard_lock flrig_lock(&mutex_flrig);
    +	LOG_INFO("set_flrig_bw %04X", ival);
     	if (!flrig_client->execute("rig.set_bw", val, result, timeout)) {
     		LOG_ERROR("%s", "rig.set_bw failed");
     		wait_bw = false;
     		wait_bw_timeout = 0;
     	} else {
    -		posted_bw = qso_opBW->value();
     		wait_bw = true;
     		wait_bw_timeout = 5;
    -if (XMLRPC_DEBUG) std::cout << "set bw: " << posted_bw << "\n";
     	}
     }
     
     pthread_mutex_t mutex_flrig_bw = PTHREAD_MUTEX_INITIALIZER;
    -void xmlrpc_rig_post_bw(void *data)
    +void xmlrpc_rig_post_bw(void *)
     {
     	guard_lock flrig_lock(&mutex_flrig_bw);
     	if (!qso_opBW) return;
     
    -	string *s = reinterpret_cast(data);
    -	size_t p = s->find("|");
    -	if (p != string::npos) s->erase(p);
    +	if (posted_bw != (std::string)(qso_opBW->value())) {
    +		qso_opBW->value(posted_bw.c_str());
    +		qso_opBW->redraw();
    +		LOG_INFO("Update BW %s", posted_bw.c_str());
    +	}
    +}
     
    -	qso_opBW->value(s->c_str());
    -	qso_opBW->redraw();
    +void xmlrpc_rig_post_bw1(void *)
    +{
    +	guard_lock flrig_lock(&mutex_flrig_bw);
    +	if (!qso_opBW1) return;
    +
    +	if (posted_bw1 != (std::string)(qso_opBW1->value())) {
    +		qso_opBW1->value(posted_bw1.c_str());
    +		qso_opBW1->redraw();
    +		LOG_INFO("Update combo BW1 %s", posted_bw1.c_str());
    +	}
    +}
    +
    +void xmlrpc_rig_post_bw2(void *)
    +{
    +	guard_lock flrig_lock(&mutex_flrig_bw);
    +	if (!qso_opBW2) return;
    +	if (posted_bw2 != (std::string)(qso_opBW2->value())) {
    +		qso_opBW2->value(posted_bw2.c_str());
    +		qso_opBW2->redraw();
    +		LOG_INFO("Update combo BW2 %s", posted_bw2.c_str());
    +	}
     }
     
     void flrig_get_bw()
     {
     	guard_lock flrig_lock(&mutex_flrig);
     	XmlRpcValue res;
    +	if (wait_bw_timeout) {
    +		wait_bw_timeout--;
    +		return;
    +	}
    +
     	if (flrig_client->execute("rig.get_bw", XmlRpcValue(), res, timeout) ) {
     		static string s1;
     		static string s2;
     
    -		s1 = string(res[0]);
    -		s2 = string(res[1]);
    -
    -		bool posted = ((s1 == posted_bw));
    -		if (!wait_bw && !posted) {
    -			posted_bw = s1;
    -			guard_lock flrig_lock(&mutex_flrig_bw);
    -			Fl::awake(xmlrpc_rig_post_bw, reinterpret_cast(&s1));
    -if (XMLRPC_DEBUG) std::cout << "get bw: " << posted_bw << "\n";
    -		} else if (wait_bw && !posted) {
    -			wait_bw = false;
    -			wait_bw_timeout = 0;
    -		} else if (wait_bw_timeout == 0) {
    -			wait_bw = false;
    -		} else if (wait_bw_timeout)
    -			--wait_bw_timeout;
    +		s2 = string(res[0]);
    +		s1 = string(res[1]);
    +		if (!s1.empty())  {
    +			posted_bw1 = s1;
    +			Fl::awake(xmlrpc_rig_post_bw1);
    +			posted_bw2 = s2;
    +			Fl::awake(xmlrpc_rig_post_bw2);
    +		} else {
    +			if (!s2.empty()) {
    +				posted_bw = s2;
    +				Fl::awake(xmlrpc_rig_post_bw);
    +			}
    +		}
    +		wait_bw_timeout = 0;
     	} else {
     		connected_to_flrig = false;
    -		wait_bw = false;
     		wait_bw_timeout = 0;
    -if (XMLRPC_DEBUG) std::cout << "get bw failed!\n";
    +		LOG_ERROR("%s", "get bw failed!");
     	}
     }
     
     pthread_mutex_t mutex_flrig_bws = PTHREAD_MUTEX_INITIALIZER;
     void xmlrpc_rig_post_bws(void *)
     {
    -//	guard_lock flrig_lock(&mutex_flrig_bws);
     	if (!qso_opBW) return;
     
     	int nargs;
     
    -	try {
    -		nargs = bws_result[0].size();
    +	try { // two BW controls
    +		nargs = bws_result[1].size();
     
    -		qso_opBW->clear();
    -if (XMLRPC_DEBUG) std::cout << "cleared bw combo\n";
    +		static string bwstr;
    +		qso_opBW1->clear();
    +		for (int i = 1; i < nargs; i++) {
    +			bwstr = string(bws_result[1][i]);
    +			qso_opBW1->add(bwstr.c_str());
    +		}
     
    -		if (nargs == 0) {
    +		string labels1 = bws_result[1][0];
    +		static char btn1_label[2];
    +		btn1_label[0] = labels1[0]; btn1_label[1] = 0;
    +		qso_btnBW1->label(btn1_label);
    +		qso_btnBW1->redraw_label();
    +		qso_btnBW1->redraw();
    +		static char tooltip1[20];
    +		snprintf(tooltip1,sizeof(tooltip1),"%s",labels1.substr(2).c_str());
    +		qso_opBW1->tooltip(tooltip1);
    +		qso_opBW1->index(0);
    +		qso_opBW1->redraw();
    +
    +		{
    +			static string debugstr;
    +			debugstr.assign("\nBW1 table: ");
    +			for (int i = 1; i < nargs-1; i++)
    +				debugstr.append(string(bws_result[1][i])).append(", ");
    +			debugstr.append(string(bws_result[1][nargs - 1])).append("\n");
    +			debugstr.append(labels1);
    +			LOG_INFO("%s", debugstr.c_str());
    +		}
    +
    +		try {
    +			nargs = bws_result[0].size();
    +
    +			static string bwstr;
    +			qso_opBW2->clear();
    +			for (int i = 1; i < nargs; i++) {
    +				bwstr = string(bws_result[0][i]);
    +				qso_opBW2->add(bwstr.c_str());
    +			}
    +
    +			string labels2 = bws_result[0][0];
    +			static char btn2_label[2];
    +			btn2_label[0] = labels2[0]; btn2_label[1] = 0;
    +			qso_btnBW2->label(btn2_label);
    +			qso_btnBW2->redraw_label();
    +			qso_btnBW2->redraw();
    +			static char tooltip2[20];
    +			snprintf(tooltip2,sizeof(tooltip2),"%s",labels2.substr(2).c_str());
    +			qso_opBW2->tooltip(tooltip2);
    +			qso_opBW2->index(0);
    +			qso_opBW2->redraw();
    +
    +			{
    +				static string debugstr;
    +				debugstr.assign("\nBW2 table: ");
    +				for (int i = 1; i < nargs-1; i++)
    +					debugstr.append(string(bws_result[0][i])).append(", ");
    +				debugstr.append(string(bws_result[0][nargs - 1])).append("\n");
    +				debugstr.append(labels2);
    +				LOG_INFO("%s", debugstr.c_str());
    +			}
    +
    +		} catch ( XmlRpcException err) {
    +			bws_posted = false;
    +			return;
    +		}
    +		qso_opBW->hide();
    +		qso_opGROUP->show();
    +		bws_posted = true;
    +		return;
    +	} catch (XmlRpcException err) {
    +		try { // one BW control
    +			nargs = bws_result[0].size();
    +			string bwstr;
    +			qso_opBW->clear();
    +			for (int i = 1; i < nargs; i++) {
    +				bwstr = string(bws_result[0][i]);
    +				qso_opBW->add(bwstr.c_str());
    +			}
    +			qso_opBW->index(0);
    +			qso_opBW->activate();
    +			qso_opBW->tooltip("xcvr bandwidth");
    +			qso_opBW->show();
    +			qso_opGROUP->hide();
    +
    +			{
    +				static string debugstr;
    +				debugstr.assign("BW table: ");
    +				for (int i = 1; i < nargs-1; i++)
    +					debugstr.append(string(bws_result[0][i])).append(", ");
    +				debugstr.append(string(bws_result[0][nargs - 1]));
    +				LOG_INFO("%s", debugstr.c_str());
    +			}
    +
    +		} catch (XmlRpcException err) {
    +			LOG_ERROR("%s", "no bandwidths specified");
     			qso_opBW->add("");
     			qso_opBW->index(0);
     			qso_opBW->deactivate();
     			return;
     		}
    -
    -		string bwstr;
    -		for (int i = 1; i < nargs; i++) {
    -			bwstr = string(bws_result[0][i]);
    -			qso_opBW->add(bwstr.c_str());
    -if (XMLRPC_DEBUG) std::cout << "added bw: " << bwstr << "\n";
    -		}
    -
    -		qso_opBW->index(0);
    -		qso_opBW->activate();
    -
    -		qso_opBW->tooltip("xcvr bandwidth");
    -
    -	} catch (XmlRpcException err) {
    -		;
     	}
    -/*
    -	string label;
    -	size_t p;
    -// add later
    -	try {
    -		nargs = bws_result[1].size();
    -		if (nargs > 1) {
    -			label = string(bws_result[1][0]);
    -			if ( (p = label.find("|")) != string::npos)
    -				label.erase(0, p + 1);
    -			bw2Label->value(label.c_str());
    -			for (int i = 1; i < nargs; i++) {
    -				bw2->add(string(bws_result[1][i]).c_str());
    -			}
    -			bw2Label->redraw();
    -			bw2->activate();
    -		} else
    -			bw2->add("");
    -	} catch (XmlRpcException err) {
    -		bw2->deactivate();
    -	}
    -	bw1->redraw_label();
    -	bw1->redraw();
    -	bw2->redraw_label();
    -	bw2->redraw();
    -*/
    -
     	bws_posted = true;
     }
     
    @@ -500,11 +653,9 @@ void flrig_get_bws()
     		wait_bw = true;
     		wait_bw_timeout = 5;
     		posted_bw.clear();
    -//		guard_lock flrig_lock(&mutex_flrig_bws);
     		Fl::awake(xmlrpc_rig_post_bws);
    -if (XMLRPC_DEBUG) std::cout << "get bws\n";
     	} else {
    -if (XMLRPC_DEBUG) std::cout << "get bws failed\n";
    +		LOG_ERROR("%s", "get bws failed");
     	}
     }
     
    @@ -559,9 +710,9 @@ void flrig_get_vfo()
     //==============================================================================
     // transceiver set / get notch
     //==============================================================================
    -bool wait_notch = false; // wait for transceiver to respond
    -int  wait_notch_timeout = 5; // 5 polls and then disable wait
    -int  xcvr_notch = 0;
    +static bool wait_notch = false; // wait for transceiver to respond
    +static int  wait_notch_timeout = 5; // 5 polls and then disable wait
    +static int  xcvr_notch = 0;
     
     void set_flrig_notch()
     {
    @@ -715,8 +866,8 @@ bool flrig_get_xcvr()
     //======================================================================
     // xmlrpc read polling thread
     //======================================================================
    -bool run_flrig_thread = true;
    -int poll_interval = 100; // milliseconds
    +static bool run_flrig_thread = true;
    +static int poll_interval = 100; // 1 second
     
     //----------------------------------------------------------------------
     // Set QSY to true if xmlrpc client connection is OK
    @@ -730,7 +881,6 @@ void flrig_setQSY(void *)
     
     void flrig_connection()
     {
    -//	guard_lock flrig_lock(&mutex_flrig);
     	XmlRpcValue noArgs, result;
     	try {
     		bool ret;
    @@ -738,7 +888,6 @@ void flrig_connection()
     			guard_lock flrig_lock(&mutex_flrig);
     			ret = flrig_client->execute("system.listMethods", noArgs, result, timeout);
     		}
    -//		if (flrig_client->execute("system.listMethods", noArgs, result, timeout)) {
     		if (ret) {
     			int nargs = result.size();
     			string method_str = "\nMethods:\n";
    @@ -746,14 +895,17 @@ void flrig_connection()
     				method_str.append("    ").append(result[i]).append("\n");
     			LOG_INFO("%s", method_str.c_str());
     			connected_to_flrig = true;
    -			poll_interval = 100;
    +			poll_interval = 20; // every 200 msec
     			flrig_get_xcvr();
     			Fl::awake(flrig_setQSY);
     		} else {
    +			LOG_VERBOSE("%s", "Waiting for flrig");
     			connected_to_flrig = false;
    -			poll_interval = 500;
    +			poll_interval = 500; // every 5 seconds
     		}
    -	} catch (...) {}
    +	} catch (...) {
    +		LOG_ERROR("%s", "failure in flrig_client");
    +	}
     }
     
     void connect_to_flrig()
    @@ -767,18 +919,27 @@ void connect_to_flrig()
     		flrig_client = new XmlRpcClient(
     				progdefaults.flrig_ip_address.c_str(),
     				atol(progdefaults.flrig_ip_port.c_str()));
    +		LOG_INFO("created flrig xmlrpc client  %s, %ld",
    +				progdefaults.flrig_ip_address.c_str(),
    +				atol(progdefaults.flrig_ip_port.c_str()));
     		flrig_connection();
     	} catch (...) {
    -			LOG_ERROR("Cannot connect to %s, %s",
    -						progdefaults.flrig_ip_address.c_str(),
    -						progdefaults.flrig_ip_port.c_str());
    +		LOG_ERROR("Cannot create flrig xmlrpc client %s, %s",
    +					progdefaults.flrig_ip_address.c_str(),
    +					progdefaults.flrig_ip_port.c_str());
     	}
     }
     
     void * flrig_thread_loop(void *d)
     {
    -	for(;;) {
    -		MilliSleep( poll_interval );//progStatus.poll_interval);
    +	while(run_flrig_thread) {
    +		for (int i = 0; i < poll_interval; i++) {
    +			if (!run_flrig_thread) {
    +				LOG_INFO("Exiting thread - 1");
    +				return NULL;
    +			}
    +			MilliSleep(10);
    +		}
     
     		if (!run_flrig_thread) break;
     
    @@ -786,7 +947,11 @@ void * flrig_thread_loop(void *d)
     			connect_to_flrig();
     		if (!connected_to_flrig) flrig_connection();
     		else if (flrig_get_xcvr()) {
    -			flrig_get_ptt();
    +			if (new_ptt > -1) {
    +				exec_flrig_ptt();
    +				continue;
    +			}
    +			if (progdefaults.flrig_keys_modem) flrig_get_ptt();
     			if (trx_state == STATE_RX) {
     				flrig_get_frequency();
     				flrig_get_smeter();
    @@ -800,13 +965,14 @@ void * flrig_thread_loop(void *d)
     				flrig_get_pwrmeter();
     		}
     	}
    +	LOG_INFO("Exiting thread - 2");
     	return NULL;
     }
     
     void FLRIG_start_flrig_thread()
     {
     	flrig_thread = new pthread_t;
    -	poll_interval = 500;
    +	poll_interval = 100;
     	if (pthread_create(flrig_thread, NULL, flrig_thread_loop, NULL)) {
     		LOG_ERROR("%s", "flrig_thread create");
     		exit(EXIT_FAILURE);
    @@ -815,11 +981,13 @@ void FLRIG_start_flrig_thread()
     
     void stop_flrig_thread()
     {
    +	LOG_INFO("%s", "stopping flrig thread");
     	flrig_client->close();
     	pthread_mutex_lock(&mutex_flrig);
     		run_flrig_thread = false;
     	pthread_mutex_unlock(&mutex_flrig);
     	pthread_join(*flrig_thread, NULL);
    +	LOG_INFO("%s", "flrig thread closed");
     }
     
     void reconnect_to_flrig()
    diff --git a/src/rsid/rsid_defs.cxx b/src/rsid/rsid_defs.cxx
    index d58cbdf0..f15dd9a3 100644
    --- a/src/rsid/rsid_defs.cxx
    +++ b/src/rsid/rsid_defs.cxx
    @@ -288,6 +288,11 @@ const int cRsId::rsid_ids_size1 = sizeof(rsid_ids_1)/sizeof(*rsid_ids_1) - 1;
             ELEM2_(1078, PSK8P1000F, MODE_8PSK1000F)        \
             ELEM2_(1058, PSK8P1200F, MODE_8PSK1200F)        \
                                                             \
    +        ELEM2_(1239, PSK8P125FL, MODE_8PSK125FL)        \
    +        ELEM2_(2052, PSK8P250FL, MODE_8PSK250FL)        \
    +                                                        \
    +        ELEM2_(1171, IFKP, MODE_IFKP)                   \
    +                                                        \
             ELEM2_(0, NONE2, NUM_MODES)
     
     #define ELEM2_(code_, tag_, mode_) RSID_ ## tag_ = code_,
    diff --git a/src/soundcard/sound.cxx b/src/soundcard/sound.cxx
    index c033a5de..65feb91c 100644
    --- a/src/soundcard/sound.cxx
    +++ b/src/soundcard/sound.cxx
    @@ -159,8 +159,8 @@ void SoundBase::get_file_params(const char* def_fname, const char** fname, int*
     		*fname = FSEL::select(_("Audio file"), filters.c_str(), def_fname, &fsel);
     	else
     		*fname = FSEL::saveas(_("Audio file"), filters.c_str(), def_fname, &fsel);
    -	if (!*fname)
    -		return;
    +	if (!*fname) return;
    +	if (!**fname) return;
     
     	if (fsel >= nfilt) // "Default" save-as type on OS X
     		fsel = 0;
    @@ -1602,6 +1602,8 @@ void SoundPort::init_stream(unsigned dir)
     				else
     						sd[1].params.suggestedLatency = (*sd[dir].idev)->defaultHighOutputLatency;
     		sd[1].params.hostApiSpecificStreamInfo = NULL;
    +		if (max_channels < 2)
    +			sd[1].params.channelCount = max_channels;
     	}
     
     	const vector& rates = supported_rates[dir][(*sd[dir].idev)->name];
    diff --git a/src/soundcard/soundconf.cxx b/src/soundcard/soundconf.cxx
    index 6dc6a257..a88b9c1f 100644
    --- a/src/soundcard/soundconf.cxx
    +++ b/src/soundcard/soundconf.cxx
    @@ -118,15 +118,18 @@ ret_def:
     
     #include 
     
    +std::string str_pa_devices;
    +
     static void init_portaudio(void)
     {
     	try {
     		SoundPort::initialize();
     	}
     	catch (const SndException& e) {
    -		if (e.error() == ENODEV) // don't complain if there are no devices
    -			return;
    -		LOG_ERROR("%s", e.what());
    +//		if (e.error() == ENODEV) // don't complain if there are no devices
    +//			return;
    +		str_pa_devices.assign("\nPortaudio devices init failure:");
    +		str_pa_devices.assign(e.what());
     		AudioPort->deactivate();
     		btnAudioIO[SND_IDX_PORT]->deactivate();
     		if (progdefaults.btnAudioIOis == SND_IDX_PORT)
    @@ -150,12 +153,16 @@ static void init_portaudio(void)
     #endif
     
     	list devlist;
    +	int devnbr = 0;
     	for (SoundPort::device_iterator idev = SoundPort::devices().begin();
    -		 idev != SoundPort::devices().end(); ++idev)
    +		 idev != SoundPort::devices().end(); ++idev) {
     		devlist.push_back( padev(*idev, idev - SoundPort::devices().begin(),
     								 Pa_GetHostApiInfo((*idev)->hostApi)->type) );
    +		devnbr++;
    +	}
     	devlist.sort();
     
    +	str_pa_devices.assign("\nPortaudio devices:\n");
     	PaHostApiTypeId first_api = devlist.begin()->api;
     	for (list::const_iterator ilist = devlist.begin();
     		 ilist != devlist.end(); ilist++) {
    @@ -166,22 +173,24 @@ static void init_portaudio(void)
     			i = menu_item.length();
     		}
     		menu_item.append(ilist->dev->name);
    +
    +		str_pa_devices.append(menu_item).append("\n");
    +
     		// backslash-escape any slashes in the device name
     		while ((i = menu_item.find('/', i)) != string::npos) {
     			menu_item.insert(i, 1, '\\');
     			i += 2;
     		}
    +
     		// add to menu
    -		if (ilist->dev->maxInputChannels > 0) {
    +		if (ilist->dev->maxInputChannels > 0)
     			menuPortInDev->add(menu_item.c_str(), 0, NULL,
     							   reinterpret_cast(ilist->idx), 0);
    -		}
     
    -		if (ilist->dev->maxOutputChannels > 0) {
    +		if (ilist->dev->maxOutputChannels > 0)
     			menuPortOutDev->add(menu_item.c_str(), 0, NULL,
     								reinterpret_cast(ilist->idx), 0);
    -LOG_INFO("%s", menu_item.c_str());
    -		}
    +
     	}
     
     	if (progdefaults.PortInDevice.length() == 0) {
    diff --git a/src/spot/notify.cxx b/src/spot/notify.cxx
    index 4ec1bf58..2f8f729d 100644
    --- a/src/spot/notify.cxx
    +++ b/src/spot/notify.cxx
    @@ -1244,14 +1244,16 @@ static void notify_event_cb(Fl_Widget* w, void* arg)
     static void notify_program_select_cb(Fl_Widget* w, void* arg)
     {
     	const char* fn = FSEL::select(_("Run program"), "", 0, 0);
    -	if (fn) {
    -		inpNotifyActionProgram->value(fn);
    -		// quote program path
    -		inpNotifyActionProgram->position(0);
    -		inpNotifyActionProgram->insert("\"", 1);
    -		inpNotifyActionProgram->position(inpNotifyActionProgram->size());
    -		inpNotifyActionProgram->insert("\"", 1);
    -	}
    +	if (!fn) return;
    +	if (!*fn) return;
    +
    +	inpNotifyActionProgram->value(fn);
    +	// quote program path
    +	inpNotifyActionProgram->position(0);
    +	inpNotifyActionProgram->insert("\"", 1);
    +	inpNotifyActionProgram->position(inpNotifyActionProgram->size());
    +	inpNotifyActionProgram->insert("\"", 1);
    +
     }
     
     // the test button callback
    diff --git a/src/spot/pskrep.cxx b/src/spot/pskrep.cxx
    index f06a8b0c..e7468777 100644
    --- a/src/spot/pskrep.cxx
    +++ b/src/spot/pskrep.cxx
    @@ -418,9 +418,10 @@ void pskrep::append(string call, const char* loc, long long freq, trx_mode mode,
     	band_map_t& bandq = queue[call][band(freq)];
     	if (bandq.empty() || rtime - bandq.back().rtime >= DUP_INTERVAL) { // add new
     		bandq.push_back(rcpt_report_t(mode, freq, rtime, rtype, loc));
    -		LOG_VERBOSE("Added (call=\"%s\", loc=\"%s\", mode=\"%s\", freq=%d, time=%" PRIdMAX ", type=%u)",
    +		LOG_VERBOSE("Added (call=\"%s\", loc=\"%s\", mode=\"%s\", freq=%d, time=%d, type=%u)",
     			 call.c_str(), loc, mode_info[mode].adif_name,
    -			 static_cast(freq), (intmax_t)rtime, rtype);
    +			 static_cast(freq), 
    +			 static_cast(rtime), rtype);
     		new_count++;
     		save_queue();
     	}
    diff --git a/src/synop-src/synop.cxx b/src/synop-src/synop.cxx
    index 346836be..b43061a9 100644
    --- a/src/synop-src/synop.cxx
    +++ b/src/synop-src/synop.cxx
    @@ -113,7 +113,7 @@ static int diffTm( time_t tim1, time_t tim2 )
     static std::string Tm2SynopTime( time_t tim ) {
     	return KmlServer::Tm2Time( tim );
     }
    -	
    +
     // ----------------------------------------------------------------------------
     
     /// Base class for displaying the key-value pairs read from Synop broadcast.
    @@ -219,7 +219,7 @@ class RecordWmoStation
     
     	// WMO Region :digits 1 through 6 representing the corresponding WMO region, 7 stands for the WMO Antarctic region.
     
    -	// Station Latitude or Latitude :DD-MM-SSH where DD is degrees, MM is minutes, SS is seconds 
    +	// Station Latitude or Latitude :DD-MM-SSH where DD is degrees, MM is minutes, SS is seconds
     	// and H is N for northern hemisphere or S for southern hemisphere or
     	// E for eastern hemisphere or W for western hemisphere.
     	// The seconds value is omitted for those stations where the seconds value is unknown.
    @@ -253,7 +253,8 @@ public:
     	/// This garantees an unique name.
     	const std::string & station_name() const { return m_name; }
     	void rename_station( const std::string & nam ) {
    -		// LOG_INFO("Renaming %s to %s", m_name.c_str(), nam.c_str() );
    +		if (bMOREINFO)
    +			LOG_INFO("Renaming %s to %s", m_name.c_str(), nam.c_str() );
     		m_name = nam;
     	}
     
    @@ -280,7 +281,7 @@ public:
     
     		&& ( rec.m_station_coordinates.latitude().is_lon() == false    )
     		&& ( rec.m_station_coordinates.longitude().is_lon() == true    )
    -		) 
    +		)
     		{
     			strtrim( rec.m_name );
     			return istrm ;
    @@ -362,7 +363,7 @@ public:
     		&&  read_until_delim( m_delim, istrm, rec.m_timezone  )
     		&&  read_until_delim( m_delim, istrm, rec.m_forecast  )
     		&&  read_until_delim( m_delim, istrm, rec.m_note      )
    -		) 
    +		)
     		{
     			// std::cout << "id=" << rec.m_id << " name=" << rec.m_name << "\n";
     			return istrm ;
    @@ -403,7 +404,7 @@ public:
     		&&  read_until_delim( m_delim, istrm                  )
     		&&  read_until_delim( m_delim, istrm                  )
     		&&  read_until_delim( m_delim, istrm                  )
    -		) 
    +		)
     		{
     			strtrim( rec.m_country );
     			strtrim( rec.m_callsign );
    @@ -478,7 +479,7 @@ public:
     		&&  read_until_delim( m_delim, istrm  /* Alloc Date */     )
     		&&  read_until_delim( m_delim, istrm  /* Dealloc Date */   )
     		&&  read_until_delim( m_delim, istrm  /* Argos Prog */     )
    -		) 
    +		)
     		{
     			return istrm ;
     		}
    @@ -537,7 +538,8 @@ protected:
     			return false ;
     		}
     		else {
    -			LOG_INFO("record=%s nb_recs=%d", typeid(Record).name(), nbRec );
    +			if (bMOREINFO)
    +				LOG_INFO("record=%s nb_recs=%d", typeid(Record).name(), nbRec );
     			return true ;
     		}
     	}
    @@ -587,8 +589,10 @@ public:
     		typedef std::multimap< std::string, IteratorType > HashT ;
     		HashT allNames ;
     
    -		// First take the names 
    -		// LOG_INFO("Eliminating duplicates out of %d elements",m_catalog.size());
    +		// First take the names
    +		if (bMOREINFO)
    +			LOG_INFO("Eliminating duplicates out of %d elements",
    +				static_cast(m_catalog.size()));
     		for( IteratorType it = m_catalog.begin(), en = m_catalog.end(); it != en; ++it )
     		{
     			RecordWmoStation & refWmo = it->second ;
    @@ -600,7 +604,8 @@ public:
     		// Iterates on all names, take only the duplicates.
     		for( HashT::iterator itH = allNames.begin(), itNextH = itH, enH = allNames.end(); itH != enH; itH = itNextH )
     		{
    -			// LOG_INFO("Name=%s", itH->first.c_str() );
    +			if (bMOREINFO)
    +				LOG_INFO("Name=%s", itH->first.c_str() );
     			size_t nbKeys = 1 ;
     			for(;;) {
     				++itNextH;
    @@ -608,13 +613,20 @@ public:
     				if( itNextH->first != itH->first ) break ;
     				++nbKeys;
     			}
    -			// LOG_INFO("Name=%s nb=%d", itH->first.c_str(), nbKeys );
    +			if (bMOREINFO)
    +				LOG_INFO("Name=%s nb=%d", 
    +					itH->first.c_str(),
    +					static_cast(nbKeys) );
     
     			// If no duplicates, then try next one.
     			if( nbKeys == 1 ) continue ;
     
     			++nbDupl ;
    -			// LOG_INFO("%d: Name %s %d occurrences", nbDupl, itH->first.c_str(), nbKeys );
    +			if (bMOREINFO)
    +				LOG_INFO("%d: Name %s %d occurrences", 
    +					static_cast(nbDupl),
    +					itH->first.c_str(),
    +					static_cast(nbKeys) );
     
     			// There should not be many elements, two or three duplicates, maximum five apparently.
     			typedef std::set< std::string > DiffNamesT ;
    @@ -622,7 +634,8 @@ public:
     			// Check that all countries are different.
     			for( HashT::iterator itSubH = itH; itSubH != itNextH; ++itSubH ) {
     				RecordWmoStation & refWmo = itSubH->second->second ;
    -				// LOG_INFO("Trying %s", refWmo.station_name().c_str() );
    +				if (bMOREINFO)
    +					LOG_INFO("Trying %s", refWmo.station_name().c_str() );
     				// Appends the country.
     				refWmo.rename_station( refWmo.station_name() + "," + refWmo.country() );
     				std::pair< DiffNamesT::iterator, bool > tmpPair = differentNames.insert( refWmo.station_name() );
    @@ -637,7 +650,9 @@ public:
     		}
     
     		if(nbDupl) {
    -			LOG_INFO("Eliminated %d duplicates out of %d elements", (int)nbDupl, (int)m_catalog.size());
    +			if (bMOREINFO)
    +				LOG_INFO("Eliminated %d duplicates out of %d elements",
    +					(int)nbDupl, (int)m_catalog.size());
     		}
     		return true ;
     	}
    @@ -668,9 +683,11 @@ public:
     		typedef std::multimap< std::string, IteratorType > HashT ;
     		HashT allNames ;
     
    -		// LOG_INFO("Eliminating duplicates out of %d elements",m_catalog.size());
    +		if (bMOREINFO)
    +			LOG_INFO("Eliminating duplicates out of %d elements",
    +				static_cast(m_catalog.size()));
     
    -		/// First take the names 
    +		/// First take the names
     		for( IteratorType it = m_catalog.begin(), en = m_catalog.end(); it != en; ++it )
     		{
     			RecordBuoy & refWmo = it->second ;
    @@ -682,7 +699,8 @@ public:
     		/// Iterates on all names, take only the duplicates.
     		for( HashT::iterator itH = allNames.begin(), itNextH = itH, enH = allNames.end(); itH != enH; itH = itNextH )
     		{
    -			// LOG_INFO("Name=%s", itH->first.c_str() );
    +			if (bMOREINFO)
    +				LOG_INFO("Name=%s", itH->first.c_str() );
     			size_t nbKeys = 1 ;
     			for(;;) {
     				++itNextH;
    @@ -690,13 +708,20 @@ public:
     				if( itNextH->first != itH->first ) break ;
     				++nbKeys;
     			}
    -			// LOG_INFO("Name=%s nb=%d", itH->first.c_str(), nbKeys );
    +			if (bMOREINFO)
    +				LOG_INFO("Name=%s nb=%d",
    +					itH->first.c_str(),
    +					static_cast(nbKeys) );
     
     			// If no duplicates, then try next one.
     			if( nbKeys == 1 ) continue ;
     
     			++nbDupl ;
    -			// LOG_INFO("%d: Buoy name %s %d occurrences", nbDupl, itH->first.c_str(), nbKeys );
    +			if (bMOREINFO)
    +				LOG_INFO("%d: Buoy name %s %d occurrences",
    +					static_cast(nbDupl),
    +					itH->first.c_str(),
    +					static_cast(nbKeys) );
     
     			// There should not be many elements, two or three duplicates, maximum five apparently.
     			typedef std::set< std::string > DiffNamesT ;
    @@ -710,7 +735,8 @@ public:
     				else
     					refBuoy.rename_buoy( strformat( "%s-%s", refBuoy.buoy_name().c_str(), refBuoy.id().c_str() ) );
     				std::pair< DiffNamesT::iterator, bool > tmpPair = differentNames.insert( refBuoy.buoy_name() );
    -				// LOG_INFO("Buoy set to %s", refBuoy.buoy_name().c_str() );
    +				if (bMOREINFO)
    +					LOG_INFO("Buoy set to %s", refBuoy.buoy_name().c_str() );
     				if( tmpPair.second ) continue ;
     				LOG_ERROR("This should never happen because buoy id is unique");
     				return false ;
    @@ -718,7 +744,9 @@ public:
     		}
     
     		if(nbDupl) {
    -			LOG_INFO("Eliminated %d duplicates out of %d elements", (int)nbDupl, (int)m_catalog.size());
    +			if (bMOREINFO)
    +				LOG_INFO("Eliminated %d duplicates out of %d elements",
    +					(int)nbDupl, (int)m_catalog.size());
     		}
     		return true ;
     	}
    @@ -1098,7 +1126,7 @@ public:
     		strm << val ;
     		ItemAdd( key, strm.str().c_str(), unit );
     	}
    - 
    +
     	void Append( const char * key, const std::string & val, const char * unit = NULL ) const
     	{
     		ItemAdd( key, val.c_str(), unit );
    @@ -1108,14 +1136,14 @@ public:
     	{
     		ItemAdd( key, val, unit );
     	}
    - 
    +
     	void Append( const char * key, double val, const char * unit = NULL ) const
     	{
     		char buf[20];
     		sprintf( buf, "%.1lf", val );
     		ItemAdd( key, buf, unit );
     	}
    - 
    +
     	void Append( const char * key, int val, const char * unit = NULL ) const
     	{
     		char buf[12];
    @@ -1193,7 +1221,7 @@ public:
     	}
     
     	/// Returns the regular expression given its index.
    -	static const RegexT * Find(size_t idx ) { 
    +	static const RegexT * Find(size_t idx ) {
     		assert( idx < Nb() );
     		return storage()[ idx ];
     	}
    @@ -1230,7 +1258,7 @@ public:
     
     	// If two different tokens, with different regular expressions, match for the
     	// same word, the priority tells which one to take. Default value is one.
    -	static priority_t Priority( size_t idx ) { 
    +	static priority_t Priority( size_t idx ) {
     		assert( idx < Nb() );
     		return storage()[ idx ]->m_priority;
     	}
    @@ -1278,7 +1306,7 @@ public:
     
     /// Loops in the tokens held by the container, for a precise type.
     template< class TokenDerived >
    -const TokenDerived * TokenProxy::get_ptr(bool previous_chains) const  
    +const TokenDerived * TokenProxy::get_ptr(bool previous_chains) const
     {
     	for(
     		TokVec::Ptr curr_container = m_container ;
    @@ -1571,7 +1599,7 @@ public:
     /// http://weather.unisys.com/wxp/Appendices/Formats/SYNOP.html
     
     /// 000 Group - Identification and Location
    -/// 
    +///
     /// IIiii The WMO number of the station.
     HEADTK(IIiii) {
     	int          m_wmo_indicator ;
    @@ -1612,7 +1640,7 @@ public:
     	{
     		// std::cout << "wmo=" << str << "\n";
     
    -		/* Station index numbers consisting of one figure repeated five times, e.g. 55555, 77777, etc., 
    +		/* Station index numbers consisting of one figure repeated five times, e.g. 55555, 77777, etc.,
     		or ending with 0000 or 9999, or duplicating special code indicators, e.g. 10001, 77744, 19191,
     		89998, etc., are not assigned to meteorological stations. We might check if the code exists or not. */
     		if( 1 != sscanf( str, "%d", &m_wmo_indicator ) ) return false ;
    @@ -1895,7 +1923,7 @@ public:
     		}
     
     		/// Due to parsing error, we might take the next group header (333 or 555) as a ship name.
    -		bool resu = 
    +		bool resu =
     			( 1 == sscanf( str, "%9s", m_ship_buoy_identifier ) )
     		&&	( strcmp( m_ship_buoy_identifier, "333" ) )
     		&&	( strcmp( m_ship_buoy_identifier, "555" ) );
    @@ -1926,7 +1954,7 @@ public:
     	const char * ShipIdentifier(void) const { return m_ship_buoy_identifier; }
     };
     
    -/// ff -- wind speed in units determined by wind type indicator (see above) 
    +/// ff -- wind speed in units determined by wind type indicator (see above)
     static const choice< char > wind_speed_units[] = {
     	{ '0',_("m/s (Estimated)") },
     	{ '1',_("m/s (Anemometer)") },
    @@ -1977,7 +2005,7 @@ public:
     
     		// No need to display it twice because it will appear after the speed value.
     		if( tstDisp ) {
    -			Append( _("Wind type indicator"), 
    +			Append( _("Wind type indicator"),
     				choice_map( wind_speed_units, G_N_ELEMENTS( wind_speed_units ),
     					m_wind_type_indicator, _("Unknown speed unit type") ) );
     		}
    @@ -2021,7 +2049,7 @@ public:
     	friend class CLASSTK(QLLLL);
     };
     
    -/// LLLL -- Longitude of  observation to .1 degrees 
    +/// LLLL -- Longitude of  observation to .1 degrees
     HEADTK(QLLLL) {
     	char           m_quadrant ;
     	int            m_longit_10deg ;
    @@ -2246,13 +2274,13 @@ public:
     
     		const char * wind_speed_title = _("Wind speed");
     		if( ptr_YYGGi ) {
    -			Append( wind_speed_title, m_wind_speed, 
    +			Append( wind_speed_title, m_wind_speed,
     				choice_map( wind_speed_units, G_N_ELEMENTS( wind_speed_units ),
     					ptr_YYGGi->m_wind_type_indicator, _("Unknown speed unit type") ) );
     		} else {
    -			Append( wind_speed_title, m_wind_speed, _("No unit (YYGGi missing)") ); 
    +			Append( wind_speed_title, m_wind_speed, _("No unit (YYGGi missing)") );
     		}
    -	       
    +
     	}
     
     	bool CanComeFirst(void) const { return false ; }
    @@ -2272,7 +2300,7 @@ public:
     
     	void Print() const {
     		// fff -- wind speed if value greater than 100
    -		Append( _("Wind speed"), m_wind_speed ); 
    +		Append( _("Wind speed"), m_wind_speed );
     	}
     };
     
    @@ -2293,14 +2321,14 @@ static void AppCelsius( const TokenProxy * ptrTok, const char * title, char sign
     	if( title == NULL ) title = "No title";
     
     	switch( sign ) {
    -		case '1' : temperature_tenth = -temperature_tenth ; 
    -		case '0' : ptrTok->Append( title, temperature_tenth * 0.10, Unit_Celsius ); 
    +		case '1' : temperature_tenth = -temperature_tenth ;
    +		case '0' : ptrTok->Append( title, temperature_tenth * 0.10, Unit_Celsius );
     			   break;
     		case '9' : ptrTok->Append( _("Relative humidity"), (double)temperature_tenth * 0.10 , "%" );
     			   break;
    -		case '/' : ptrTok->Append( title, _("Undefined") ); 
    +		case '/' : ptrTok->Append( title, _("Undefined") );
     			   break;
    -		default  : ptrTok->Append( title, _("Unexpected case") ); 
    +		default  : ptrTok->Append( title, _("Unexpected case") );
     			   break;
     	}
     }
    @@ -2367,7 +2395,7 @@ static void thousands_omitted( const TokenProxy * ptrTok, const char * pressure,
     	double tmpPres ;
     	// Checks reasonable values for a pressure.
     	if( ( 1 != sscanf( buf, "%lf", &tmpPres ) )
    -		|| ( tmpPres > 12000 ) 
    +		|| ( tmpPres > 12000 )
     		|| ( tmpPres <  7000 ) ) {
     		ptrTok->Append( title, _("Inconsistent:") + std::string(pressure) );
     	} else {
    @@ -2392,7 +2420,7 @@ public:
     };
     
     /** 4PPPP -- Sea level pressure in 0.1 mb (thousandths digit omitted, last digit can be slash, then pressure in full mb)
    -Can be as well 4ahhh http://metaf2xml.sourceforge.net/parser.pm.html : 
    +Can be as well 4ahhh http://metaf2xml.sourceforge.net/parser.pm.html :
     a3 Isobaric surface (CT 0264), hhh Geopotential of isobaric surface
     */
     HEADTK(4PPPP) {
    @@ -2965,7 +2993,7 @@ public:
     	}
     };
     
    -/// 9GGgg -- Time of observation in hours and minutes 
    +/// 9GGgg -- Time of observation in hours and minutes
     HEADTK(9GGgg) {
     	int m_hours;
     	int m_minutes;
    @@ -2983,7 +3011,7 @@ public:
     };
     
     /// 222 Group - Sea Surface Observations
    -/// 
    +///
     ///       222Dv
     HEADTK(222Dv) {
     	char m_ship_direction;
    @@ -3088,9 +3116,9 @@ public:
     			Append( _("Sea surface temperature"), _("Unspecified") );
     
     		if( m_temperature_type == NULL )
    -			Append( _("Temperature type"), _("Unspecified") ); 
    +			Append( _("Temperature type"), _("Unspecified") );
     		else
    -			Append( _("Temperature type"), m_temperature_type ); 
    +			Append( _("Temperature type"), m_temperature_type );
     	}
     };
     
    @@ -3194,7 +3222,7 @@ public:
     		m_swell_waves_period = -1;
     		m_swell_waves_height = -1;
     		if( 0 == strcmp( str, "4////") ) return true;
    -		return ( 2 == sscanf( str, "4%2d%2d", &m_swell_waves_period, &m_swell_waves_height ) ) 
    +		return ( 2 == sscanf( str, "4%2d%2d", &m_swell_waves_period, &m_swell_waves_height ) )
     		||     ( 1 == sscanf( str, "4%2d//", &m_swell_waves_period ) );
     	}
     
    @@ -3300,7 +3328,7 @@ public:
     	}
     };
     
    -/// 8aTTT -- Wet bulb temperature 
    +/// 8aTTT -- Wet bulb temperature
     HEADTK(8aTTT) {
     	char         m_wet_bulb_sign_type ;
     	char         m_temperature_sign ;
    @@ -3362,7 +3390,7 @@ public:
     	}
     };
     
    -/// Separator for ice detection. 
    +/// Separator for ice detection.
     HEADTK(ICE) {
     public:
     	// TODO: It is possible to have free text after the string ICE.
    @@ -3394,7 +3422,7 @@ public:
     
     	bool Parse( const char * str )
     	{
    -		return ( 5 == sscanf( str, "%c%c%c%c%c", 
    +		return ( 5 == sscanf( str, "%c%c%c%c%c",
     			&m_sea_ice_arrangement,
     			&m_sea_ice_development_stage,
     			&m_ice_of_land_origin,
    @@ -3419,7 +3447,7 @@ public:
     			_("Concentration or arrangement of Sea Ice") );
     
     		/// Si = Sea Ice Stage of Development
    -		static const char * sea_ice_development_stages[] = { 
    +		static const char * sea_ice_development_stages[] = {
     			_("New ice only (frail ice, grease ice, slush ice, shuga)"),
     			_("Nilas or ice rind, less than 10 cm thick"),
     			_("Young ice (grey ice, grey-white ice), 10-30 cm thick"),
    @@ -3669,19 +3697,19 @@ public:
     
     		/// sss -- snow depth in cm: Code table 3889 sss : Total depth of snow
     		switch( m_snow_depth ) {
    -			case 0 : 
    +			case 0 :
     				Append( _("Snow depth"), _("Not used") );
     				break;
     			default :
     				Append( _("Snow depth"), m_snow_depth, Unit_centimeters );
     				break;
    -			case 997 : 
    +			case 997 :
     				Append( _("Snow depth"), _("Less than 0.5 cm") );
     				break;
    -			case 998 : 
    +			case 998 :
     				Append( _("Snow depth"), _("Snow cover, not continuous") );
     				break;
    -			case 999 : 
    +			case 999 :
     				Append( _("Snow depth"), _("Measurement impossible or inaccurate") );
     				break;
     		}
    @@ -3880,7 +3908,7 @@ public:
     		m_cloud_base_height = 0 ;
     		return ( 3 == sscanf( str, "8%c%c%2d", &m_cloud_cover, &m_cloud_genus, &m_cloud_base_height ) )
     		||     ( 2 == sscanf( str, "8%c%c//", &m_cloud_cover, &m_cloud_genus ) )
    -		|| ( 0 == strncmp( str, "80///", 5 ) );	
    +		|| ( 0 == strncmp( str, "80///", 5 ) );
     	}
     
     	void Print() const {
    @@ -3896,9 +3924,9 @@ public:
     		switch( m_cloud_base_height ) {
     			case  0        : Append( title, _("Less than 30 meters") ); break;
     			case  1 ... 50 : Append( title, m_cloud_base_height * 30, Unit_meters ); break;
    -			case 51 ... 56 : Append( title, 1500 + ( m_cloud_base_height - 50 ) *   50, Unit_meters ); break; 
    -			case 57 ... 80 : Append( title, 1800 + ( m_cloud_base_height - 56 ) *  300, Unit_meters ); break; 
    -			case 81 ... 88 : Append( title, 9000 + ( m_cloud_base_height - 80 ) * 1500, Unit_meters ); break; 
    +			case 51 ... 56 : Append( title, 1500 + ( m_cloud_base_height - 50 ) *   50, Unit_meters ); break;
    +			case 57 ... 80 : Append( title, 1800 + ( m_cloud_base_height - 56 ) *  300, Unit_meters ); break;
    +			case 81 ... 88 : Append( title, 9000 + ( m_cloud_base_height - 80 ) * 1500, Unit_meters ); break;
     			case 89        : Append( title, _("Greater than 21000 m") ); break;
     			case 90 ... 99 : disp_arr(cloud_bases,G_N_ELEMENTS(cloud_bases),m_cloud_base_height,90,title );
     					break;
    @@ -3907,7 +3935,7 @@ public:
     	}
     };
     
    -/// 9SSss -- Supplementary information 
    +/// 9SSss -- Supplementary information
     /// http://www.met.fu-berlin.de/~stefan/fm12.html#32
     /// 9SPSPspsp -- Besondere Wettererscheinungen und zusätzliche Informationen (Gruppe kann mehrmals verschlüsselt werden)
     HEADTK(9SSss) {
    @@ -4454,7 +4482,7 @@ public:
         * 9snTgTgTgsTg -- Minimumtemperatur des Vortags (00 - 24 UTC) 5 cm über dem Erdboden bzw. der Schneedecke (wird um 06 UTC gemeldet)
           sn -- Vorzeichen der Temperatur (0 = positiv, 1 = negativ)
           Tg Tg Tg -- Erdbodenminimumtemperatur in 1/10 Grad Celsius
    -      sTg -- Bedeckung des Temperaturmeßfühlers 5 cm über dem Erdboden mit Schnee oder Eis am Vortag (0 = nein, 1 = ja, / = Angabe nicht möglich) 
    +      sTg -- Bedeckung des Temperaturmeßfühlers 5 cm über dem Erdboden mit Schnee oder Eis am Vortag (0 = nein, 1 = ja, / = Angabe nicht möglich)
     */
     
     /// Abschnitt 6 - Automatisch erzeugte Daten
    @@ -4923,43 +4951,43 @@ static const void init_patterns(void)
     
     	// http://metaf2xml.sourceforge.net/parser.pm.html
     	// AT: 1snTxTxTx 6RRR/
    -	//    1snTxTxTx : maximum temperature on the previous day from 06:00 to 18:00 UTC 
    -	//    6RRR/ : amount of precipitation on the previous day from 06:00 to 18:00 UTC 
    +	//    1snTxTxTx : maximum temperature on the previous day from 06:00 to 18:00 UTC
    +	//    6RRR/ : amount of precipitation on the previous day from 06:00 to 18:00 UTC
      	// BE: 1snTxTxTx 2snTnTnTn
    -	//    1snTxTxTx : maximum temperature on the next day from 00:00 to 24:00 UTC 
    -	//    2snTnTnTn : minimum temperature on the next day from 00:00 to 24:00 UTC 
    +	//    1snTxTxTx : maximum temperature on the next day from 00:00 to 24:00 UTC
    +	//    2snTnTnTn : minimum temperature on the next day from 00:00 to 24:00 UTC
      	// CA: 1ssss 2swswswsw 3dmdmfmfm 4fhftftfi
    -	//    1ssss : amount of snowfall, in tenths of a centimeter, for the 24-hour period ending at 06:00 UTC 
    -	//    2swswswsw : amount of water equivalent, in tenths of a millimeter, for the 24-hour snowfall ending at 06:00 UTC 
    -	//    3dmdmfmfm : maximum (mean or gust) wind speed, in knots, for the 24-hour period ending at 06:00 UTC and its direction 
    +	//    1ssss : amount of snowfall, in tenths of a centimeter, for the 24-hour period ending at 06:00 UTC
    +	//    2swswswsw : amount of water equivalent, in tenths of a millimeter, for the 24-hour snowfall ending at 06:00 UTC
    +	//    3dmdmfmfm : maximum (mean or gust) wind speed, in knots, for the 24-hour period ending at 06:00 UTC and its direction
     	//    4fhftftfi : together with the previous group, the hundreds digit of the maximum wind speed (in knots),
     	//                the time of occurrence of the maximum wind speed, and the speed range
    -	//                of the maximum two-minute mean wind speed, for the 24-hour period ending at 06:00 UTC and its direction 
    +	//                of the maximum two-minute mean wind speed, for the 24-hour period ending at 06:00 UTC and its direction
      	// US land: RECORD* 0ittDtDtD 1snTT snTxTxsnTnTn RECORD* 2R24R24R24R24 44snTwTw 9YYGG
    -	//    RECORD : indicator for temperature record(s) 
    -	//    0ittDtDtD : tide data 
    +	//    RECORD : indicator for temperature record(s)
    +	//    0ittDtDtD : tide data
     	//    1snTT snTxTxsnTnTn RECORD* 2R24R24R24R24 : city data: temperature, maximum and minimum temperature,
    -	//                indicator for temperature record(s), precipitation last 24 hours 
    -	//    44snTwTw : water temperature 
    -	//    9YYGG : additional day and hour of observation (repeated from Section 0) 
    +	//                indicator for temperature record(s), precipitation last 24 hours
    +	//    44snTwTw : water temperature
    +	//    9YYGG : additional day and hour of observation (repeated from Section 0)
      	// US sea: 11fff 22fff 3GGgg 4ddfmfm 6GGgg dddfff dddfff dddfff dddfff dddfff dddfff 8ddfmfm 9GGgg
    -	//    11fff 22fff : equivalent wind speeds at 10 and 20 meters 
    -	//    3GGgg 4ddfmfm : maximum wind speed since the last observation and the time when it occurred 
    -	//    6GGgg : end time of the latest 10-minute continuous wind measurements 
    -	//    6 x dddfff : 6 10-minute continuous wind measurements 
    -	//    8ddfmfm 9GGgg : highest 1-minute wind speed and the time when it occurred 
    +	//    11fff 22fff : equivalent wind speeds at 10 and 20 meters
    +	//    3GGgg 4ddfmfm : maximum wind speed since the last observation and the time when it occurred
    +	//    6GGgg : end time of the latest 10-minute continuous wind measurements
    +	//    6 x dddfff : 6 10-minute continuous wind measurements
    +	//    8ddfmfm 9GGgg : highest 1-minute wind speed and the time when it occurred
      	// CZ: 1dsdsfsfs 2fsmfsmfsxfsx 3UU// 5snT5T5T5 6snT10T10T10 7snT20T20T20 8snT50T50T50 9snT100T100T100
    -	//    1dsdsfsfs : wind direction and speed from tower measurement 
    -	//    2fsmfsmfsxfsx : maximum wind gust speed over 10 minute period and the period W1W2 
    -	//    3UU// : relative humidity 
    -	//    5snT5T5T5 6snT10T10T10 7snT20T20T20 8snT50T50T50 9snT100T100T100 : soil temperature at the depths of 5, 10, 20, 50, and 100 cm 
    +	//    1dsdsfsfs : wind direction and speed from tower measurement
    +	//    2fsmfsmfsxfsx : maximum wind gust speed over 10 minute period and the period W1W2
    +	//    3UU// : relative humidity
    +	//    5snT5T5T5 6snT10T10T10 7snT20T20T20 8snT50T50T50 9snT100T100T100 : soil temperature at the depths of 5, 10, 20, 50, and 100 cm
      	// RU: 1EsnT'gT'g 2snTnTnTn 3EsnTgTg 4E'sss 52snT2T2 6RRRtR 7R24R24R24/ 88R24R24R24
    -	//    1EsnT'gT'g : state of the ground without snow or measurable ice cover, temperature of the ground surface 
    -	//    2snTnTnTn : minimum temperature last night 
    -	//    3EsnTgTg : state of the ground without snow or measurable ice cover, minimum temperature of the ground surface last night 
    -	//    4E'sss : state of the ground if covered with snow or ice, snow depth 
    -	//    6RRRtR : amount of precipitation for given period 
    -	//    7R24R24R24/ : amount of daily precipitation 
    +	//    1EsnT'gT'g : state of the ground without snow or measurable ice cover, temperature of the ground surface
    +	//    2snTnTnTn : minimum temperature last night
    +	//    3EsnTgTg : state of the ground without snow or measurable ice cover, minimum temperature of the ground surface last night
    +	//    4E'sss : state of the ground if covered with snow or ice, snow depth
    +	//    6RRRtR : amount of precipitation for given period
    +	//    7R24R24R24/ : amount of daily precipitation
     	//    88R24R24R24 : amount of daily precipitation if 30 mm or more
     
     
    @@ -5070,7 +5098,7 @@ class synop_impl
     						std::cout << "DEBUG:" << __FUNCTION__
     							<< " m_idxGroup=" <<  m_idxGroup << " m_idxTok=" << m_idxTok
     							<< " reg=" << reg.Name() << " str=" << str
    -							<< " m_nxtTok=" << m_nxtTok 
    +							<< " m_nxtTok=" << m_nxtTok
     							<< " priority=" << m_sum_prios << "\n" ;
     						*/
     						return tp ;
    @@ -5093,8 +5121,8 @@ class synop_impl
     						std::cout << "DEBUG:" << __FUNCTION__
     							<< " REPET m_idxGroup=" <<  m_idxGroup << " m_idxTok=" << m_idxTok
     							<< " reg=" << reg.Name() << " str=" << str
    -							<< " m_nxtTok=" << m_nxtTok 
    -							<< " m_idxTok=" << m_idxTok 
    +							<< " m_nxtTok=" << m_nxtTok
    +							<< " m_idxTok=" << m_idxTok
     							<< " maxTks=" << ptrSynopGroup->m_nb_toks
     							<< " priority=" << m_sum_prios << "\n" ;
     						*/
    @@ -5200,7 +5228,7 @@ class synop_impl
     				LOG_DEBUG("No publish0 empty message");
     				return;
     			}
    -	
    +
     			// Quick check if the message is very short. Beware, it it the total
     			// number of tokens, not the number of sections.
     			if(m_nbTokens <= 2 ) {
    @@ -5211,7 +5239,7 @@ class synop_impl
     
     			// We eliminate this kind of message which is not SYNOP although the beginning is similar.
     			// Other simple combinations might be eliminated but they are rarer.
    -			// ZCZC 603     
    +			// ZCZC 603
     			// WWXX60 EDZW 201700
     			const_iterator it1 = it0;
     			++it1 ;
    @@ -5220,7 +5248,8 @@ class synop_impl
     			&&  ( it1            != end()            )
     			&&  ( it1->section() == SECTION_IDENTLOC ) ) {
     				if( m_nbTokens <= 3 ) {
    -					LOG_INFO("No publish3 %s", TstToStr().c_str() );
    +					if (bMOREINFO)
    +						LOG_INFO("No publish3 %s", TstToStr().c_str() );
     					return ;
     				}
     				// TODO: Store these for next run if their are missing.
    @@ -5230,7 +5259,8 @@ class synop_impl
     				// For example, receiving only the following line makes no sense:
     				// Climatological data=6RRRt#69907+8NChh#81822+9SSss#91113+9SSss#96480;+;
     				if( it0->section() != SECTION_LAND_OBS ) {
    -					LOG_INFO("No publish2 %s", TstToStr().c_str() );
    +					if (bMOREINFO)
    +						LOG_INFO("No publish2 %s", TstToStr().c_str() );
     					return ;
     				}
     				// TODO: We should use the header SECTION_IDENTLOC of the previous message:
    @@ -5307,7 +5337,8 @@ class synop_impl
     									<< " IIiii:" << newCoo
     									<< " Against:" << tmpCoo
     									<< " Dist:" << dist ;
    -								LOG_INFO("%s", strm.str().c_str() );
    +								if (bMOREINFO)
    +									LOG_INFO("%s", strm.str().c_str() );
     							}
     						} else {
     							foundCoo = true ;
    @@ -5344,7 +5375,8 @@ class synop_impl
     									<< " IIiii:" << newCoo
     									<< " Against:" << tmpCoo
     									<< " Dist:" << dist ;
    -								LOG_INFO("%s", strm.str().c_str() );
    +								if (bMOREINFO)
    +									LOG_INFO("%s", strm.str().c_str() );
     							}
     						} else {
     							foundCoo = true ;
    @@ -5359,7 +5391,8 @@ class synop_impl
     							ptrJComm_Tok->SetJCommFields( kmlNam, iconNam );
     							if( stationCountry.empty() ) stationCountry = ptrJComm_Tok->country();
     						} else {
    -							LOG_INFO("Cannot find WMO station:%s", wmoIndicStr.c_str() );
    +							if (bMOREINFO)
    +								LOG_INFO("Cannot find WMO station:%s", wmoIndicStr.c_str() );
     							kmlNam = "WMO:" + wmoIndicStr ;
     						}
     					}
    @@ -5711,7 +5744,7 @@ private:
     		const size_t buf_sz = m_buf.size();
     
     		// The same list can appear in several chains, this is intended.
    -		for( int i = 0, nbSynGrp = arrSynopGroups.size(); i < nbSynGrp; ++i )	
    +		for( int i = 0, nbSynGrp = arrSynopGroups.size(); i < nbSynGrp; ++i )
     		{
     			for( size_t j = 0, nbToks = arrSynopGroups[i].m_nb_toks; j < nbToks; ++j )
     			{
    @@ -5800,7 +5833,7 @@ private:
     
     		/// What happens if it matches the beginning if a chain
     		// NOTE: We suppose that the beginning is never multiple ("Many").
    -		for( int idxGrp = 0, nbSynGrp = arrSynopGroups.size(); idxGrp < nbSynGrp; ++idxGrp )	
    +		for( int idxGrp = 0, nbSynGrp = arrSynopGroups.size(); idxGrp < nbSynGrp; ++idxGrp )
     		{
     			const synop_group * ptrSynopGroup = &arrSynopGroups[idxGrp];
     			assert( ptrSynopGroup->m_nb_toks > 0 );
    @@ -5839,7 +5872,7 @@ private:
     
     		if( nbInserts != 0 ) {
     			/// Removes the chains which cannot possibly match the current suite of tokens.
    -			for( ChainsNoInsrtsT::iterator it = chainsNoInsrts.begin(), en = chainsNoInsrts.end(); it != en; ++it ) 
    +			for( ChainsNoInsrtsT::iterator it = chainsNoInsrts.begin(), en = chainsNoInsrts.end(); it != en; ++it )
     			{
     				m_chains.erase( *it );
     			}
    @@ -5954,7 +5987,7 @@ public:
     					{
     						// -1, no display of '=', whose length is one.
     						decode_then_flush(-1);
    -					} else if( nbInserts == 0 ) 
    +					} else if( nbInserts == 0 )
     					{
     						if( noChains ) {
     							/// There was no chains before.
    @@ -6022,7 +6055,7 @@ void synop::regex_usage(void) {
     		if( ptrSynopGroup-> m_usage_counter > 0 ) continue ;
     
     		std::cout << "DEBUG:" << "Unused:"
    -			<< " idxGrp=" <<  idxGrp 
    +			<< " idxGrp=" <<  idxGrp
     			<< ' ' << *ptrSynopGroup
     			<< '\n' ;
     	}
    diff --git a/src/thor/thor-pic.cxx b/src/thor/thor-pic.cxx
    new file mode 100644
    index 00000000..b32e70d1
    --- /dev/null
    +++ b/src/thor/thor-pic.cxx
    @@ -0,0 +1,971 @@
    +// ----------------------------------------------------------------------------
    +// thorpic.cxx  --  thor image support functions
    +//
    +// Copyright (C) 2015
    +//		Dave Freese, W1HKJ
    +//
    +// This file is part of fldigi.  Adapted from code contained in gthor source code
    +// distribution.
    +//
    +// Fldigi 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.
    +//
    +// Fldigi 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 fldigi.  If not, see .
    +// ----------------------------------------------------------------------------
    +
    +#include 
    +#include 
    +
    +#include "gettext.h"
    +#include "fileselect.h"
    +#include "qrunner.h"
    +
    +void thor_createTxViewer();
    +
    +Fl_Double_Window	*thorpicRxWin = (Fl_Double_Window *)0;
    +picture				*thorpicRx = (picture *)0;
    +Fl_Button			*btnthorRxReset = (Fl_Button *)0;
    +Fl_Button			*btnthorRxSave = (Fl_Button *)0;
    +Fl_Button			*btnthorRxClose = (Fl_Button *)0;
    +Fl_Counter			*thorcnt_phase = (Fl_Counter *)0;
    +Fl_Counter			*thorcnt_slant = (Fl_Counter *)0;
    +
    +Fl_Double_Window	*thorpicTxWin = (Fl_Double_Window *)0;
    +picture				*thorpicTx = (picture *)0;
    +Fl_Button			*btnthorpicTransmit = (Fl_Button *)0;
    +Fl_Button			*btnthorpicTxSendAbort = (Fl_Button *)0;
    +Fl_Button			*btnthorpicTxLoad = (Fl_Button *)0;
    +Fl_Button			*btnthorpicTxClose = (Fl_Button *)0;
    +Fl_Choice			*selthorpicSize = (Fl_Choice *)0;
    +
    +void thor_showTxViewer(char c);
    +
    +Fl_Shared_Image	*thorTxImg = (Fl_Shared_Image *)0;
    +unsigned char *thorxmtimg = (unsigned char *)0;
    +unsigned char *thorxmtpicbuff = (unsigned char *)0;
    +
    +#define RAWSIZE 640*(480 + 8)*3*thor::IMAGEspp
    +
    +#define RAWSTART 640*4*3*thor::IMAGEspp
    +
    +unsigned char *thor_rawvideo = 0;//[RAWSIZE + 1];
    +
    +int thor_numpixels;
    +int thor_pixelptr;
    +int thor_rawcol;
    +int thor_rawrow;
    +int thor_rawrgb;
    +char thor_image_type = 'S';
    +
    +char thor_txclr_tooltip[24];
    +char thor_txgry_tooltip[24];
    +
    +static int translate = 0;
    +static bool enabled = false;
    +
    +std::string thor::imageheader;
    +std::string thor::avatarheader;
    +int thor::IMAGEspp = THOR_IMAGESPP;
    +
    +void thor_correct_video()
    +{
    +	int W = thorpicRx->w();
    +	int H = thorpicRx->h();
    +	int slant = thorcnt_slant->value();
    +	int vidsize = W * H;
    +	int index, rowptr, colptr;
    +	float ratio = (((float)vidsize - (float)slant)/(float)vidsize);
    +	unsigned char vid[W * H * 3];
    +	for (int row = 0; row < H; row++) {
    +		rowptr = W * 3 * row * thor::IMAGEspp;
    +		for (int col = 0; col < W; col++) {
    +			colptr = thor::IMAGEspp*col;
    +			for (int rgb = 0; rgb < 3; rgb++) {
    +				index = ratio*(rowptr + colptr + thor::IMAGEspp*W*rgb);
    +				index += RAWSTART - thor::IMAGEspp*thor_pixelptr;
    +				if (index < 2) index = 2;
    +				if (index > RAWSIZE - 2) index = RAWSIZE - 2;
    +				vid[rgb + 3 * (col + row * W)] = thor_rawvideo[index];
    +			}
    +		}
    +	}
    +	thorpicRx->video(vid, W*H*3);
    +}
    +
    +void thor_updateRxPic(unsigned char data, int pos)
    +{
    +	if (!thorpicRxWin->shown()) thorpicRx->show();
    +
    +	thorpicRx->pixel(data, pos);
    +
    +	int W = thorpicRx->w();
    +	if (thor_image_type == 'F' || thor_image_type == 'p' || thor_image_type == 'm') {
    +		int n = RAWSTART + thor::IMAGEspp*(thor_rawcol + W * (thor_rawrgb + 3 * thor_rawrow));
    +		if (n < RAWSIZE)
    +			for (int i = 0; i < thor::IMAGEspp; i++) thor_rawvideo[n + i] = data;
    +		thor_rawrgb++;
    +		if (thor_rawrgb == 3) {
    +			thor_rawrgb = 0;
    +			thor_rawcol++;
    +			if (thor_rawcol == W) {
    +				thor_rawcol = 0;
    +				thor_rawrow++;
    +			}
    +		}
    +	} else
    +		for (int i = 0; i < thor::IMAGEspp; i++)
    +			thor_rawvideo[RAWSTART + thor::IMAGEspp*thor_numpixels + i] = data;
    +	thor_numpixels++;
    +	if (thor_numpixels >= (RAWSIZE - RAWSTART - thor::IMAGEspp)) 
    +		thor_numpixels = RAWSIZE - RAWSTART - thor::IMAGEspp;
    +}
    +
    +void cb_btnthorRxReset(Fl_Widget *, void *)
    +{
    +//	progStatus.thor_rx_abort = true;
    +}
    +
    +void cb_btnthorRxSave(Fl_Widget *, void *)
    +{
    +	thorpicRx->save_png(PicsDir.c_str());
    +//	FILE *raw = fopen("image.raw", "wb");
    +//	std::cout << "wrote " << fwrite(thor_rawvideo, 1, RAWSIZE, raw) << "\n";
    +//	fclose(raw);
    +}
    +
    +void cb_btnthorRxClose(Fl_Widget *, void *)
    +{
    +	thorpicRxWin->hide();
    +//	progStatus.thor_rx_abort = true;
    +//	thorpicRxWin->hide();
    +//	FILE *raw = fopen("image.raw", "rb");
    +//	std::cout << "read " << fread(thor_rawvideo, 1, RAWSIZE, raw) << "\n";
    +//	fclose(raw);
    +//	thor_correct_video();
    +}
    +
    +void cb_thor_cnt_phase(Fl_Widget *, void *data)
    +{
    +	thor_pixelptr = thorcnt_phase->value();
    +	if (thor_pixelptr >= RAWSTART/thor::IMAGEspp) {
    +		thor_pixelptr = RAWSTART/thor::IMAGEspp - 1;
    +		thorcnt_phase->value(thor_pixelptr);
    +	}
    +	if (thor_pixelptr < -RAWSTART/thor::IMAGEspp) {
    +		thor_pixelptr = -RAWSTART/thor::IMAGEspp;
    +		thorcnt_phase->value(thor_pixelptr);
    +	}
    +	thor_correct_video();
    +}
    +
    +void cb_thor_cnt_slant(Fl_Widget *, void *)
    +{
    +	thor_correct_video();
    +}
    +
    +void thor_disableshift()
    +{
    +	if (!thorpicRxWin) return;
    +	thorcnt_phase->deactivate();
    +	thorcnt_slant->deactivate();
    +	btnthorRxSave->deactivate();
    +	thorpicRxWin->redraw();
    +}
    +
    +void thor_enableshift()
    +{
    +	if (!thorpicRxWin) return;
    +	thorcnt_phase->activate();
    +	thorcnt_slant->activate();
    +	btnthorRxSave->activate();
    +	thorpicRxWin->redraw();
    +}
    +
    +void thor_createRxViewer()
    +{
    +
    +	thorpicRxWin = new Fl_Double_Window(324, 274, _("thor Rx Image"));
    +	thorpicRxWin->xclass(PACKAGE_NAME);
    +	thorpicRxWin->begin();
    +
    +	thorpicRx = new picture(2, 2, 320, 240);
    +	thorpicRx->noslant();
    +
    +	Fl_Group *buttons = new Fl_Group(0, thorpicRxWin->h() - 26, thorpicRxWin->w(), 26, "");
    +	buttons->box(FL_FLAT_BOX);
    +
    +	btnthorRxReset = new Fl_Button(2, thorpicRxWin->h() - 26, 40, 24, "Reset");
    +	btnthorRxReset->callback(cb_btnthorRxReset, 0);
    +
    +	thorcnt_phase = new Fl_Counter(46, thorpicRxWin->h() - 24, 80, 20, "");
    +	thorcnt_phase->step(1);
    +	thorcnt_phase->lstep(10);
    +	thorcnt_phase->minimum(-RAWSTART + 1);
    +	thorcnt_phase->maximum(RAWSTART - 1);
    +	thorcnt_phase->value(0);
    +	thorcnt_phase->callback(cb_thor_cnt_phase, 0);
    +	thorcnt_phase->tooltip(_("Phase correction"));
    +
    +	thorcnt_slant = new Fl_Counter(140, thorpicRxWin->h() - 24, 80, 20, "");
    +	thorcnt_slant->step(1);
    +	thorcnt_slant->lstep(10);
    +	thorcnt_slant->minimum(-200);
    +	thorcnt_slant->maximum(200);
    +	thorcnt_slant->value(0);
    +	thorcnt_slant->callback(cb_thor_cnt_slant, 0);
    +	thorcnt_slant->tooltip(_("Slant correction"));
    +
    +	btnthorRxSave = new Fl_Button(226, thorpicRxWin->h() - 26, 45, 24, _("Save"));
    +	btnthorRxSave->callback(cb_btnthorRxSave, 0);
    +
    +	btnthorRxClose = new Fl_Button(273, thorpicRxWin->h() - 26, 45, 24, _("Close"));
    +	btnthorRxClose->callback(cb_btnthorRxClose, 0);
    +	buttons->end();
    +
    +	thorpicRxWin->end();
    +	thorpicRxWin->resizable(thorpicRx);
    +
    +	thor_numpixels = 0;
    +}
    +
    +void thor_showRxViewer(char itype)
    +{
    +	int W = 320;
    +	int H = 240;
    +	switch (itype) {
    +		case 'L' : W = 320; H = 240; break;
    +		case 'S' : W = 160; H = 120; break;
    +		case 'F' : W = 640; H = 480; break;
    +		case 'V' : W = 640; H = 480; break;
    +		case 'P' : W = 240; H = 300; break;
    +		case 'p' : W = 240; H = 300; break;
    +		case 'M' : W = 120; H = 150; break;
    +		case 'm' : W = 120; H = 150; break;
    +		case 'T' : W = 59; H = 74; break;
    +	}
    +
    +	if (!thorpicRxWin) thor_createRxViewer();
    +	int winW, winH;
    +	int thorpicX, thorpicY;
    +	winW = W < 320 ? 324 : W + 4;
    +	winH = H < 240 ? 274 : H + 34;
    +	thorpicX = (winW - W) / 2;
    +	thorpicY = (winH - 30 - H) / 2;
    +	thorpicRxWin->size(winW, winH);
    +	thorpicRx->resize(thorpicX, thorpicY, W, H);
    +	thorpicRxWin->init_sizes();
    +
    +	thorpicRx->clear();
    +	thorpicRxWin->show();
    +	thor_disableshift();
    +
    +	if (thor_rawvideo == 0) thor_rawvideo = new unsigned char [RAWSIZE + 1];
    +	memset(thor_rawvideo, 0, RAWSIZE);
    +	thor_numpixels = 0;
    +	thor_pixelptr = 0;
    +	thor_rawrow = thor_rawrgb = thor_rawcol = 0;
    +	thor_image_type = itype;
    +}
    +
    +void thor_clear_rximage()
    +{
    +	thorpicRx->clear();
    +	thor_disableshift();
    +	translate = 0;
    +	enabled = false;
    +	thor_numpixels = 0;
    +	thor_pixelptr = 0;
    +	thorcnt_phase->value(0);
    +	thorcnt_slant->value(0);
    +	thor_rawrow = thor_rawrgb = thor_rawcol = 0;
    +}
    +
    +//------------------------------------------------------------------------------
    +// image transmit functions
    +//------------------------------------------------------------------------------
    +
    +void thor_load_scaled_image(std::string fname)
    +{
    +
    +	if (!thorpicTxWin) thor_createTxViewer();
    +
    +	int D = 0;
    +	unsigned char *img_data;
    +	int W = 160;
    +	int H = 120;
    +	int winW = 644;
    +	int winH = 512;
    +	int thorpicX = 0;
    +	int thorpicY = 0;
    +	string picmode = "pic% \n";
    +
    +	if (thorTxImg) {
    +		thorTxImg->release();
    +		thorTxImg = 0;
    +	}
    +
    +	thorTxImg = Fl_Shared_Image::get(fname.c_str());
    +	if (!thorTxImg)
    +		return;
    +
    +	int iW = thorTxImg->w();
    +	int iH = thorTxImg->h();
    +	int aspect = 0;
    +
    +	if (iW > iH ) {
    +		if (iW >= 640) {
    +			W = 640; H = 480;
    +			winW = 644; winH = 484;
    +			aspect = 4;
    +			picmode[4] = 'V';
    +		}
    +		else if (iW >= 320) {
    +			W = 320; H = 240;
    +			winW = 324; winH = 244;
    +			aspect = 2;
    +			picmode[4] = 'L';
    +		}
    +		else {
    +			W = 160; H = 120;
    +			winW = 164; winH = 124;
    +			aspect = 1;
    +			picmode[4] = 'S';
    +		}
    +	} else {
    +		if (iH >= 300) {
    +			W = 240; H = 300;
    +			winW = 244; winH = 304;
    +			aspect = 5;
    +			picmode[4] = 'P';
    +		}
    +		else if (iH >= 150) {
    +			W = 120; H = 150;
    +			winW = 124; winH = 154;
    +			aspect = 7;
    +			picmode[4] = 'M';
    +		}
    +		else {
    +			W = 59; H = 74;
    +			winW = 67; winH = 82;
    +			aspect = 0;
    +			picmode[4] = 'T';
    +		}
    +	}
    +
    +	{
    +		Fl_Image *temp;
    +		selthorpicSize->value(aspect);
    +		temp = thorTxImg->copy(W, H);
    +		thorTxImg->release();
    +		thorTxImg = (Fl_Shared_Image *)temp;
    +	}
    +
    +	if (thorTxImg->count() > 1) {
    +		thorTxImg->release();
    +		thorTxImg = 0;
    +		return;
    +	}
    +
    +	thorpicTx->hide();
    +	thorpicTx->clear();
    +
    +	img_data = (unsigned char *)thorTxImg->data()[0];
    +
    +	D = thorTxImg->d();
    +
    +	if (thorxmtimg) delete [] thorxmtimg;
    +
    +	thorxmtimg = new unsigned char [W * H * 3];
    +	if (D == 3)
    +		memcpy(thorxmtimg, img_data, W*H*3);
    +	else if (D == 4) {
    +		int i, j, k;
    +		for (i = 0; i < W*H; i++) {
    +			j = i*3; k = i*4;
    +			thorxmtimg[j] = img_data[k];
    +			thorxmtimg[j+1] = img_data[k+1];
    +			thorxmtimg[j+2] = img_data[k+2];
    +		}
    +	} else if (D == 1) {
    +		int i, j;
    +		for (i = 0; i < W*H; i++) {
    +			j = i * 3;
    +			thorxmtimg[j] = thorxmtimg[j+1] = thorxmtimg[j+2] = img_data[i];
    +		}
    +	} else
    +		return;
    +
    +	char* label = strdup(fname.c_str());
    +	thorpicTxWin->copy_label(basename(label));
    +	free(label);
    +
    +// load the thorpicture widget with the rgb image
    +
    +	thorpicTxWin->size(winW, winH);
    +	thorpicX = (winW - W) / 2;
    +	thorpicY = (winH - H) / 2;
    +	thorpicTx->resize(thorpicX, thorpicY, W, H);
    +
    +	selthorpicSize->hide();
    +	btnthorpicTransmit->hide();
    +	btnthorpicTxLoad->hide();
    +	btnthorpicTxClose->hide();
    +	btnthorpicTxSendAbort->hide();
    +
    +	thorpicTx->video(thorxmtimg, W * H * 3);
    +	thorpicTx->show();
    +
    +	thorpicTxWin->show();
    +
    +	active_modem->thor_send_image(picmode);
    +
    +	return;
    +}
    +
    +
    +int thor_load_image(const char *n) {
    +
    +	int D = 0;
    +	unsigned char *img_data;
    +	int W = 640;
    +	int H = 480;
    +
    +	switch (selthorpicSize->value()) {
    +		case 0 : W = 59; H = 74; break;
    +		case 1 : W = 160; H = 120; break;
    +		case 2 : W = 320; H = 240; break;
    +		case 3 : W = 640; H = 480; break;
    +		case 4 : W = 640; H = 480; break;
    +		case 5 : W = 240; H = 300; break;
    +		case 6 : W = 240; H = 300; break;
    +		case 7 : W = 120; H = 150; break;
    +		case 8 : W = 120; H = 150; break;
    +	}
    +
    +	if (thorTxImg) {
    +		thorTxImg->release();
    +		thorTxImg = 0;
    +	}
    +	thorTxImg = Fl_Shared_Image::get(n, W, H);
    +
    +	if (!thorTxImg)
    +		return 0;
    +
    +	if (thorTxImg->count() > 1) {
    +		thorTxImg->release();
    +		thorTxImg = 0;
    +		return 0;
    +	}
    +
    +	thorpicTx->hide();
    +	thorpicTx->clear();
    +
    +	img_data = (unsigned char *)thorTxImg->data()[0];
    +
    +	D = thorTxImg->d();
    +
    +	if (thorxmtimg) delete [] thorxmtimg;
    +
    +	thorxmtimg = new unsigned char [W * H * 3];
    +	if (D == 3)
    +		memcpy(thorxmtimg, img_data, W*H*3);
    +	else if (D == 4) {
    +		int i, j, k;
    +		for (i = 0; i < W*H; i++) {
    +			j = i*3; k = i*4;
    +			thorxmtimg[j] = img_data[k];
    +			thorxmtimg[j+1] = img_data[k+1];
    +			thorxmtimg[j+2] = img_data[k+2];
    +		}
    +	} else if (D == 1) {
    +		int i, j;
    +		for (i = 0; i < W*H; i++) {
    +			j = i * 3;
    +			thorxmtimg[j] = thorxmtimg[j+1] = thorxmtimg[j+2] = img_data[i];
    +		}
    +	} else
    +		return 0;
    +
    +	char* label = strdup(n);
    +	thorpicTxWin->copy_label(basename(label));
    +	free(label);
    +// load the thorpicture widget with the rgb image
    +
    +	thorpicTx->show();
    +	thorpicTxWin->redraw();
    +	thorpicTx->video(thorxmtimg, W * H * 3);
    +
    +	btnthorpicTransmit->activate();
    +
    +	return 1;
    +}
    +
    +void thor_updateTxPic(unsigned char data, int pos)
    +{
    +	if (!thorpicTxWin->shown()) thorpicTx->show();
    +	thorpicTx->pixel(data, pos);
    +}
    +
    +void cb_thorpicTxLoad(Fl_Widget *, void *)
    +{
    +	const char *fn =
    +		FSEL::select(_("Load image file"), "Image\t*.{png,,gif,jpg,jpeg}\n", PicsDir.c_str());
    +	if (!fn) return;
    +	if (!*fn) return;
    +
    +	thor_load_image(fn);
    +}
    +
    +void thor_clear_tximage()
    +{
    +	thorpicTx->clear();
    +}
    +
    +void cb_thorpicTxClose( Fl_Widget *w, void *)
    +{
    +	thorpicTxWin->hide();
    +}
    +
    +int thorpic_TxGetPixel(int pos, int color)
    +{
    +	return thorxmtimg[3*pos + color]; // color = {RED, GREEN, BLUE}
    +}
    +
    +void cb_thorpicTransmit( Fl_Widget *w, void *)
    +{
    +	std::string header = "\npic%";
    +	switch (selthorpicSize->value()) {
    +		case 0: header += 'T'; break;
    +		case 1: header += 'S'; break;
    +		case 2: header += 'L'; break;
    +		case 3: header += 'F'; break;
    +		case 4: header += 'V'; break;
    +		case 5: header += 'P'; break;
    +		case 6: header += 'p'; break;
    +		case 7: header += 'M'; break;
    +		case 8: header += 'm'; break;
    +	}
    +	thor::imageheader = header;
    +	active_modem->thor_send_image();
    +}
    +
    +void cb_thorpicTxSendAbort( Fl_Widget *w, void *)
    +{
    +}
    +
    +
    +void cb_selthorpicSize( Fl_Widget *w, void *)
    +{
    +	switch (selthorpicSize->value()) {
    +		case 0 : thor_showTxViewer('T'); break;
    +		case 1 : thor_showTxViewer('S'); break;
    +		case 2 : thor_showTxViewer('L'); break;
    +		case 3 : thor_showTxViewer('F'); break;
    +		case 4 : thor_showTxViewer('V'); break;
    +		case 5 : thor_showTxViewer('P'); break;
    +		case 6 : thor_showTxViewer('p'); break;
    +		case 7 : thor_showTxViewer('M'); break;
    +		case 8 : thor_showTxViewer('m'); break;
    +	}
    +}
    +
    +void thor_createTxViewer()
    +{
    +
    +	thorpicTxWin = new Fl_Double_Window(324, 270, _("thor Send image"));
    +	thorpicTxWin->xclass(PACKAGE_NAME);
    +	thorpicTxWin->begin();
    +
    +	thorpicTx = new picture (2, 2, 320, 240);
    +	thorpicTx->noslant();
    +	thorpicTx->hide();
    +
    +	selthorpicSize = new Fl_Choice(5, 244, 110, 24);
    +	selthorpicSize->add("59 x 74 clr");	// case 0
    +	selthorpicSize->add("160x120 clr");	// case 1
    +	selthorpicSize->add("320x240 clr");	// case 2
    +	selthorpicSize->add("640x480 gry");	// case 3
    +	selthorpicSize->add("640x480 clr");	// case 4
    +	selthorpicSize->add("240x300 clr");	// case 5
    +	selthorpicSize->add("240x300 gry");	// case 6
    +	selthorpicSize->add("120x150 clr");	// case 7
    +	selthorpicSize->add("120x150 gry");	// case 8
    +	selthorpicSize->value(0);
    +	selthorpicSize->callback(cb_selthorpicSize, 0);
    +
    +	btnthorpicTxLoad = new Fl_Button(120, 244, 60, 24, _("Load"));
    +	btnthorpicTxLoad->callback(cb_thorpicTxLoad, 0);
    +
    +	btnthorpicTransmit = new Fl_Button(thorpicTxWin->w() - 130, 244, 60, 24, "Xmt");
    +	btnthorpicTransmit->callback(cb_thorpicTransmit, 0);
    +
    +	btnthorpicTxSendAbort = new Fl_Button(thorpicTxWin->w() - 130, 244, 60, 24, "Abort Xmt");
    +	btnthorpicTxSendAbort->callback(cb_thorpicTxSendAbort, 0);
    +
    +	btnthorpicTxClose = new Fl_Button(thorpicTxWin->w() - 65, 244, 60, 24, _("Close"));
    +	btnthorpicTxClose->callback(cb_thorpicTxClose, 0);
    +
    +	btnthorpicTxSendAbort->hide();
    +	btnthorpicTransmit->deactivate();
    +
    +	thorpicTxWin->end();
    +
    +}
    +
    +void thor_showTxViewer(char c)
    +{
    +	if (!thorpicTxWin) thor_createTxViewer();
    +
    +	int winW = 644, winH = 512, W = 480, H = 320;
    +	int thorpicX, thorpicY;
    +
    +	thorpicTx->clear();
    +
    +	switch (c) {
    +		case 'T' :
    +			W = 59; H = 74; winW = 324; winH = 184;
    +			selthorpicSize->value(0);
    +			break;
    +		case 'S' :
    +		case 's' :
    +			W = 160; H = 120; winW = 324; winH = 154;
    +			selthorpicSize->value(1);
    +			break;
    +		case 'L' :
    +		case 'l' :
    +			W = 320; H = 240; winW = 324; winH = 274; 
    +			selthorpicSize->value(2);
    +			break;
    +		case 'F' :
    +			W = 640; H = 480; winW = 644; winH = 514;
    +			selthorpicSize->value(3);
    +			break;
    +		case 'V' :
    +			W = 640; H = 480; winW = 644; winH = 514;
    +			selthorpicSize->value(4);
    +			break;
    +		case 'P' :
    +			W = 240; H = 300; winW = 324; winH = 334;
    +			selthorpicSize->value(5);
    +			break;
    +		case 'p' :
    +			W = 240; H = 300; winW = 324; winH = 334;
    +			selthorpicSize->value(6);
    +			break;
    +		case 'M' :
    +			W = 120; H = 150; winW = 324; winH = 184;
    +			selthorpicSize->value(7);
    +			break;
    +		case 'm' :
    +			W = 120; H = 150; winW = 324; winH = 184;
    +			selthorpicSize->value(8);
    +			break;
    +	}
    +
    +	thorpicTxWin->size(winW, winH);
    +	thorpicX = (winW - W) / 2;
    +	thorpicY = (winH - 26 - H) / 2;
    +	thorpicTx->resize(thorpicX, thorpicY, W, H);
    +
    +	selthorpicSize->resize(5, winH - 26, 110, 24);
    +
    +	btnthorpicTxLoad->resize(120, winH - 26, 60, 24);
    +
    +	btnthorpicTransmit->resize(winW - 130, winH - 26, 60, 24);
    +	btnthorpicTxSendAbort->resize(winW - 130, winH - 26, 60, 24);
    +
    +	btnthorpicTxClose->resize(winW -65, winH - 26, 60, 24);
    +
    +	selthorpicSize->show();
    +	btnthorpicTransmit->show();
    +	btnthorpicTxLoad->show();
    +	btnthorpicTxClose->show();
    +	btnthorpicTxSendAbort->hide();
    +
    +	thorpicTxWin->show();
    +
    +}
    +
    +void thor_deleteTxViewer()
    +{
    +	if (thorpicTxWin) thorpicTxWin->hide();
    +	if (thorpicTx) {
    +		delete thorpicTx;
    +		thorpicTx = 0;
    +	}
    +	delete [] thorxmtimg;
    +	thorxmtimg = 0;
    +	delete [] thorxmtpicbuff;
    +	thorxmtpicbuff = 0;
    +	if (thorpicTxWin) delete thorpicTxWin;
    +	thorpicTxWin = 0;
    +}
    +
    +void thor_deleteRxViewer()
    +{
    +	if (thorpicRxWin) thorpicRxWin->hide();
    +	if (thorpicRx) {
    +		delete thorpicRx;
    +		thorpicRx = 0;
    +	}
    +	if (thorpicRxWin) {
    +		delete thorpicRxWin;
    +		thorpicRxWin = 0;
    +	}
    +}
    +
    +int thor_print_time_left(float time_sec, char *str, size_t len,
    +			  const char *prefix, const char *suffix)
    +{
    +	int time_min = (int)(time_sec / 60);
    +	time_sec -= time_min * 60;
    +
    +	if (time_min)
    +		return snprintf(str, len, "%s %02dm %2.1fs%s",
    +				prefix, time_min, time_sec, suffix);
    +	else
    +		return snprintf(str, len, "%s %2.1fs%s", prefix, time_sec, suffix);
    +}
    +
    +// -----------------------------------------------------------------------------
    +// avatar send/recv
    +// -----------------------------------------------------------------------------
    +
    +static Fl_Shared_Image	*shared_avatar_img = (Fl_Shared_Image *)0;
    +static unsigned char *avatar_img = (unsigned char *)0;
    +static Fl_Shared_Image	*my_avatar_img = (Fl_Shared_Image *)0;
    +static int avatar_phase_correction = 0;
    +static unsigned char avatar[59 * 74 * 3];
    +
    +void thor_clear_avatar()
    +{
    +	thor_avatar->clear();
    +	avatar_phase_correction = 0;
    +	thor_numpixels = 0;
    +	thor_rawrow = thor_rawrgb = thor_rawcol = 0;
    +	thor_avatar->video(tux_img, 59 * 74 * 3);
    +}
    +
    +
    +// W always 59, H always 74
    +int thor_load_avatar(std::string image_fname, int W, int H)
    +{
    +	if (image_fname.empty()) {
    +		thor_clear_avatar();
    +		return 1;
    +	}
    +
    +	int D = 0;
    +	unsigned char *img_data;
    +
    +	if (shared_avatar_img) {
    +		shared_avatar_img->release();
    +		shared_avatar_img = 0;
    +	}
    +
    +	for (size_t n = 0; n < image_fname.length(); n++)
    +		image_fname[n] = tolower(image_fname[n]);
    +	std::string fname = AvatarDir;
    +	fname.append(image_fname).append(".png");
    +
    +	FILE *temp = fopen(fname.c_str(), "rb");
    +	if (temp) {
    +		fseek(temp, 0L, SEEK_SET);
    +		fclose(temp);
    +	} else {
    +		thor_avatar->video(tux_img, W * H * 3);
    +		return 1;
    +	}
    +
    +	shared_avatar_img = Fl_Shared_Image::get(fname.c_str(), W, H);
    +
    +// force image to be retrieved from hard drive vice shared image memory
    +	shared_avatar_img->reload(); 
    +
    +	if (!shared_avatar_img) {
    +		thor_avatar->video(tux_img, W * H * 3);
    +		return 1;
    +	}
    +
    +	if (shared_avatar_img->count() > 1) {
    +		shared_avatar_img->release();
    +		shared_avatar_img = 0;
    +		thor_avatar->video(tux_img, W * H * 3);
    +		return 0;
    +	}
    +
    +	img_data = (unsigned char *)shared_avatar_img->data()[0];
    +
    +	D = shared_avatar_img->d();
    +
    +	if (avatar_img) delete [] avatar_img;
    +
    +	avatar_img = new unsigned char [W * H * 3];
    +	if (D == 3)
    +		memcpy(avatar_img, img_data, W*H*3);
    +	else if (D == 4) {
    +		int i, j, k;
    +		for (i = 0; i < W*H; i++) {
    +			j = i*3; k = i*4;
    +			avatar_img[j] = img_data[k];
    +			avatar_img[j+1] = img_data[k+1];
    +			avatar_img[j+2] = img_data[k+2];
    +		}
    +	} else if (D == 1) {
    +		int i, j;
    +		for (i = 0; i < W*H; i++) {
    +			j = i * 3;
    +			avatar_img[j] = avatar_img[j+1] = avatar_img[j+2] = img_data[i];
    +		}
    +	} else {
    +		thor_avatar->video(tux_img, W * H * 3);
    +		return 0;
    +	}
    +	thor_avatar->video(avatar_img, W * H * 3);
    +
    +	shared_avatar_img->release();
    +
    +	return 1;
    +}
    +
    +void thor_correct_avatar()
    +{
    +	int W = 59;
    +	int H = 74;
    +	int index, rowptr, colptr;
    +	unsigned char vid[W * H * 3];
    +
    +	if (avatar_phase_correction >= RAWSTART/thor::IMAGEspp) {
    +		avatar_phase_correction = RAWSTART/thor::IMAGEspp - 1;
    +	}
    +	if (avatar_phase_correction < -RAWSTART/thor::IMAGEspp) {
    +		avatar_phase_correction = -RAWSTART/thor::IMAGEspp;
    +	}
    +
    +	for (int row = 0; row < H; row++) {
    +		rowptr = W * 3 * row * thor::IMAGEspp;
    +		for (int col = 0; col < W; col++) {
    +			colptr = thor::IMAGEspp*col;
    +			for (int rgb = 0; rgb < 3; rgb++) {
    +				index = rowptr + colptr + W*rgb*thor::IMAGEspp;
    +				index += RAWSTART - thor::IMAGEspp * avatar_phase_correction;
    +				if (index < 2) index = 2;
    +				if (index > RAWSIZE - 2) index = RAWSIZE - 2;
    +				vid[rgb + 3 * (col + row * W)] = thor_rawvideo[index];
    +			}
    +		}
    +	}
    +	thor_avatar->video(vid, W*H*3);
    +}
    +
    +void thor_update_avatar(unsigned char data, int pos)
    +{
    +	if (thor_rawvideo == 0) {
    +		thor_rawvideo = new unsigned char [RAWSIZE + 1];
    +		memset(thor_rawvideo, 0, RAWSIZE);
    +	}
    +
    +	thor_avatar->pixel(data, pos);
    +	for (int i = 0; i < thor::IMAGEspp; i++)
    +		thor_rawvideo[RAWSTART + thor::IMAGEspp*thor_numpixels + i] = data;
    +
    +	thor_numpixels++;
    +
    +	if (thor_numpixels >= (RAWSIZE - RAWSTART - thor::IMAGEspp)) 
    +		thor_numpixels = RAWSIZE - RAWSTART - thor::IMAGEspp;
    +
    +}
    +
    +int thor_get_avatar_pixel(int pos, int color)
    +{
    +// color = {RED, GREEN, BLUE}
    +	return (int)avatar[3*pos + color];
    +
    +}
    +
    +// ADD CALLBACK HANDLING OF PHASE CORRECTIONS
    +
    +void cb_thor_send_avatar( Fl_Widget *w, void *)
    +{
    +	if (Fl::event_button() == FL_RIGHT_MOUSE) {
    +		if (Fl::get_key	(FL_Shift_L) || Fl::get_key(FL_Shift_R)) {
    +			if (thor_numpixels == 0) return;
    +			avatar_phase_correction += 5;
    +			thor_correct_avatar();
    +			return;
    +		}
    +		if (Fl::get_key	(FL_Control_L) || Fl::get_key(FL_Control_R)) {
    +			if (thor_numpixels == 0) return;
    +			avatar_phase_correction++;
    +			thor_correct_avatar();
    +			return;
    +		}
    +		std::string mycall = progdefaults.myCall;
    +		for (size_t n = 0; n < mycall.length(); n++)
    +			mycall[n] = tolower(mycall[n]);
    +		std::string fname = AvatarDir;
    +		fname.append(mycall).append(".png");
    +
    +		my_avatar_img = Fl_Shared_Image::get(fname.c_str(), 59, 74);
    +		if (!my_avatar_img) return;
    +		unsigned char *img_data = (unsigned char *)my_avatar_img->data()[0];
    +		memset(avatar, 0, sizeof(avatar));
    +		int D = my_avatar_img->d();
    +
    +		if (D == 3)
    +			memcpy(avatar, img_data, 59*74*3);
    +		else if (D == 4) {
    +			int i, j, k;
    +			for (i = 0; i < 59*74; i++) {
    +				j = i*3; k = i*4;
    +				avatar[j] = img_data[k];
    +				avatar[j+1] = img_data[k+1];
    +				avatar[j+2] = img_data[k+2];
    +			}
    +		} else if (D == 1) {
    +			int i, j;
    +			for (i = 0; i < 59*74; i++) {
    +				j = i * 3;
    +				avatar[j] = avatar[j+1] = avatar[j+2] = img_data[i];
    +			}
    +		} else
    +			return;
    +
    +		thor::avatarheader = "\npic%A";
    +		active_modem->thor_send_avatar();
    +
    +		return;
    +	}
    +
    +	if (Fl::event_button() == FL_LEFT_MOUSE) {
    +		if (Fl::get_key	(FL_Shift_L) || Fl::get_key(FL_Shift_R)) {
    +			if (thor_numpixels == 0) return;
    +			avatar_phase_correction -= 5;
    +			thor_correct_avatar();
    +			return;
    +		}
    +		if (Fl::get_key	(FL_Control_L) || Fl::get_key(FL_Control_R)) {
    +			if (thor_numpixels == 0) return;
    +			avatar_phase_correction--;
    +			thor_correct_avatar();
    +			return;
    +		}
    +		std::string mycall = inpCall->value();
    +		if (mycall.empty()) return;
    +		for (size_t n = 0; n < mycall.length(); n++)
    +			mycall[n] = tolower(mycall[n]);
    +		std::string fname = AvatarDir;
    +		fname.append(mycall).append(".png");
    +		thor_avatar->save_png(fname.c_str());
    +	}
    +}
    +
    +
    diff --git a/src/thor/thor.cxx b/src/thor/thor.cxx
    index 09d63c0f..e5007073 100644
    --- a/src/thor/thor.cxx
    +++ b/src/thor/thor.cxx
    @@ -22,11 +22,19 @@
     // along with fldigi.  If not, see .
     // ----------------------------------------------------------------------------
     
    +
     #include 
     
     #include 
    -
     #include 
    +#include 
    +#include 
    +#include 
    +#include 
    +#include 
    +#include 
    +
    +#include 
     
     #include "confdialog.h"
     #include "status.h"
    @@ -52,6 +60,8 @@ using namespace std;
     char thormsg[80];
     char confidence[80];
     
    +#include "thor-pic.cxx"
    +
     void thor::tx_init(SoundBase *sc)
     {
     	scard = sc;
    @@ -88,6 +98,11 @@ void thor::rx_init()
     	fec_confidence = 0;
     
     	s2n_valid = false;
    +	txstate = TX_STATE_RECEIVE;
    +
    +	state = TEXT;
    +	pic_str = "     ";
    +	img_phase = 0.0;
     }
     
     void thor::reset_filters()
    @@ -149,6 +164,8 @@ void thor::init()
     	modem::init();
     //	reset_filters();
     	rx_init();
    +	imageheader.clear();
    +	avatarheader.clear();
     
     	set_scope_mode(Digiscope::DOMDATA);
     }
    @@ -174,6 +191,9 @@ thor::~thor()
     	if (Dec) delete Dec;
     	if (Enc) delete Enc;
     
    +	delete picfilter;
    +	delete pixfilter;
    +	delete pixsyncfilter;
     }
     
     thor::thor(trx_mode md) : hilbert(0), fft(0), filter_reset(false)
    @@ -195,12 +215,14 @@ thor::thor(trx_mode md) : hilbert(0), fft(0), filter_reset(false)
     		break;
     
     	case MODE_THOR11:
    +		cap |= CAP_IMG;
     		symlen = 1024;
     		doublespaced = 1;
     		samplerate = 11025;
     		break;
     
     	case MODE_THOR22:
    +		cap |= CAP_IMG;
     		symlen = 512;
     		doublespaced = 1;
     		samplerate = 11025;
    @@ -253,6 +275,7 @@ thor::thor(trx_mode md) : hilbert(0), fft(0), filter_reset(false)
     
     	case MODE_THOR16:
     	default:
    +		cap |= CAP_IMG;
     		symlen = 512;
     		doublespaced = 1;
     		samplerate = 8000;
    @@ -318,6 +341,13 @@ thor::thor(trx_mode md) : hilbert(0), fft(0), filter_reset(false)
     	symbolpair[0] = symbolpair[1] = 0;
     	datashreg = 1;
     
    +	picfilter = new C_FIR_filter();
    +	picfilter->init_lowpass(257, 1, 1.0 * bandwidth / samplerate);
    +
    +	IMAGEspp = THOR_IMAGESPP;
    +	pixfilter = new Cmovavg(IMAGEspp);
    +	pixsyncfilter = new Cmovavg(3*IMAGEspp);
    +
     	init();
     }
     
    @@ -349,6 +379,41 @@ void thor::s2nreport(void)
     	s2n_valid = false;
     }
     
    +void thor::parse_pic(int ch)
    +{
    +	pic_str.erase(0,1);
    +	pic_str += ch;
    +	b_ava = false;
    +	image_mode = 0;
    +	if (pic_str.find("pic%") == 0) {
    +		switch (pic_str[4]) {
    +			case 'A':	picW = 59; picH = 74; b_ava = true; break;
    +			case 'T':	picW = 59; picH = 74; break;
    +			case 'S':	picW = 160; picH = 120; break;
    +			case 'L':	picW = 320; picH = 240; break;
    +			case 'F':	picW = 640; picH = 480; break;
    +			case 'V':	picW = 640; picH = 480; break;
    +			case 'P':	picW = 240; picH = 300; break;
    +			case 'p':	picW = 240; picH = 300; image_mode = 1; break;
    +			case 'M':	picW = 120; picH = 150; break;
    +			case 'm':	picW = 120; picH = 150; image_mode = 1; break;
    +			default: return;
    +		}
    +	} else
    +		return;
    +
    +	if (b_ava)
    +		REQ( thor_clear_avatar );
    +	else
    +		REQ( thor_showRxViewer, pic_str[4]);
    +
    +	image_counter = -symlen / 2;
    +	col = row = rgb = 0;
    +	pixsyncfilter->reset();
    +	pixfilter->reset();
    +	state = IMAGE_START;
    +}
    +
     void thor::recvchar(int c)
     {
     	if (c == -1)
    @@ -356,6 +421,7 @@ void thor::recvchar(int c)
     	if (c & 0x100)
     		put_sec_char(c & 0xFF);
     	else {
    +		parse_pic(c);
     		put_rx_char(c & 0xFF);
     		if (progdefaults.Pskmails2nreport && (mailserver || mailclient)) {
     			if (((c & 0xFF) == SOH) && !s2n_valid) {
    @@ -861,6 +927,93 @@ void thor::eval_s2n()
     	put_Status2(confidence);
     }
     
    +void thor::recvpic(double smpl)
    +{
    +	phidiff = 2.0 * M_PI * frequency / samplerate;
    +	img_phase -= phidiff;
    +	if (img_phase < 0) img_phase += 2.0 * M_PI;
    +
    +	cmplx z = smpl * cmplx( cos(img_phase), sin(img_phase ) );
    +	picfilter->run( z, currz);
    +	double dphase = arg(conj(prevz) * currz);
    +	pixel = (samplerate / TWOPI) * pixfilter->run(dphase);
    +	sync = (samplerate / TWOPI) * pixsyncfilter->run(dphase);
    +	prevz = currz;
    +
    +//if (image_counter == - (symlen / 2)) std::cout << "IMAGE START\n";
    +
    +	image_counter++;
    +	if (image_counter < 0)
    +		return;
    +
    +	if (state == IMAGE_START) {
    +		if (sync < -0.59 * bandwidth) {
    +			state = IMAGE_SYNC;
    +//std::cout << "IMAGE SYNC " << image_counter << "\n";
    +		}
    +		return;
    +	}
    +	if (state == IMAGE_SYNC) {
    +		if (sync > -0.51 * bandwidth) {
    +			state = IMAGE;
    +//std::cout << "IMAGE RECV " << image_counter << "\n";
    +		}
    +		return;
    +	}
    +
    +	if ((image_counter % IMAGEspp) == 0) {
    +		byte = pixel * 256.0 / bandwidth + 128;
    +		byte = (int)CLAMP( byte, 0.0, 255.0);
    +
    +		if (image_mode == 1) { // bw transmission
    +			pixelnbr = 3 * (col + row * picW);
    +			if (b_ava) {
    +				REQ(thor_update_avatar, byte, pixelnbr);
    +				REQ(thor_update_avatar, byte, pixelnbr + 1);
    +				REQ(thor_update_avatar, byte, pixelnbr + 2);
    +			} else {
    +				REQ(thor_updateRxPic, byte, pixelnbr);
    +				REQ(thor_updateRxPic, byte, pixelnbr + 1);
    +				REQ(thor_updateRxPic, byte, pixelnbr + 2);
    +			}
    +			if (++ col == picW) {
    +				col = 0;
    +				row++;
    +				if (row >= picH) {
    +					state = TEXT;
    +					REQ(thor_enableshift);
    +				}
    +			}
    +		} else { // color transmission
    +			pixelnbr = rgb + 3 * (col + row * picW);
    +			if (b_ava)
    +				REQ(thor_update_avatar, byte, pixelnbr);
    +			else
    +				REQ(thor_updateRxPic, byte, pixelnbr);
    +			if (++col == picW) {
    +				col = 0;
    +				if (++rgb == 3) {
    +					rgb = 0;
    +					++row;
    +				}
    +			}
    +			if (row > picH) {
    +				state = TEXT;
    +				REQ(thor_enableshift);
    +			}
    +		}
    +/*
    +		amplitude *= (samplerate/2)*(.734); // sqrt(3000 / (11025/2))
    +		s2n = 10 * log10(snfilt->run( amplitude * amplitude / noise));
    +
    +		metric = 2 * (s2n + 20);
    +		metric = CLAMP(metric, 0, 100.0);  // -20 to +30 db range
    +		display_metric(metric);
    +		amplitude = 0;
    +*/
    +	}
    +}
    +
     int thor::rx_process(const double *buf, int len)
     {
     	cmplx zref, *zp;
    @@ -875,60 +1028,65 @@ int thor::rx_process(const double *buf, int len)
     	if (filter_reset) reset_filters();
     
     	while (len) {
    -// create analytic signal at first IF
    -		zref = cmplx( *buf, *buf );
    -		buf++;
    -		hilbert->run(zref, zref);
    -		zref = mixer(0, zref);
    -
    -		if (progdefaults.THOR_FILTER && fft) {
    -// filter using fft convolution
    -			n = fft->run(zref, &zp);
    +		if (state != TEXT) {
    +			recvpic(*buf);
     		} else {
    -			zarray[0] = zref;
    -			zp = zarray;
    -			n = 1;
    -		}
     
    -		if (n) {
    -			for (int i = 0; i < n; i++) {
    -				cmplx * pipe_pipeptr_vector = pipe[pipeptr].vector ;
    -				const cmplx zp_i = zp[i];
    +// create analytic signal at first IF
    +			zref = cmplx( *buf, *buf );
    +			hilbert->run(zref, zref);
    +			zref = mixer(0, zref);
    +
    +			if (progdefaults.THOR_FILTER && fft) {
    +// filter using fft convolution
    +				n = fft->run(zref, &zp);
    +			} else {
    +				zarray[0] = zref;
    +				zp = zarray;
    +				n = 1;
    +			}
    +
    +			if (n) {
    +				for (int i = 0; i < n; i++) {
    +					cmplx * pipe_pipeptr_vector = pipe[pipeptr].vector ;
    +					const cmplx zp_i = zp[i];
     // process THORMAXFFTS sets of sliding FFTs spaced at 1/THORMAXFFTS bin intervals each of which
     // is a matched filter for the current symbol length
    -				for (int k = 0; k < paths; k++) {
    +					for (int k = 0; k < paths; k++) {
     // shift in frequency to base band for the sliding DFTs
    -					const cmplx z = mixer(k + 1, zp_i );
    +						const cmplx z = mixer(k + 1, zp_i );
     // copy current vector to the pipe interleaving the FFT vectors
    -					binsfft[k]->run(z, pipe_pipeptr_vector + k, paths );
    +						binsfft[k]->run(z, pipe_pipeptr_vector + k, paths );
    +					}
    +					if (--synccounter <= 0) {
    +						synccounter = symlen;
    +
    +						if (progdefaults.THOR_SOFTSYMBOLS)
    +							currsymbol = softdecode();
    +						else
    +							currsymbol = harddecode();
    +
    +						currmag = abs(pipe_pipeptr_vector[currsymbol]);
    +						eval_s2n();
    +
    +						if (progdefaults.THOR_SOFTBITS)
    +							softdecodesymbol();
    +						else
    +							decodesymbol();
    +
    +						synchronize();
    +						prev2symbol = prev1symbol;
    +						prev1symbol = currsymbol;
    +						prev2mag = prev1mag;
    +						prev1mag = currmag;
    +					}
    +					pipeptr++;
    +					if (pipeptr >= twosym)
    +						pipeptr = 0;
     				}
    -				if (--synccounter <= 0) {
    -					synccounter = symlen;
    -
    -					if (progdefaults.THOR_SOFTSYMBOLS)
    -						currsymbol = softdecode();
    -					else
    -						currsymbol = harddecode();
    -
    -					currmag = abs(pipe_pipeptr_vector[currsymbol]);
    -					eval_s2n();
    -
    -					if (progdefaults.THOR_SOFTBITS)
    -						softdecodesymbol();
    -					else
    -						decodesymbol();
    -
    -					synchronize();
    -					prev2symbol = prev1symbol;
    -					prev1symbol = currsymbol;
    -					prev2mag = prev1mag;
    -					prev1mag = currmag;
    -				}
    -				pipeptr++;
    -				if (pipeptr >= twosym)
    -					pipeptr = 0;
     			}
     		}
    +		buf++;
     		--len;
     	}
     
    @@ -1036,6 +1194,8 @@ void thor::flushtx()
       bitstate = 0;
     }
     
    +static bool hide_after_sending = false;
    +
     int thor::tx_process()
     {
     	int i = 0;
    @@ -1046,16 +1206,24 @@ int thor::tx_process()
     
     		for (int j = 0; j < 16; j++) sendsymbol(0);
     
    -	sendidle();
    +		sendidle();
     		txstate = TX_STATE_START;
     		break;
     	case TX_STATE_START:
     		sendchar('\r', 0);
     		sendchar(2, 0);		// STX
     		sendchar('\r', 0);
    -		txstate = TX_STATE_DATA;
    +			txstate = TX_STATE_DATA;
     		break;
     	case TX_STATE_DATA:
    +		if (imageheader.length()) {
    +			txstate = TX_STATE_IMAGE;
    +			break;
    +		}
    +		if (avatarheader.length()) {
    +			txstate = TX_STATE_AVATAR;
    +			break;
    +		}
     		i = get_tx_char();
     		if (i == GET_TX_CHAR_NODATA)
     			sendsecondary();
    @@ -1063,8 +1231,10 @@ int thor::tx_process()
     			txstate = TX_STATE_END;
     		else
     			sendchar(i, 0);
    -		if (stopflag)
    +		if (stopflag) {
     			txstate = TX_STATE_END;
    +			stopflag = false;
    +		}
     		break;
     	case TX_STATE_END:
     		sendchar('\r', 0);
    @@ -1075,8 +1245,179 @@ int thor::tx_process()
     	case TX_STATE_FLUSH:
     		flushtx();
     		cwid();
    +		txstate = TX_STATE_RECEIVE;
     		return -1;
    +	case TX_STATE_IMAGE:
    +		for (size_t n = 0; n < imageheader.length(); n++)
    +			sendchar(imageheader[n], 0);
    +		flushtx();
    +		send_image();
    +		if (hide_after_sending) thorpicTxWin->hide();
    +		hide_after_sending = false;
    +		txstate = TX_STATE_DATA;
    +		break;
    +	case TX_STATE_AVATAR:
    +		for (size_t n = 0; n < avatarheader.length(); n++)
    +			sendchar(avatarheader[n], 0);
    +		flushtx();
    +		send_avatar();
    +		txstate = TX_STATE_DATA;
    +		break;
     	}
     	return 0;
     }
     
    +// image support
    +
    +#define PHASE_CORR  20
    +
    +void thor::send_image() {
    +	int W = 640, H = 480;  // grey scale transfer (FAX)
    +	bool color = true;
    +	float freq, phaseincr;
    +	float radians = 2.0 * M_PI / samplerate;
    +
    +	imageheader.clear();
    +
    +	if (!thorpicTxWin || !thorpicTxWin->visible()) {
    +		return;
    +	}
    +
    +	switch (selthorpicSize->value()) {
    +		case 0 : W = 59; H = 74; break;
    +		case 1 : W = 160; H = 120; break;
    +		case 2 : W = 320; H = 240; break;
    +		case 3 : W = 640; H = 480; color = false; break;
    +		case 4 : W = 640; H = 480; break;
    +		case 5 : W = 240; H = 300; break;
    +		case 6 : W = 240; H = 300; color = false; break;
    +		case 7 : W = 120; H = 150; break;
    +		case 8 : W = 120; H = 150; color = false; break;
    +	}
    +
    +	REQ(thor_clear_tximage);
    +
    +	double black[symlen];
    +
    +	memset(black, 0, sizeof(*black) * symlen);
    +	for (int i = 0; i < PHASE_CORR; i++) ModulateXmtr(black, symlen);
    +
    +	freq = frequency - 0.6 * bandwidth;
    +	phaseincr = radians * freq;
    +	for (int i = 0; i < PHASE_CORR; i++) {
    +		for (int n = 0; n < symlen; n++) {
    +			black[n] = cos(txphase);
    +			txphase -= phaseincr;
    +			if (txphase < 0) txphase += TWOPI;
    +		}
    +		ModulateXmtr(black, symlen);
    +	}
    +
    +	if (color == false) {  // grey scale image
    +		for (int row = 0; row < H; row++) {
    +			memset(outbuf, 0, IMAGEspp * sizeof(*outbuf));
    +			for (int col = 0; col < W; col++) {
    +				if (stopflag) return;
    +				tx_pixelnbr = col + row * W;
    +				tx_pixel =	0.3 * thorpic_TxGetPixel(tx_pixelnbr, 0) +   // red
    +							0.6 * thorpic_TxGetPixel(tx_pixelnbr, 1) +   // green
    +							0.1 * thorpic_TxGetPixel(tx_pixelnbr, 2);    // blue
    +				REQ(thor_updateTxPic, tx_pixel, tx_pixelnbr*3 + 0);
    +				REQ(thor_updateTxPic, tx_pixel, tx_pixelnbr*3 + 1);
    +				REQ(thor_updateTxPic, tx_pixel, tx_pixelnbr*3 + 2);
    +				freq = frequency + (tx_pixel - 128) * bandwidth / 256.0;
    +				phaseincr = radians * freq;
    +				for (int n = 0; n < IMAGEspp; n++) {
    +					outbuf[n] = cos(txphase);
    +					txphase -= phaseincr;
    +					if (txphase < 0) txphase += TWOPI;
    +				}
    +				ModulateXmtr(outbuf, IMAGEspp);
    +				Fl::awake();
    +			}
    +		}
    +	} else {
    +		for (int row = 0; row < H; row++) {
    +			for (int color = 0; color < 3; color++) {
    +				memset(outbuf, 0, IMAGEspp * sizeof(*outbuf));
    +				for (int col = 0; col < W; col++) {
    +					if (stopflag) return;
    +					tx_pixelnbr = col + row * W;
    +					tx_pixel = thorpic_TxGetPixel(tx_pixelnbr, color);
    +					REQ(thor_updateTxPic, tx_pixel, tx_pixelnbr*3 + color);
    +					freq = frequency + (tx_pixel - 128) * bandwidth / 256.0;
    +					phaseincr = radians * freq;
    +					for (int n = 0; n < IMAGEspp; n++) {
    +						outbuf[n] = cos(txphase);
    +						txphase -= phaseincr;
    +						if (txphase < 0) txphase += TWOPI;
    +					}
    +					ModulateXmtr(outbuf, IMAGEspp);
    +				}
    +				Fl::awake();
    +			}
    +		}
    +	}
    +
    +}
    +
    +void thor::thor_send_image(std::string image_str) {
    +	if (!image_str.empty()) {
    +		hide_after_sending = true;
    +		imageheader = image_str;
    +	}
    +	if (txstate == TX_STATE_RECEIVE)
    +		start_tx();
    +}
    +
    +void thor::send_avatar()
    +{
    +	int W = 59, H = 74;
    +	float freq, phaseincr;
    +	float radians = 2.0 * M_PI / samplerate;
    +
    +	avatarheader.clear();
    +
    +	double black[symlen];
    +
    +	memset(black, 0, sizeof(*black) * symlen);
    +
    +	freq = frequency - 0.6 * bandwidth;
    +	phaseincr = radians * freq;
    +	for (int i = 0; i < PHASE_CORR; i++) ModulateXmtr(black, symlen);
    +
    +	for (int i = 0; i < PHASE_CORR; i++) {
    +		for (int n = 0; n < symlen; n++) {
    +			black[n] = cos(txphase);
    +			txphase -= phaseincr;
    +			if (txphase < 0) txphase += TWOPI;
    +		}
    +		ModulateXmtr(black, symlen);
    +	}
    +
    +	for (int row = 0; row < H; row++) {
    +		for (int color = 0; color < 3; color++) {
    +			memset(outbuf, 0, IMAGEspp * sizeof(*outbuf));
    +			for (int col = 0; col < W; col++) {
    +				if (stopflag) return;
    +				tx_pixelnbr = col + row * W;
    +				tx_pixel = thor_get_avatar_pixel(tx_pixelnbr, color);
    +				freq = frequency + (tx_pixel - 128) * bandwidth / 256.0;
    +				phaseincr = radians * freq;
    +				for (int n = 0; n < IMAGEspp; n++) {
    +					outbuf[n] = cos(txphase);
    +					txphase -= phaseincr;
    +					if (txphase < 0) txphase += TWOPI;
    +				}
    +				ModulateXmtr(outbuf, IMAGEspp);
    +			}
    +			Fl::awake();
    +		}
    +	}
    +}
    +
    +void thor::thor_send_avatar() {
    +	if (txstate == TX_STATE_RECEIVE) {
    +		start_tx();
    +	}
    +}
    diff --git a/src/trx/modem.cxx b/src/trx/modem.cxx
    index c1c03920..bc087c3d 100644
    --- a/src/trx/modem.cxx
    +++ b/src/trx/modem.cxx
    @@ -102,7 +102,9 @@ modem *_8psk1000_modem = 0;
     modem *_8psk1200_modem = 0;
     modem *_8psk1333_modem = 0;
     
    +modem *_8psk125fl_modem = 0;
     modem *_8psk125f_modem = 0;
    +modem *_8psk250fl_modem = 0;
     modem *_8psk250f_modem = 0;
     modem *_8psk500f_modem = 0;
     modem *_8psk1000f_modem = 0;
    @@ -175,6 +177,8 @@ modem *thor100_modem = 0;
     
     modem *fsq_modem = 0;
     
    +modem *ifkp_modem = 0;
    +
     modem *dominoex4_modem = 0;
     modem *dominoex5_modem = 0;
     modem *dominoex8_modem = 0;
    @@ -302,6 +306,7 @@ double modem::get_txfreq(void) const
     		return 0;
     	else if (mailserver && progdefaults.PSKmailSweetSpot)
     		return progdefaults.PSKsweetspot;
    +	if (get_mode() == MODE_FSQ) return 1500;
     	return tx_frequency;
     }
     
    @@ -309,6 +314,7 @@ double modem::get_txfreq_woffset(void) const
     {
     	if (mailserver && progdefaults.PSKmailSweetSpot)
     		return (progdefaults.PSKsweetspot - progdefaults.TxOffset);
    +	if (get_mode() == MODE_FSQ) return (1500 - progdefaults.TxOffset);
     	return (tx_frequency - progdefaults.TxOffset);
     }
     
    @@ -334,7 +340,7 @@ void modem::set_metric(double m)
     void modem::display_metric(double m)
     {
     	set_metric(m);
    -	if(!progStatus.pwrsqlonoff)
    +	if(!progStatus.kpsql_enabled)
     	::global_display_metric(m);
     }
     
    @@ -405,7 +411,7 @@ double modem::sigmaN (double es_ovr_n0)
     	case MODE_PSK125: case MODE_PSK250: case MODE_PSK500:
     	case MODE_QPSK31: case MODE_QPSK63: case MODE_QPSK125: case MODE_QPSK250:
     	case MODE_PSK125R: case MODE_PSK250R: case MODE_PSK500R:
    -		mode_factor *= 16;
    +		mode_factor = 400;
     		break;
     	case MODE_THROB1: case MODE_THROB2: case MODE_THROB4:
     	case MODE_THROBX1: case MODE_THROBX2: case MODE_THROBX4:
    @@ -454,13 +460,20 @@ double modem::gauss(double sigma) {
     // simulating the noise that is added to the signal.
     // return signal + noise, limiting value to +/- 1.0
     
    +//static double mag;
    +
     void modem::add_noise(double *buffer, int len)
     {
    -	double sigma = sigmaN(progdefaults.s2n);
    +	double sigma = sigmaN(noiseDB->value());
     	double sn = 0;
     	for (int n = 0; n < len; n++) {
    -		sn = (buffer[n] + gauss(sigma)) / (1.0 + 3.0 * sigma);
    -		buffer[n] = clamp(sn, -1.0, 1.0);
    +//		mag = fabs(buffer[n]);
    +//		if (btn_imd_on->value())
    +//			buffer[n] *= (1.0 - mag *xmtimd->value())/(1.0 - xmtimd->value());
    +		if (btnNoiseOn->value()) {
    +			sn = (buffer[n] + gauss(sigma)) / (1.0 + 3.0 * sigma);
    +			buffer[n] = clamp(sn, -1.0, 1.0);
    +		}
     	}
     }
     
    @@ -488,12 +501,12 @@ void modem::ModulateXmtr(double *buffer, int len)
     		return;
     	}
     
    +	if (withnoise) add_noise(buffer, len);
    +
     	if (progdefaults.viewXmtSignal &&
     		!(PERFORM_CPS_TEST || active_modem->XMLRPC_CPS_TEST))
     		trx_xmit_wfall_queue(samplerate, buffer, (size_t)len);
     
    -	if (withnoise && progdefaults.noise) add_noise(buffer, len);
    -
     	double mult = pow(10, progdefaults.txlevel / 20.0);
     	if (mult > 0.99) mult = 0.99;
     	for (int i = 0; i < len; i++) {
    @@ -527,12 +540,12 @@ void modem::ModulateStereo(double *left, double *right, int len, bool sample_fla
     	if(sample_flag)
     		tx_sample_count += len;
     
    +	if (withnoise && progdefaults.noise) add_noise(left, len);
    +
     	if (progdefaults.viewXmtSignal &&
     		!(PERFORM_CPS_TEST || active_modem->XMLRPC_CPS_TEST))
     		trx_xmit_wfall_queue(samplerate, left, (size_t)len);
     
    -	if (withnoise && progdefaults.noise) add_noise(left, len);
    -
     	double mult = pow(10, progdefaults.txlevel / 20.0);
     	if (mult > 0.99) mult = 0.99;
     
    @@ -569,12 +582,12 @@ void modem::ModulateVideoStereo(double *left, double *right, int len, bool sampl
     	if(sample_flag)
     		tx_sample_count += len;
     
    +	if (withnoise && progdefaults.noise) add_noise(left, len);
    +
     	if (progdefaults.viewXmtSignal &&
     		!(PERFORM_CPS_TEST || active_modem->XMLRPC_CPS_TEST))
     		trx_xmit_wfall_queue(samplerate, left, (size_t)len);
     
    -	if (withnoise && progdefaults.noise) add_noise(left, len);
    -
     	double mult = 0.99 * pow(10, progdefaults.txlevel / 20.0);
     
     	for (int i = 0; i < len; i++) {
    @@ -612,6 +625,8 @@ void modem::ModulateVideo(double *buffer, int len)
     		return;
     	}
     
    +	if (withnoise && progdefaults.noise) add_noise(buffer, len);
    +
     	if (progdefaults.viewXmtSignal &&
     		!(PERFORM_CPS_TEST || active_modem->XMLRPC_CPS_TEST))
     		trx_xmit_wfall_queue(samplerate, buffer, (size_t)len);
    @@ -732,7 +747,7 @@ void modem::cwid_send_symbol(int bits)
     		sample = 0,
     		currsym = bits & 1;
     
    -	freq = tx_frequency - progdefaults.TxOffset;
    +	freq = get_txfreq() - progdefaults.TxOffset;
     
     	if ((currsym == 1) && (cwid_lastsym == 0))
     		cwid_phaseacc = 0.0;
    @@ -857,7 +872,7 @@ void modem::wfid_make_tones(int numchars)
     {
     	double f, flo, fhi;
     	int vwidth = (numchars*NUMCOLS + (numchars-1)*CHARSPACE - 1);
    -	f = tx_frequency + TONESPACING * vwidth/2.0;
    +	f = get_txfreq() + TONESPACING * vwidth/2.0;
     	fhi = f + TONESPACING;
     	flo = fhi - (vwidth + 2) * TONESPACING;
     	for (int i = 1; i <= NUMCOLS * numchars; i++) {
    diff --git a/src/trx/trx.cxx b/src/trx/trx.cxx
    index cc7c9bfd..83b036bd 100644
    --- a/src/trx/trx.cxx
    +++ b/src/trx/trx.cxx
    @@ -696,11 +696,13 @@ void trx_start(void)
     //=============================================================================
     void trx_close()
     {
    +	LOG_INFO("%s", "closing trx thread");
     	int count = 1000;
     	active_modem->set_stopflag(true);
     	while (trx_state != STATE_RX && count--)
     		MilliSleep(10);
     	if (trx_state != STATE_RX) {
    +		LOG_INFO("%s", "trx_state != STATE_RX");
     		exit(1);
     	}
     	count = 1000;
    @@ -708,6 +710,7 @@ void trx_close()
     	while (trx_state != STATE_ENDED && count--)
     		MilliSleep(10);
     	if (trx_state != STATE_ENDED) {
    +		LOG_INFO("%s", "trx_state != STATE_ENDED");
     		exit(2);
     	}
     #if USE_NAMED_SEMAPHORES
    @@ -723,6 +726,7 @@ void trx_close()
     		delete scard;
     		scard = 0;
     	}
    +	LOG_INFO("%s", "trx thread closed");
     }
     
     //=============================================================================
    diff --git a/src/waterfall/colorbox.cxx b/src/waterfall/colorbox.cxx
    index 94dc7020..a64b0c0b 100644
    --- a/src/waterfall/colorbox.cxx
    +++ b/src/waterfall/colorbox.cxx
    @@ -88,6 +88,7 @@ void loadPalette()
     	}
         const char *p = FSEL::select(_("Open palette"), _("Fldigi palette\t*.pal"), palfilename.c_str());
     	if (!p) return;
    +	if (!*p) return;
     	if ((clrfile = fopen(p, "r")) != NULL) {
     		for (int i = 0; i < 9; i++) {
     			if (fscanf(clrfile, "%d;%d;%d\n", &r, &g, &b) == EOF) {
    diff --git a/src/waterfall/raster.cxx b/src/waterfall/raster.cxx
    index 383bdd90..9efc0159 100644
    --- a/src/waterfall/raster.cxx
    +++ b/src/waterfall/raster.cxx
    @@ -22,6 +22,9 @@
     
     #include 
     
    +#include 
    +
    +#include 
     #include 
     
     #include "raster.h"
    @@ -33,21 +36,24 @@
     #include "raster.h"
     #include "qrunner.h"
     
    +using namespace std;
    +
     bool rowschanged = false;
     
     Raster::Raster (int X, int Y, int W, int H) :
     	Fl_Widget (X, Y, W, H) {
     	width = W - 4;
     	height = H - 4;
    -	space = 2;
    -	rowheight = 60;
    -	Nrows = (int)(height / (rowheight + space) - 0.5);
    +	space = 1;
    +	rowheight = 2 * FELD_RX_COLUMN_LEN + space;
    +
    +	Nrows = 0;
    +	while ((Nrows * rowheight) < height) Nrows++;
    +	Nrows--;
    +
     	vidbuf = new unsigned char[width * height];
     	memset(vidbuf, 255, width * height);
     	col = 0;
    -	vidpos = 0;
    -	numcols = 0;
    -	yp = Nrows * (space + rowheight);
     	box(FL_DOWN_BOX);
     }
     
    @@ -59,39 +65,29 @@ Raster::~Raster()
     
     void Raster::data(int data[], int len)
     {
    -	if (data == NULL || len == 0)
    +	if (data == NULL || len == 0 || (len > rowheight))
     		return;
    -	int h = len;
    -	int pos;
    -	int zeropos;
     
     	FL_LOCK_D();
     
    -	if (h > height) 
    -		h = height;
    -	col++;
    -	if (col >= width) {
    -		unsigned char *from = vidbuf + (space + rowheight) * width;
    -		int numtocopy = Nrows * (space + rowheight) * width;
    -		memmove(vidbuf, from, numtocopy);
    -		memset(	vidbuf + yp * width, 
    -				255, (space + rowheight) * width);
    -		col = 0;
    -		damage(FL_DAMAGE_USER2);
    +	for (int row = 0; row < Nrows; row++) {
    +		int rowstart = width * rowheight * row;
    +		int nextrow = width * rowheight * (row + 1);
    +		for (int i = 0; i < len; i++) {
    +			memmove(	vidbuf + rowstart + i*width,
    +						vidbuf + rowstart + i*width + 1, 
    +						width - 1);
    +			if (row < (Nrows - 1)) {
    +				vidbuf[rowstart + i*width + width - 1] =
    +					vidbuf[nextrow + i* width];
    +			}
    +		}
     	}
    -	else
    -		if (damage() != FL_DAMAGE_ALL)
    -			damage(FL_DAMAGE_USER1);
    -	zeropos = Nrows * (space + rowheight) * width;
    -	for (int i = 0; i < h; i++) {
    -		pos = zeropos + width * (h - i - 1) + col;
    -		vidbuf[pos] = (unsigned char)data[i];
    +	int toppixel = width * (Nrows - 1) * rowheight + width - 1;
    +	for (int i = 0; i < len; i++) {
    +		vidbuf[toppixel + width * (len - i)] = (unsigned char) data[i];
     	}
    -	numcols++;
    -	vidpos = col - numcols;
    -	if (vidpos < 0) vidpos = 0;
    -	
    -//	redraw();
    +
     	REQ_DROP(&Raster::redraw, this);
     	FL_UNLOCK_D();
     
    @@ -100,25 +96,26 @@ void Raster::data(int data[], int len)
     
     void Raster::clear()
     {
    -	FL_LOCK_D();
    -	for (int i = 0; i < width * height; i++)
    -		vidbuf[i] = 255;
    -	col = width;
    -	REQ_DROP(&Raster::redraw, this);
    +	memset(vidbuf, 255, width * height);
     //	redraw();
    -	FL_UNLOCK_D();
    +	REQ_DROP(&Raster::redraw, this);
     	FL_AWAKE_D();
     }
     
     void Raster::resize(int x, int y, int w, int h)
     {
    -	int Wdest = w - 4, Hdest = h - 4;
    -	int Ndest = (int)(Hdest / (rowheight + space) - 0.5);
    +	int Wdest = w - 4;
    +	int Hdest = h - 4;
    +	int Ndest;
     	unsigned char *tempbuf = new unsigned char [Wdest * Hdest];
     	unsigned char *oldbuf;
     	int xfrcols, xfrrows;
     	int from, to;
     
    +	Ndest = 0;
    +	while ((Ndest * rowheight) < Hdest) Ndest++;
    +	Ndest--;
    +
     	memset(tempbuf, 255, Wdest * Hdest);
     
     	if (Wdest >= width)
    @@ -127,27 +124,27 @@ void Raster::resize(int x, int y, int w, int h)
     		xfrcols = Wdest;
     
     	if (Ndest <= Nrows) {
    -		xfrrows = (Ndest + 1)*(rowheight + space);
    -		from = (Nrows - Ndest) * (rowheight + space);
    +		xfrrows = Ndest * rowheight;
    +		from = (Nrows - Ndest) * rowheight;
     		to = 0;
     		for (int r = 0; r < xfrrows; r++)
     			for (int c = 0; c < xfrcols; c++)
     				tempbuf[(to + r) * Wdest + c] = vidbuf[(from + r) * width + c];
     	} else {
    -		xfrrows = (Nrows + 1)*(rowheight + space);
    +		xfrrows = Nrows * rowheight;
     		from = 0;
    -		to = (Ndest - Nrows) * (rowheight + space);
    +		to = (Ndest - Nrows) * rowheight;
     		for (int r = 0; r < xfrrows; r++)
     			for (int c = 0; c < xfrcols; c++)
     				tempbuf[(to + r) * Wdest + c] = vidbuf[(from + r) * width + c];
     	}
    -	
    +
     	oldbuf = vidbuf;
     	vidbuf = tempbuf;
     
    -	width = Wdest; height = Hdest;
    +	width = Wdest;
    +	height = Hdest;
     	Nrows = Ndest;
    -	yp = Ndest * (space + rowheight);
     
     	delete [] oldbuf;
     
    @@ -158,27 +155,22 @@ void Raster::resize(int x, int y, int w, int h)
     
     void Raster::draw()
     {
    -	if ((damage() & FL_DAMAGE_USER2)) {
    -		draw_box();
    -		fl_draw_image_mono(
    -			vidbuf, 
    -			x() + 2, y() + 2, 
    -			width, height,
    -			1, width );
    -	} else if ((damage() & FL_DAMAGE_USER1)) {
    -		fl_draw_image_mono(
    -			vidbuf + vidpos + Nrows * (space + rowheight) * width,
    -			x() + vidpos + 2, y() + yp + 2,
    -			numcols, rowheight, 
    -			1, width);
    -		numcols = 0;
    -	} else {
    -		draw_box();
    -		fl_draw_image_mono(
    -			vidbuf, 
    -			x() + 2, y() + 2, 
    -			width, height,
    -			1, width );
    -	}
    +	draw_box();
    +	fl_draw_image_mono(
    +		vidbuf, 
    +		x() + 2, y() + 2, 
    +		width, height, 1);
     }
     
    +int Raster::handle(int event)
    +{
    +	if (Fl::event_inside( this )) {
    +		if (event == FL_PUSH) {
    +			if (Fl::event_button() == FL_RIGHT_MOUSE) {
    +				clear();
    +				return 1;
    +			}
    +		}
    +	}
    +	return Fl_Widget::handle(event);
    +}
    diff --git a/src/waterfall/waterfall.cxx b/src/waterfall/waterfall.cxx
    index aa800fe0..907ee90a 100644
    --- a/src/waterfall/waterfall.cxx
    +++ b/src/waterfall/waterfall.cxx
    @@ -70,6 +70,8 @@
     #include "rtty.h"
     #include "flslider2.h"
     #include "debug.h"
    +#include "rigsupport.h"
    +#include "xmlrpc.h"
     
     using namespace std;
     
    @@ -255,7 +257,7 @@ inline void WFdisp::makeMarker_(int width, const RGB* color, int freq, const RGB
     	if (marker_mode >= MODE_MT63_500S && marker_mode <= MODE_MT63_2000L)
     			bw_upper = (int)(width * 31 / 32);
     
    -	if (marker_mode == MODE_FSQ)
    +	if (marker_mode == MODE_FSQ || marker_mode == MODE_IFKP)
     			bw_upper = (int)(width * 32 / 33);
     
     	if (bw_lower + static_cast(freq+0.5) < 0)
    @@ -305,7 +307,7 @@ void WFdisp::makeMarker()
     
     	makeMarker_(marker_width, &RGBmarker, carrierfreq, clrMin, clrM, clrMax);
     
    -	if (unlikely(active_modem->freqlocked())) {
    +	if (unlikely(active_modem->freqlocked() || mode == MODE_FSQ)) {
     		int txfreq = static_cast(active_modem->get_txfreq());
     		adjust_color_inv(RGBmarker.R, RGBmarker.G, RGBmarker.B, FL_BLACK, FL_RED);
     		makeMarker_( static_cast(bandwidth / 2.0 + 1),
    @@ -335,7 +337,7 @@ void WFdisp::makeMarker()
     	int bw_hi = marker_width;
     	if (mode >= MODE_MT63_500S && mode <= MODE_MT63_2000L)
     		bw_hi = bw_hi * 31 / 32;
    -	if (mode == MODE_FSQ) bw_hi = bw_hi * 32 / 33;
    +	if (mode == MODE_FSQ || mode == MODE_IFKP) bw_hi = bw_hi * 32 / 33;
     
     	for (int y = 0; y < WFMARKER - 2; y++) {
     		int incr = y * scale_width;
    @@ -650,28 +652,27 @@ void WFdisp::sig_data( double *sig, int len, int sr )
     update_freq:
     	static char szFrequency[14];
     	if (active_modem && rfc != 0) { // use a boolean for the waterfall
    -		int cwoffset = 0;
    -		int rttyoffset = 0;
    +		int offset = 0;
    +		double afreq = active_modem->get_txfreq();
     		trx_mode mode = active_modem->get_mode();
     		if (mode == MODE_RTTY && progdefaults.useMARKfreq) {
    -			rttyoffset = (progdefaults.rtty_shift < rtty::numshifts ?
    +			offset = (progdefaults.rtty_shift < rtty::numshifts ?
     				  rtty::SHIFT[progdefaults.rtty_shift] :
     				  progdefaults.rtty_custom_shift);
    -			rttyoffset /= 2;
    -			if (active_modem->get_reverse()) rttyoffset *= -1;
    +			offset /= 2;
    +			if (active_modem->get_reverse()) offset *= -1;
     		}
     		string testmode = qso_opMODE->value();
    -		if (testmode == "CW" or testmode == "CWR") {
    -			cwoffset = progdefaults.CWsweetspot;
    -			usb = ! (progdefaults.CWIsLSB ^ (testmode == "CWR"));
    -		}
    +		usb = !ModeIsLSB(testmode);
    +		if (testmode.find("CW") != string::npos)
    +			afreq = 0;//-progdefaults.CWsweetspot;
     		if (mode == MODE_ANALYSIS) {
    -			dfreq = active_modem->track_freq();
    +			dfreq = 0;
     		} else {
     			if (usb)
    -				dfreq = rfc + active_modem->get_txfreq() - cwoffset + rttyoffset;
    +				dfreq = rfc + afreq + offset;
     			else
    -				dfreq = rfc - active_modem->get_txfreq() + cwoffset - rttyoffset;
    +				dfreq = rfc - afreq - offset;
     		}
     		snprintf(szFrequency, sizeof(szFrequency), "%-.3f", dfreq / 1000.0);
     	} else {
    @@ -805,10 +806,9 @@ void WFdisp::drawScale() {
     		else {
     		    int cwoffset = 0;
     		    string testmode = qso_opMODE->value();
    -		    if (testmode == "CW" or testmode == "CWR") {
    -				cwoffset = ( progdefaults.CWOffset ? progdefaults.CWsweetspot : 0 );
    -				usb = ! (progdefaults.CWIsLSB ^ (testmode == "CWR"));
    -		    }
    +		    usb = !ModeIsLSB(testmode);
    +			if (testmode.find("CW") != string::npos)
    +				cwoffset = progdefaults.CWsweetspot;
     			if (usb)
     				fr = (rfc - (rfc%500))/1000.0 + 0.5*i - cwoffset/1000.0;
     			else
    @@ -888,7 +888,7 @@ case Step: for (int row = 0; row < image_height; row++) { \
     		trx_mode mode = active_modem->get_mode();
     		if (mode >= MODE_MT63_500S && mode <= MODE_MT63_2000L)
     			bw_hi = bw_hi * 31 / 32;
    -		if (mode == MODE_FSQ) {
    +		if (mode == MODE_FSQ || mode == MODE_IFKP) {
     			bw_hi = bw_lo = 69 * bandwidth / 100;
     		}
     		RGBI  *pos1 = fft_img + (carrierfreq - offset - bw_lo) / step;
    @@ -957,7 +957,7 @@ void WFdisp::drawcolorWF() {
     		int bw_hi = bandwidth / 2;
     		if (mode >= MODE_MT63_500S && mode <= MODE_MT63_2000L)
     			bw_hi = bw_hi * 31 / 32;
    -		if (mode == MODE_FSQ) bw_hi = bw_hi * 32 / 33;
    +		if (mode == MODE_FSQ || mode == MODE_IFKP) bw_hi = bw_hi * 32 / 33;
     		RGBI  *pos0 = (fft_img + cursorpos);
     		RGBI  *pos1 = (fft_img + cursorpos - bw_lo/step);
     		RGBI  *pos2 = (fft_img + cursorpos + bw_hi/step);
    @@ -1038,7 +1038,7 @@ void WFdisp::drawspectrum() {
     		int bw_hi = bandwidth / 2;
     		if (mode >= MODE_MT63_500S && mode <= MODE_MT63_2000L)
     			bw_hi = bw_hi * 31 / 32;
    -		if (mode == MODE_FSQ) bw_hi = bw_hi * 32 / 33;
    +		if (mode == MODE_FSQ || mode == MODE_IFKP) bw_hi = bw_hi * 32 / 33;
     		uchar  *pos0 = pixmap + cursorpos;
     		uchar  *pos1 = (pixmap + cursorpos - bw_lo/step);
     		uchar  *pos2 = (pixmap + cursorpos + bw_hi/step);
    @@ -1248,6 +1248,7 @@ void xmtrcv_cb(Fl_Widget *w, void *vi)
     		}
     		else {
     			TransmitText->clear();
    +			reset_xmlchars();
     			if (arq_text_available)
     				AbortARQ();
     			if (progStatus.timer)
    diff --git a/src/wefax/wefax-pic.cxx b/src/wefax/wefax-pic.cxx
    index 5f972cc0..9019b96d 100644
    --- a/src/wefax/wefax-pic.cxx
    +++ b/src/wefax/wefax-pic.cxx
    @@ -719,14 +719,16 @@ static void wefax_cb_pic_rx_save( Fl_Widget *, void *)
     
     	const char *file_name = FSEL::saveas(_("Save image as:"), ffilter, dfname.c_str(), NULL);
     	/// Beware that no extra comments are saved here.
    -	if (file_name) {
    -		wefax_pic_rx_picture->save_png(file_name,progdefaults.WEFAX_SaveMonochrome);
    -		qso_notes( "RX:", file_name );
    -		wefax_serviceme->qso_rec_save();
    -		/// Next time, image will be saved at the same place.
    -		default_dir_set( progdefaults.wefax_save_dir, file_name );
    -		add_to_files_list( file_name );
    -	}
    +	if (!file_name) return;
    +	if (!*file_name) return;
    +
    +	wefax_pic_rx_picture->save_png(file_name,progdefaults.WEFAX_SaveMonochrome);
    +	qso_notes( "RX:", file_name );
    +	wefax_serviceme->qso_rec_save();
    +	/// Next time, image will be saved at the same place.
    +	default_dir_set( progdefaults.wefax_save_dir, file_name );
    +	add_to_files_list( file_name );
    +
     }
     
     /// Beware, might be called by another thread. Called by the GUI
    @@ -1482,10 +1484,9 @@ static void wefax_cb_pic_tx_load(Fl_Widget *, void *)
     			"Independent JPEG Group\t*.{jpg,jif,jpeg,jpe}\n"
     			"Graphics Interchange Format\t*.gif",
     			default_dir_get( progdefaults.wefax_load_dir ).c_str() );
    -	if (!fil_name) {
    -		LOG_WARN( " Cannot FSEL::select" );
    -		return ;
    -	};
    +	if (!fil_name) return;
    +	if (!*fil_name) return;
    +
     	/// Next time, image will be saved at the same place.
     	default_dir_set( progdefaults.wefax_load_dir, fil_name );
     	wefax_load_image(fil_name);
    diff --git a/src/wefax/wefax.cxx b/src/wefax/wefax.cxx
    index 03462a72..c35d3543 100644
    --- a/src/wefax/wefax.cxx
    +++ b/src/wefax/wefax.cxx
    @@ -1129,7 +1129,7 @@ public:
     				// So we trash the image.
     				// TODO: It is done too many times: SOMETIMES THE MESSAGE IS REPEATED HUNDREDTH.
     				// crr8row continues to grow although it makes no sense.
    -				LOG_INFO("Flushing dummy image m_imag_corr_max=%f crr_row=%d 200 lines.",
    +				LOG_DEBUG("Flushing dummy image m_imag_corr_max=%f crr_row=%d 200 lines.",
     					m_imag_corr_max, crr_row );
     				static const char * garbage_200 = GARBAGE_STR ".200";
     				*stop_code = garbage_200;
    @@ -1137,7 +1137,7 @@ public:
     				stable_state = RXAPTSTOP ;
     			} else if( ( m_imag_corr_max < 0.20 ) && ( crr_row > 500 ) ) {
     				// If the max line-to-line correlation still low for a bigger image.
    -				LOG_INFO("Flushing dummy image m_imag_corr_max=%f crr_row=%d 500 lines.",
    +				LOG_DEBUG("Flushing dummy image m_imag_corr_max=%f crr_row=%d 500 lines.",
     					m_imag_corr_max, crr_row );
     				static const char * garbage_500 = GARBAGE_STR ".500";
     				*stop_code = garbage_500;
    @@ -1207,7 +1207,7 @@ public:
     		if( reset_afc ) {
     			/// Displays the message only once.
     			if( prev_row != -1 ) {
    -				LOG_INFO("Resetting AFC total_img_rows=%d",total_img_rows);
    +				LOG_DEBUG("Resetting AFC total_img_rows=%d",total_img_rows);
     			}
     			prev_row = -1 ;
     			total_img_rows = 0 ;
    diff --git a/src/widgets/FTextRXTX.cxx b/src/widgets/FTextRXTX.cxx
    index f3bcfc39..8f69ea51 100644
    --- a/src/widgets/FTextRXTX.cxx
    +++ b/src/widgets/FTextRXTX.cxx
    @@ -448,6 +448,7 @@ int FTextRX::handle_qso_data(int start, int end)
     			*(s + offsets.rm_eo) = '\0';
     			inpCall->value(p);
     			log_callback(inpCall);
    +			Fl::copy(p, strlen(p), 1);  // copy to clipboard
     		} else {
     			inpXchgIn->position(inpXchgIn->size());
     			if (inpXchgIn->size()) inpXchgIn->insert(" ", 1);
    @@ -464,6 +465,7 @@ int FTextRX::handle_qso_data(int start, int end)
     			p = s + offsets.rm_so;
     			*(s + offsets.rm_eo) = '\0';
     			target = inpCall;
    +			Fl::copy(p, strlen(p), 1);  // copy to clipboard
     		}
     		else if (count_if(s, s + strlen(s), static_cast(isdigit)))
     			target = inpQth;
    @@ -693,9 +695,9 @@ const char* FTextRX::dxcc_lookup_call(int x, int y)
     	    QRB::qrb(lon1, lat1, lon2, lat2, &distance, &azimuth) == QRB::QRB_OK) {
     			if (progdefaults.us_units) {
     				stip << "QTE " << fixed << setprecision(0) << azimuth << '\260' << " ("
    -					<< QRB::azimuth_long_path(azimuth) << '\260' << ")  QRB " 
    +					<< QRB::azimuth_long_path(azimuth) << '\260' << ")  QRB "
     					<< distance * 0.62168188 << "mi"<< " (" <<
    -					QRB::distance_long_path(distance) * 0.62168188 << 
    +					QRB::distance_long_path(distance) * 0.62168188 <<
     					"mi)\n";
     			}
     			else {
    @@ -762,8 +764,8 @@ void FTextRX::dxcc_tooltip(void* obj)
     Fl_Menu_Item FTextTX::menu[] = {
     	{ icons::make_icon_label(_("Transmit"), tx_icon), 0, 0, 0, 0, _FL_MULTI_LABEL },
     	{ icons::make_icon_label(_("Receive"), rx_icon), 0, 0, 0, 0, _FL_MULTI_LABEL },
    -	{ icons::make_icon_label(_("Abort"), process_stop_icon), 0, 0, 0, 0, _FL_MULTI_LABEL },
    -	{ icons::make_icon_label(_("Send image..."), image_icon), 0, 0, 0, FL_MENU_DIVIDER, _FL_MULTI_LABEL },
    +	{ icons::make_icon_label(_("Abort"), process_stop_icon), 0, 0, 0, FL_MENU_DIVIDER, _FL_MULTI_LABEL },
    +	{ icons::make_icon_label(_("Send image..."), image_icon), 0, 0, 0, 0, _FL_MULTI_LABEL },
     
     	{ 0 }, // EDIT_MENU_CUT
     	{ 0 }, // EDIT_MENU_COPY
    @@ -772,6 +774,92 @@ Fl_Menu_Item FTextTX::menu[] = {
     	{ 0 }, // EDIT_MENU_READ
     	{ 0 }, // EDIT_MENU_WRAP
     
    +	{ _("Spec Char"), 0, 0, 0, FL_SUBMENU, FL_NORMAL_LABEL },
    +		{ "¢ - cent", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +		{ "£ - pound", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +		{ "µ - micro", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +		{ "° - degree", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +		{ "¿ - iques", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +		{ "× - times", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +		{ "÷ - divide", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +		{ _("A"), 0, 0, 0, FL_SUBMENU, FL_NORMAL_LABEL },
    +			{ "À - grave", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "à - grave", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "Á - acute", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "á - acute", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "Â - circ", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "â - circ", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "Ã - tilde", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "ã - tilde", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "Ä - umlaut", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "ä - umlaut", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "Å - ring", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "å - ring", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "Æ - aelig", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "æ - aelig", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{0,0,0,0,0,0,0,0,0},
    +		{ _("E"), 0, 0, 0, FL_SUBMENU, FL_NORMAL_LABEL },
    +			{ "È - grave", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "è - grave", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "É - acute", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "é - acute", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "Ê - circ", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "Ê - circ", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "Ë - umlaut", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "ë - umlaut", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{0,0,0,0,0,0,0,0,0},
    +		{ _("I"), 0, 0, 0, FL_SUBMENU, FL_NORMAL_LABEL },
    +			{ "Ì - grave", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "ì - grave", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "Í - acute", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "í - acute", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "Î - circ", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "î - circ", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "Ï - umlaut", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "ï - umlaut", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{0,0,0,0,0,0,0,0,0},
    +		{ _("N"), 0, 0, 0, FL_SUBMENU, FL_NORMAL_LABEL },
    +			{ "Ñ - tilde", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "ñ - tilde", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{0,0,0,0,0,0,0,0,0},
    +		{ _("O"), 0, 0, 0, FL_SUBMENU, FL_NORMAL_LABEL },
    +			{ "Ò - grave", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "ò - grave", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "Ó - acute", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "ó - acute", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "Ô - circ", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "ô - circ", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "Õ - tilde", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "õ - tilde", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "Ö - umlaut", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "ö - umlaut", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "Ø - slash", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "ø - slash", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{0,0,0,0,0,0,0,0,0},
    +		{ _("U"), 0, 0, 0, FL_SUBMENU, FL_NORMAL_LABEL },
    +			{ "Ù - grave", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "ù - grave", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "Ú - acute", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "ú - acute", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "Û - circ", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "û - circ", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "Ü - umlaut", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "ü - umlaut", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{0,0,0,0,0,0,0,0,0},
    +		{ _("Y"), 0, 0, 0, FL_SUBMENU, FL_NORMAL_LABEL },
    +			{ "Ý - acute", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "ý - acute", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "ÿ - umlaut", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{0,0,0,0,0,0,0,0,0},
    +		{ _("Other"), 0, 0, 0, FL_SUBMENU, FL_NORMAL_LABEL },
    +			{ "ß - szlig", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "Ç - cedil", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "ç - cedil", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "Ð - eth", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "ð - eth", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "Þ - thorn", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{0,0,0,0,0,0,0,0,0},
    +		{0,0,0,0,0,0,0,0,0},
     	{ 0 }
     };
     
    @@ -811,7 +899,7 @@ int FTextTX::handle(int event)
     	case FL_KEYBOARD:
     		if (active_modem->get_mode() == MODE_FSQ) {
     			if (Fl::event_key() == FL_Enter || Fl::event_key() == FL_KP_Enter) {
    -				fsq_transmit(active_modem);
    +				fsq_transmit(0);
     				return 1;
     			}
     		}
    @@ -1279,8 +1367,16 @@ void FTextTX::menu_cb(size_t item)
      			abort_tx();
       		break;
     	case TX_MENU_MFSK16_IMG:
    -		showTxViewer(0, 0);
    +		{
    +			trx_mode md = active_modem->get_mode();
    +		if (md == MODE_IFKP)
    +			ifkp_showTxViewer();
    +		else if (md >= MODE_THOR_FIRST && md <= MODE_THOR_LAST)
    +			thor_showTxViewer();
    +		else
    +			showTxViewer(0, 0);
     		break;
    +		}
     	case TX_MENU_CLEAR:
     		clear();
     		break;
    @@ -1302,6 +1398,9 @@ void FTextTX::menu_cb(size_t item)
     	case TX_MENU_WRAP:
     		set_word_wrap(!wrap, true);
     		break;
    +	default:
    +		if (FTextTX::menu[item].flags == 0) // not an FL_SUB_MENU
    +			add(FTextTX::menu[item].text[0]); add(FTextTX::menu[item].text[1]);
     	}
     }
     
    diff --git a/src/widgets/FTextView.cxx b/src/widgets/FTextView.cxx
    index 0f1c14a1..e2d4f2db 100644
    --- a/src/widgets/FTextView.cxx
    +++ b/src/widgets/FTextView.cxx
    @@ -46,6 +46,7 @@
     #include "ascii.h"
     #include "icons.h"
     #include "gettext.h"
    +#include "macros.h"
     
     #include "FTextView.h"
     
    @@ -352,7 +353,7 @@ void FTextBase::saveFile(void)
     
     		char *p1, *p2, *text = tbuf->text();
     		for (p1 = p2 = text; *p1; p1 = p2) {
    -			while (*p2 != '\0' && *p2 != '\n')
    +			while (*p2 != '\0' && *p2 != '\r')
     				p2++;
     			if (*p2 == '\n') {
     				*p2 = '\0';
    @@ -466,6 +467,10 @@ void FTextBase::reset_styles(int set)
     	set_style(CTRL, FL_HELVETICA, FL_NORMAL_SIZE, FL_DARK_GREEN, set);
     	set_style(SKIP, FL_HELVETICA, FL_NORMAL_SIZE, FL_BLUE, set);
     	set_style(ALTR, FL_HELVETICA, FL_NORMAL_SIZE, FL_DARK_MAGENTA, set);
    +	set_style(FSQ_TX, FL_HELVETICA, FL_NORMAL_SIZE, FL_RED, set);
    +	set_style(FSQ_DIR, FL_HELVETICA, FL_NORMAL_SIZE, FL_BLUE, set);
    +	set_style(FSQ_UND, FL_HELVETICA, FL_NORMAL_SIZE, FL_DARK_GREEN, set);
    +
     }
     
     // ----------------------------------------------------------------------------
    @@ -803,8 +808,33 @@ int FTextEdit::handle_dnd_drop(void)
     			len -= 7;
     		}
     #endif
    +
    +#ifndef BUILD_FLARQ
    +	if ((text.find("jpg") != string::npos) ||
    +		(text.find("JPG") != string::npos) ||
    +		(text.find("jpeg") != string::npos) ||
    +		(text.find("JPEG") != string::npos) ||
    +		(text.find("png") != string::npos) ||
    +		(text.find("PNG") != string::npos) ||
    +		(text.find("bmp") != string::npos) ||
    +		(text.find("BMP") != string::npos) ) {
    +
    +		LOG_INFO("DnD image %s", text.c_str());
    +
    +		if ((p = text.find("file://")) != string::npos)
    +			text.erase(0, p + strlen("file://"));
    +		if ((p = text.find('\r')) != string::npos)
    +			text.erase(p);
    +		if ((p = text.find('\n')) != string::npos)
    +			text.erase(p);
    +		if (text[text.length()-1] == 0) text.erase(text.length() -1);
    +		TxQueINSERTIMAGE(text);
    +		return 1;
    +	}
    +#endif
    +
     // paste everything verbatim if we cannot read the first file
    -LOG_INFO("DnD file %s", text.c_str());
    +		LOG_INFO("DnD file %s", text.c_str());
     		if (readFile(text.c_str()) == -1 && len == text.length())
     			return FTextBase::handle(FL_PASTE);
     		text.erase(0, p + sizeof(sep) - 1);
    diff --git a/src/widgets/Panel.cxx b/src/widgets/Panel.cxx
    index 1d4039a1..c2fc0278 100644
    --- a/src/widgets/Panel.cxx
    +++ b/src/widgets/Panel.cxx
    @@ -34,6 +34,7 @@
     
     // Drag the edges that were initially at oldx,oldy to newx,newy:
     // pass -1 as oldx or oldy to disable drag in that direction:
    +//#define DEVEL_DEBUG 1
     
     int Panel::orgx()
     {
    diff --git a/src/widgets/dock_gp.cxx b/src/widgets/dock_gp.cxx
    new file mode 100644
    index 00000000..fe161e95
    --- /dev/null
    +++ b/src/widgets/dock_gp.cxx
    @@ -0,0 +1,59 @@
    +#include 
    +
    +#include 
    +
    +#include "dock_gp.h"
    +#include "dropwin.h"
    +
    +// basic fltk constructors
    +dockgroup::dockgroup(int x, int y, int w, int h, const char *l) 
    +  : Fl_Group(x, y, w, h, l) 
    +{
    +	pack = new Fl_Pack(x, y, w, h);
    +	pack->type(Fl_Pack::HORIZONTAL);
    +	children = 0;
    +	resizable(pack);
    +	vis_h = h;
    +}
    +
    +void dockgroup::add(Fl_Widget *grp)
    +{
    +	int wd = w();
    +	int ht = h();
    +	
    +	// if the dock is "closed", open it back up
    +	if (ht < vis_h)
    +	{
    +		dropwin *dw = (dropwin *)win;
    +		size(wd, vis_h);
    +		pack->size(wd, vis_h);
    +		dw->dock_resize(ht - vis_h);
    +	}
    +	pack->add(grp); 
    +	pack->resizable(grp);
    +	children++;
    +	if (callback() != NULL) do_callback();
    +}
    +
    +void dockgroup::remove(Fl_Widget *grp)
    +{
    +	int wd = w();
    +	pack->remove(grp);
    +	children--;
    +	pack->resizable(pack->child(pack->children() - 1));
    +	// If the dock is empty, close it down
    +	if (children <= 0) {
    +		dropwin *dw = (dropwin *)win;
    +		children = 0;
    +		size(wd, 2);
    +		dw->dock_resize(vis_h - 2);
    +	}
    +	if (callback() != NULL) do_callback();
    +}
    +
    +char *dockgroup::dock_check(void)
    +{
    +	static char szcheck[50];
    +	snprintf(szcheck, sizeof(szcheck), "DG: %d - %dx%d", children, pack->w(), pack->h());
    +	return szcheck;
    +}
    diff --git a/src/widgets/drag_btn.cxx b/src/widgets/drag_btn.cxx
    new file mode 100644
    index 00000000..0a488d19
    --- /dev/null
    +++ b/src/widgets/drag_btn.cxx
    @@ -0,0 +1,144 @@
    +#include 
    +
    +#include 
    +#include 
    +#include 
    +
    +#include "drag_btn.h"
    +#include "dock_events.h"
    +#include "toolgrp.h"
    +
    +static const char * grip_tile_xpm[] = {
    +"6 6 4 1",
    +" 	c None",
    +".	c #FCFEFC",
    +"+	c #D4D6D4",
    +"@	c #9C9294",
    +".+++++",
    +"+@+.++",
    +"++++@+",
    +".+++++",
    +"+@+.++",
    +"++++@+"};
    +
    +drag_btn::drag_btn(int x, int y, int w, int h, const char *l)
    + : Fl_Box(x, y, w, h, l)
    +{
    +	was_docked = 0; // Assume we have NOT just undocked...
    +}
    +
    +void drag_btn::draw()
    +{
    +	int xo = x();
    +	int yo = y();
    +
    +	// Draw the button box
    +	draw_box(box(), color());
    +
    +	// set the clip region so we only "tile" the box
    +	fl_push_clip(xo+1, yo+1, w()-3, h()-3);
    +
    +	// tile the pixmap onto the button face... there must be a better way
    +	for(int i = 2; i <= w(); i += 6)
    +		for(int j = 2; j <= h(); j += 6)
    +			fl_draw_pixmap(grip_tile_xpm, (xo + i), (yo + j));
    +
    +	fl_pop_clip();
    +} // draw
    +
    +int drag_btn::handle(int event)
    +{
    + 	toolgrp *tg = (toolgrp *)parent();
    +	int docked = tg->docked();
    +	int ret = 0;
    +	int x2 = 0, y2 = 0;
    +	int cx, cy;
    +
    +	// If we are not docked, deal with dragging the toolwin around
    +	if (!docked) {
    +		// get the enclosing parent widget
    +		Fl_Widget *tw = (Fl_Widget *)(tg->parent());
    +		if(!tw) return 0;
    +
    +		switch (event) {
    +			case FL_PUSH: // downclick in button creates cursor offsets
    +				x1 = Fl::event_x_root();
    +				y1 = Fl::event_y_root();
    +				xoff = tw->x() - x1;
    +				yoff = tw->y() - y1;
    +				ret = 1;
    +				break;
    +			case FL_DRAG: // drag the button (and its parent window) around the screen
    +				if (was_docked) {
    +					// Need to init offsets, we probably got here following a drag
    +					// from the dock, so the PUSH (above) will not have happened.
    +					was_docked = 0;
    +					x1 = Fl::event_x_root();
    +					y1 = Fl::event_y_root();
    +					xoff = tw->x() - x1;
    +					yoff = tw->y() - y1;
    +				}
    +				tw->position(xoff + Fl::event_x_root(), yoff + Fl::event_y_root());
    +				tw->redraw();
    +				ret = 1;
    +				break;
    +
    +			case FL_RELEASE:
    +				cx = Fl::event_x_root(); // Where did the release occur...
    +				cy = Fl::event_y_root();
    +				x2 = x1 - cx;
    +				y2 = y1 - cy;
    +				x2 = (x2 > 0) ? x2 : (-x2);
    +				y2 = (y2 > 0) ? y2 : (-y2);
    +				// See if anyone is able to accept a dock with this widget
    +			// How to find the dock window? Search 'em all for now...
    +				for(Fl_Window *win = Fl::first_window(); win; win = Fl::next_window(win)) {
    +					// Get the co-ordinates of each window
    +					int ex = win->x_root();
    +					int ey = win->y_root();
    +					// Are we inside the boundary of the window?
    +					if (win->visible() &&
    +						abs(cx - ex) < DROP_REGION_HEIGHT &&
    +						abs(cy - ey) < DROP_REGION_HEIGHT) {
    +						// Send the found window a message that we want to dock with it.
    +						if(Fl::handle(FX_DROP_EVENT, win)) {
    +							tg->dock_grp(tg);
    +							break;
    +						}
    +					}
    +				}
    +				//show();
    +				ret = 1;
    +				break;
    +			default:
    +				break;
    +		}
    +		return(ret);
    +	}
    +
    +	// OK, so we must be docked - are we being dragged out of the dock?
    +	switch(event) {
    +		case FL_PUSH: // downclick in button creates cursor offsets
    +			x1 = Fl::event_x_root();
    +			y1 = Fl::event_y_root();
    +			ret = 1;
    +			break;
    +		case FL_DRAG:
    +			// IF the drag has moved further than the drag_min distance
    +			// THEN invoke an un-docking
    +			x2 = Fl::event_x_root() - x1;
    +			y2 = Fl::event_y_root() - y1;
    +			x2 = (x2 > 0) ? x2 : (-x2);
    +			y2 = (y2 > 0) ? y2 : (-y2);
    +			if ((x2 > 10) || (y2 > 10)) {
    +				tg->undock_grp((void *)tg); // undock the window
    +				was_docked = -1; // note that we *just now* undocked
    +			}
    +			ret = 1;
    +			break;
    +		default:
    +			break;
    +	}
    +	return ret;
    +} // handle
    +
    diff --git a/src/widgets/dropwin.cxx b/src/widgets/dropwin.cxx
    new file mode 100644
    index 00000000..17599e81
    --- /dev/null
    +++ b/src/widgets/dropwin.cxx
    @@ -0,0 +1,67 @@
    +#include 
    +#include 
    +
    +#include "dropwin.h"
    +#include "dock_events.h"
    +
    +// basic fltk constructors
    +dropwin::dropwin(int x, int y, int w, int h, const char *l)
    +  : Fl_Double_Window(x, y, w, h, l)
    +{
    +	init_dropwin();
    +}
    +
    +dropwin::dropwin(int w, int h, const char *l)
    +  : Fl_Double_Window(w, h, l)
    +{
    +	init_dropwin();
    +}
    +
    +void dropwin::init_dropwin(void)
    +{
    +	dock = (dockgroup *)0;
    +	workspace = (Fl_Group *)0;
    +	Wdrop = DROP_REGION_HEIGHT;
    +	Hdrop = DROP_REGION_HEIGHT;
    +}
    +
    +void dropwin::dock_resize(int delta_h)
    +{
    +	int xo = workspace->x();
    +	int yo = workspace->y();
    +	int wo = workspace->w();
    +	int ho = workspace->h();
    +
    +	yo = yo - delta_h;
    +	ho = ho + delta_h;
    +	workspace->resize(xo, yo, wo, ho);
    +	workspace->redraw();
    +	redraw();
    +}
    +
    +
    +int dropwin::handle(int evt)
    +{
    +	int res = Fl_Double_Window::handle(evt);
    +
    +	// Is this a dock_drop event?
    +	if((evt == FX_DROP_EVENT) && (dock)) {
    +		// Did the drop happen on us?
    +		// Get our co-ordinates
    +		int ex = x_root() + dock->x();
    +		int ey = y_root() + dock->y();
    +		// get the drop event co-ordinates
    +		int cx = Fl::event_x_root();
    +		int cy = Fl::event_y_root();
    +		// Is the event inside the boundary of this window?
    +		if (visible() &&
    +			abs(cx - ex) < Wdrop &&
    +			abs(cy - ey) < Hdrop) {
    +			res = 1;
    +		} else {
    +			res = 0;
    +		}
    +	}
    +	return res;
    +}
    +
    diff --git a/src/widgets/flinput2.cxx b/src/widgets/flinput2.cxx
    index 35cf9135..94f125e7 100644
    --- a/src/widgets/flinput2.cxx
    +++ b/src/widgets/flinput2.cxx
    @@ -34,6 +34,7 @@
     #include "icons.h"
     #include "flinput2.h"
     #include "gettext.h"
    +#include "debug.h"
     
     
     enum { OP_UNDO, OP_CUT, OP_COPY, OP_PASTE, OP_DELETE, OP_CLEAR, OP_SELECT_ALL };
    @@ -46,11 +47,96 @@ static Fl_Menu_Item cmenu[] = {
     	{ icons::make_icon_label(_("Delete"), trash_icon), 0, 0, 0, 0, _FL_MULTI_LABEL },
     	{ icons::make_icon_label(_("Clear"), edit_clear_icon), 0, 0, 0, FL_MENU_DIVIDER, _FL_MULTI_LABEL },
     	{ icons::make_icon_label(_("Select All"), edit_select_all_icon), 0, 0, 0, 0, _FL_MULTI_LABEL },
    -	{ 0 }
    +	{ _("Spec Char"), 0, 0, 0, FL_SUBMENU, FL_NORMAL_LABEL },
    +		{ "¢ - cent", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +		{ "£ - pound", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +		{ "µ - micro", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +		{ "° - degree", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +		{ "¿ - iques", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +		{ "× - times", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +		{ "÷ - divide", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +		{ _("A"), 0, 0, 0, FL_SUBMENU, FL_NORMAL_LABEL },
    +			{ "À - grave", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "à - grave", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "Á - acute", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "á - acute", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "Â - circ", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "â - circ", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "Ã - tilde", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "ã - tilde", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "Ä - umlaut", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "ä - umlaut", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "Å - ring", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "å - ring", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "Æ - aelig", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "æ - aelig", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{0,0,0,0,0,0,0,0,0},
    +		{ _("E"), 0, 0, 0, FL_SUBMENU, FL_NORMAL_LABEL },
    +			{ "È - grave", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "è - grave", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "É - acute", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "é - acute", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "Ê - circ", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "Ê - circ", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "Ë - umlaut", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "ë - umlaut", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{0,0,0,0,0,0,0,0,0},
    +		{ _("I"), 0, 0, 0, FL_SUBMENU, FL_NORMAL_LABEL },
    +			{ "Ì - grave", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "ì - grave", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "Í - acute", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "í - acute", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "Î - circ", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "î - circ", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "Ï - umlaut", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "ï - umlaut", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{0,0,0,0,0,0,0,0,0},
    +		{ _("N"), 0, 0, 0, FL_SUBMENU, FL_NORMAL_LABEL },
    +			{ "Ñ - tilde", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "ñ - tilde", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{0,0,0,0,0,0,0,0,0},
    +		{ _("O"), 0, 0, 0, FL_SUBMENU, FL_NORMAL_LABEL },
    +			{ "Ò - grave", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "ò - grave", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "Ó - acute", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "ó - acute", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "Ô - circ", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "ô - circ", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "Õ - tilde", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "õ - tilde", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "Ö - umlaut", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "ö - umlaut", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "Ø - slash", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "ø - slash", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{0,0,0,0,0,0,0,0,0},
    +		{ _("U"), 0, 0, 0, FL_SUBMENU, FL_NORMAL_LABEL },
    +			{ "Ù - grave", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "ù - grave", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "Ú - acute", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "ú - acute", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "Û - circ", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "û - circ", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "Ü - umlaut", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "ü - umlaut", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{0,0,0,0,0,0,0,0,0},
    +		{ _("Y"), 0, 0, 0, FL_SUBMENU, FL_NORMAL_LABEL },
    +			{ "Ý - acute", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "ý - acute", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "ÿ - umlaut", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{0,0,0,0,0,0,0,0,0},
    +		{ _("Other"), 0, 0, 0, FL_SUBMENU, FL_NORMAL_LABEL },
    +			{ "ß - szlig", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "Ç - cedil", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "ç - cedil", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "Ð - eth", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "ð - eth", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{ "Þ - thorn", 0, 0, 0, 0, FL_NORMAL_LABEL },
    +			{0,0,0,0,0,0,0,0,0},
    +		{0,0,0,0,0,0,0,0,0},
    +	{0,0,0,0,0,0,0,0,0}
     };
     static bool cmenu_init = false;
     
    -
     Fl_Input2::Fl_Input2(int x, int y, int w, int h, const char* l)
     	: Fl_Input(x, y, w, h, l)
     {
    @@ -60,13 +146,60 @@ Fl_Input2::Fl_Input2(int x, int y, int w, int h, const char* l)
     				icons::set_icon_label(&cmenu[i]);
     		cmenu_init = true;
     	}
    +	ascii_cnt = 0; // restart the numeric keypad entries.
    +	ascii_chr = 0;
    +	utf8text = NULL;
     }
     
    +//----------------------------------------------------------------------
    +/// Composes ascii characters and adds them to the Fl_Input2 buffer.
    +/// Control characters are inserted with the CTRL style. Values larger than 127
    +/// (0x7f) are ignored. We cannot really add NULs for the time being.
    +/// 
    +/// @param key A digit character
    +///
    +/// @return 1
    +///
    +int Fl_Input2::handle_key_ascii(int key)
    +{
    +	if (key >= FL_KP) key -= FL_KP;
    +	key -= '0';
    +	ascii_cnt++;
    +	ascii_chr *= 10;
    +	ascii_chr += key;
    +	if (ascii_cnt == 3) {
    +		if (ascii_chr < 0x100) {
    +			utf8text = new char[fl_utf8bytes(ascii_chr) + 1];
    +			utf8cnt = fl_utf8encode(ascii_chr, utf8text);
    +			return 1;
    +		}
    +		ascii_cnt = ascii_chr = 0;
    +	}
    +
    +	return 0;
    +}
    +
    +//----------------------------------------------------------------------
     int Fl_Input2::handle(int event)
     {
     	switch (event) {
     	case FL_KEYBOARD: {
     		int b = Fl::event_key();
    +
    +		if ((Fl::event_state() & FL_CTRL) && (isdigit(b) || isdigit(b - FL_KP))) {
    +			if (handle_key_ascii(b)) {
    +				if (utf8text) {
    +					insert(utf8text, utf8cnt);
    +					delete utf8text;
    +				}
    +				ascii_cnt = 0;
    +				ascii_chr = 0;
    +			}
    +			return 1;
    +		}
    +		ascii_cnt = 0;
    +		ascii_chr = 0;
    +
     		int p = position();
     		// stop the move-to-next-field madness, we have Tab for that!
     		if (unlikely((b == FL_Left && p == 0) || (b == FL_Right && p == size()) ||
    @@ -176,6 +309,8 @@ int Fl_Input2::handle(int event)
     	case OP_SELECT_ALL:
     		position(0, size());
     		break;
    +	default:
    +		insert(m->text, 1);
     	}
     
     	return 1;
    diff --git a/src/widgets/flmisc.cxx b/src/widgets/flmisc.cxx
    index f4343639..becb93bb 100644
    --- a/src/widgets/flmisc.cxx
    +++ b/src/widgets/flmisc.cxx
    @@ -253,7 +253,7 @@ Mode_Browser::Mode_Browser(void)
     	int bw = 80, bh = 20, pad = 2;
     
     	modes = new Fl_Check_Browser(pad, pad, w() - pad, h() - 2 * (bh + 2 * pad));
    -	for (int i = 0; i < NUM_RXTX_MODES; i++)
    +	for (int i = 0; i < NUM_MODES; i++)
     		modes->add(mode_info[i].name);
     	modes->callback(modes_cb, this);
     	modes->when(FL_WHEN_CHANGED);
    diff --git a/src/widgets/picture.cxx b/src/widgets/picture.cxx
    index 277d5864..3d0685fb 100644
    --- a/src/widgets/picture.cxx
    +++ b/src/widgets/picture.cxx
    @@ -24,6 +24,7 @@
     // along with this program.  If not, see .
     // ----------------------------------------------------------------------------
     
    +#include 
     #include 
     
     #ifdef __MINGW32__
    @@ -45,7 +46,7 @@
     #include 
     #include 
     
    -#include 
    +//#include 
     #include 
     
     #include "fl_digi.h"
    @@ -72,6 +73,7 @@ picture::picture (int X, int Y, int W, int H, int bg_col) :
     	binary = false ;
     	binary_threshold = 128 ;
     	slantcorr = true;
    +	cbFunc = NULL;
     }
     
     picture::~picture()
    @@ -110,16 +112,19 @@ void picture::resize_zoom(int x, int y, int w, int h)
     	} else {
     		Fl_Widget::resize(x,y,w,h);
     	}
    +	redraw();
     }
     
     void picture::resize(int x, int y, int w, int h)
     {
    -	width = w;
    -	height = h;
    -	delete [] vidbuf;
    -	bufsize = depth * w * h;
    -	vidbuf = new unsigned char[bufsize];
    -	memset( vidbuf, background, bufsize );
    +	if (w != width || h != height) {
    +		width = w;
    +		height = h;
    +		delete [] vidbuf;
    +		bufsize = depth * w * h;
    +		vidbuf = new unsigned char[bufsize];
    +		memset( vidbuf, background, bufsize );
    +	}
     	resize_zoom(x,y,w,h);
     }
     
    @@ -382,7 +387,6 @@ void picture::draw()
     		fl_draw_image( vidbuf, x(), y(), w(), h() );
     	} else {
     		fl_draw_image( draw_cb, this, x(), y(), w(), h() );
    -		// redraw();
     	}
     }
     
    @@ -477,9 +481,12 @@ void picture::slant(int dir)
     
     int picture::handle(int event)
     {
    -	if (!slantcorr) return 0;
     	if (Fl::event_inside( this )) {
     		if (event == FL_RELEASE) {
    +			if (!slantcorr) {
    +				do_callback();
    +				return 1;
    +			}
     			int xpos = Fl::event_x() - x();
     			int ypos = Fl::event_y() - y();
     			int evb = Fl::event_button();
    @@ -487,7 +494,6 @@ int picture::handle(int event)
     				slant_corr(xpos, ypos);
     			else if (evb == 3)
     				slant_undo();
    -LOG_WARN("xpos, ypos %d, %d", xpos, ypos);
     			LOG_DEBUG("#2 %d, %d", xpos, ypos);
     			return 1;
     		}
    @@ -527,9 +533,29 @@ static FILE* open_file(const char* name, const char* suffix)
     			fp = NULL;
     		delete [] newfn;
     	}
    -	else
    -		fp = fopen(name, "wb");
    +	else {
    +		fp = fopen(name, "rb");
    +		if (fp) {
    +			fclose(fp);
    +			const int n = 5; // rename existing image files to keep up to 5 old versions
    +			ostringstream oldfn, newfn;
    +			ostringstream::streampos p;
     
    +			oldfn << name << '.';
    +			newfn << name << '.';
    +			p = oldfn.tellp();
    +
    +			for (int i = n - 1; i > 0; i--) {
    +				oldfn.seekp(p);
    +				newfn.seekp(p);
    +				oldfn << i;
    +				newfn << i + 1;
    +				rename(oldfn.str().c_str(), newfn.str().c_str());
    +			}
    +			rename(name, oldfn.str().c_str());
    +		}
    +		fp = fopen(name, "wb");
    +	}
     	return fp;
     }
     
    @@ -668,6 +694,10 @@ int picture::save_png(const char* filename, bool monochrome, const char *extra_c
     	free(text.key);
     	free(text.text);
     	png_destroy_write_struct(&png, &info);
    +
    +	fflush(fp);
    +	fsync(fileno(fp));
    +
     	fclose(fp);
     
     	return 0;
    diff --git a/src/widgets/pwrmeter.cxx b/src/widgets/pwrmeter.cxx
    index 3ff85e3d..6e23363b 100644
    --- a/src/widgets/pwrmeter.cxx
    +++ b/src/widgets/pwrmeter.cxx
    @@ -59,7 +59,7 @@ void PWRmeter::select_25W()
     	fl_font(FL_HELVETICA, labelsize());
     	meter_width = fl_width(W25_face);
     	sx = (tw - meter_width) / 2 + fl_width("|") / 2;
    -	meter_width -= fl_width("|  25");
    +	meter_width -= fl_width("|");
     }
     
     void PWRmeter::select_50W()
    @@ -69,7 +69,7 @@ void PWRmeter::select_50W()
     	fl_font(FL_HELVETICA, labelsize());
     	meter_width = fl_width(W50_face);
     	sx = (tw - meter_width) / 2 + fl_width("|") / 2;
    -	meter_width -= fl_width("|  50");
    +	meter_width -= fl_width("|");
     }
     
     void PWRmeter::select_100W()
    @@ -79,7 +79,7 @@ void PWRmeter::select_100W()
     	fl_font(FL_HELVETICA, labelsize());
     	meter_width = fl_width(W100_face);
     	sx = (tw - meter_width) / 2 + fl_width("|") / 2;
    -	meter_width -= fl_width("| 100");
    +	meter_width -= fl_width("|");
     }
     
     void PWRmeter::select_200W()
    @@ -89,7 +89,7 @@ void PWRmeter::select_200W()
     	fl_font(FL_HELVETICA, labelsize());
     	meter_width = fl_width(W200_face);
     	sx = (tw - meter_width) / 2 + fl_width("|") / 2;
    -	meter_width -= fl_width("| 200");
    +	meter_width -= fl_width("|");
     }
     
     void PWRmeter::select_auto()
    @@ -132,10 +132,10 @@ void PWRmeter::select( int sel ) {
     	redraw();
     }
     
    -const char * PWRmeter::W25_face   = "| : : : : | : : : : | : : : : | : : : : | : : : : |  25";
    -const char * PWRmeter::W50_face   = "|    :    |    :    |    :    |    :    |    :    |  50";
    -const char * PWRmeter::W100_face  = "|    |    |    |    |    |    |    |    |    |    | 100";
    -const char * PWRmeter::W200_face  = "|     :     |     :      |      :     |     :     | 200";
    +const char * PWRmeter::W25_face   = "| : : : : | : : : : | : : : : | : : : : | : : : 25|";
    +const char * PWRmeter::W50_face   = "|    :    |    :    |    :    |    :    |    :  50|";
    +const char * PWRmeter::W100_face  = "|    |    |    |    |    |    |    |    |    | 100|";
    +const char * PWRmeter::W200_face  = "|     :     |     :      |      :     |     :  200|";
     
     PWRmeter::PWRmeter(int X, int Y, int W, int H, const char* l)
     : Fl_Widget(X, Y, W, H, "")
    @@ -174,9 +174,6 @@ PWRmeter::PWRmeter(int X, int Y, int W, int H, const char* l)
     	fl_font(FL_HELVETICA, fsize);
     	meter_width = fl_width(W100_face);
     
    -//printf("widths: 25W %.0f, 50W %.0f, 100W %.0f, 200W %.0f\n",
    -//fl_width(W25_face), fl_width(W50_face), fl_width(W100_face), fl_width(W200_face));
    -
     	meter_height = fl_height();
     	label(W100_face);
     	labelfont(FL_HELVETICA);
    @@ -185,7 +182,73 @@ PWRmeter::PWRmeter(int X, int Y, int W, int H, const char* l)
     
     	sx = (tw - meter_width) / 2 + fl_width("|") / 2;
     
    -	meter_width -= fl_width("| 100");
    +	meter_width -= fl_width("|");
    +}
    +
    +void PWRmeter::resize(int X, int Y, int W, int H) {
    +	Fl_Widget::resize(X,Y,W,H);
    +
    +	bx = Fl::box_dx(box());
    +	by = Fl::box_dy(box());
    +	bw = Fl::box_dw(box());
    +	bh = Fl::box_dh(box());
    +
    +	tx = X + bx;
    +	tw = W - bw;
    +	ty = Y + by;
    +	th = H - bh;
    +
    +	const char *face;
    +	switch (select_) {
    +		case P25:
    +			face = W25_face;
    +			break;
    +		case P50:
    +			face = W50_face;
    +			break;
    +		case P100:
    +			face = W100_face;
    +			break;
    +		case P200:
    +			face = W200_face;
    +			break;
    +		case AUTO:
    +		default:
    +			face = W25_face;
    +	}
    +
    +	static int fsize = 6;
    +	fl_font(FL_HELVETICA, fsize);
    +	meter_width = fl_width(face);
    +	while ((meter_width < tw) && (fl_height() < th)) {
    +		fsize++;
    +		fl_font(FL_HELVETICA, fsize);
    +		meter_width = fl_width(face);
    +	}
    +	fsize--;
    +	fl_font(FL_HELVETICA, fsize);
    +	meter_width = fl_width(face);
    +
    +	meter_height = fl_height();
    +	label(face);
    +	labelfont(FL_HELVETICA);
    +	labelsize(fsize);
    +	labelcolor(scale_color);
    +
    +	sx = (tw - meter_width) / 2 + fl_width("|") / 2;
    +	meter_width -= fl_width("|");
    +
    +}
    +
    +int PWRmeter::handle(int event)
    +{
    +	if (Fl::event_inside( this )) {
    +		if (event == FL_RELEASE) {
    +			do_callback();
    +			return 1;
    +		}
    +	}
    +	return 0;
     }
     
     //
    diff --git a/src/widgets/smeter.cxx b/src/widgets/smeter.cxx
    index abeba00c..9cc2b69e 100644
    --- a/src/widgets/smeter.cxx
    +++ b/src/widgets/smeter.cxx
    @@ -98,6 +98,52 @@ Smeter::Smeter(int X, int Y, int W, int H, const char* l)
     	sx = (tw - meter_width) / 2;
     }
     
    +void Smeter::resize(int X, int Y, int W, int H) {
    +	Fl_Widget::resize(X,Y,W,H);
    +
    +	bx = Fl::box_dx(box());
    +	by = Fl::box_dy(box());
    +	bw = Fl::box_dw(box());
    +	bh = Fl::box_dh(box());
    +
    +	tx = X + bx;
    +	tw = W - bw;
    +	ty = Y + by;
    +	th = H - bh;
    +
    +	static int fsize = 6;
    +	fl_font(FL_HELVETICA, fsize);
    +	meter_width = fl_width(meter_face);
    +	while ((meter_width < tw) && (fl_height() < th)) {
    +		fsize++;
    +		fl_font(FL_HELVETICA, fsize);
    +		meter_width = fl_width(meter_face);
    +	}
    +	fsize--;
    +	fl_font(FL_HELVETICA, fsize);
    +	meter_width = fl_width(meter_face);
    +	meter_height = fl_height();
    +	label(meter_face);
    +	labelfont(FL_HELVETICA);
    +	labelsize(fsize);
    +	labelcolor(scale_color);
    +
    +	meter_width -= fl_width("|");
    +	sx = (tw - meter_width) / 2;
    +}
    +
    +int Smeter::handle(int event)
    +{
    +	if (Fl::event_inside( this )) {
    +		if (event == FL_RELEASE) {
    +			do_callback();
    +			return 1;
    +		}
    +	}
    +	return 0;
    +}
    +
    +
     //
     // End of Smeter.cxx
     //
    diff --git a/src/widgets/toolgrp.cxx b/src/widgets/toolgrp.cxx
    new file mode 100644
    index 00000000..ec3f0372
    --- /dev/null
    +++ b/src/widgets/toolgrp.cxx
    @@ -0,0 +1,204 @@
    +#include 
    +
    +/* fltk includes */
    +#include 
    +
    +#include "toolgrp.h"
    +#include "toolwin.h"
    +#include "dropwin.h"
    +#include "dock_gp.h"
    +
    +// function to handle the dock actions
    +void toolgrp::dock_grp(void* v) 
    +{ // dock CB
    +	toolgrp *gp = (toolgrp *)v;
    +	dockgroup *dock = gp->get_dock();
    +
    +	// we can only dock a group that's not already docked... 
    +	// and only if a dock exists for it
    +	if((gp->docked() == 0) && (dock))
    +	{	//re-dock the group
    +		toolwin *cur_parent = (toolwin *)gp->parent();
    +		dock->add(gp); // move the toolgroup into the dock
    +		dock->redraw();
    +		gp->docked(-1);    // toolgroup is docked...
    +		// so we no longer need the tool window.
    +		cur_parent->hide();
    +		delete cur_parent;
    +	}
    +}
    +
    +// static CB to handle the undock actions
    +void toolgrp::undock_grp(void* v) 
    +{ // undock CB
    +	toolgrp *gp = (toolgrp *)v;
    +	dockgroup *dock = gp->get_dock();
    +	
    +	if(gp->docked() == -1)
    +	{	// undock the group into its own non-modal tool window
    +		int w = gp->w();
    +		int h = gp->h();
    +		Fl_Group::current(0);
    +		toolwin *new_parent = new toolwin(Fl::event_x_root() - 10, Fl::event_y_root() - 35, w + 3, h + 3);
    +		new_parent->end();
    +		dock->remove(gp);
    +		new_parent->add(gp);// move the tool group into the floating window
    +		new_parent->set_inner((void *)gp);
    +		gp->position(1, 1); // align group in floating window
    +		new_parent->show(); // show floating window
    +		gp->docked(0);      // toolgroup is no longer docked
    +		dock->redraw();     // update the dock, to show the group has gone...
    +	}
    +}
    +
    +void toolgrp::hide_show()
    +{
    +//	if (docked() == 0) return;
    +
    +	dockgroup *dock = get_dock();
    +	if (docked() == 0) {
    +		toolwin *cur_parent = (toolwin *)parent();
    +		dock->add(this); // move the toolgroup into the dock
    +		dock->redraw();
    +		cur_parent->remove(this);
    +		cur_parent->hide(); // remove current parent window
    +		delete cur_parent;
    +		dock->remove(this); // remove toolgroup from docked parent
    +		docked(-2);
    +		dock->redraw();
    +	}
    +	else if (docked() == -1) {
    +		dock->remove(this);
    +		docked(-2);
    +		dock->redraw();
    +	} else { // docked() == -2  // the unassigned state
    +		dock->add(this);
    +		docked(-1);
    +		dock->redraw();
    +	}
    +}
    +
    +// static CB to handle the dismiss action
    +//void toolgrp::cb_dismiss(Fl_Button*, void* v) 
    +//{
    +//	toolgrp *gp = (toolgrp *)v;
    +//	dockgroup *dock = gp->get_dock();
    +	
    +//	if(gp->docked())
    +//	{	// remove the group from the dock
    +//		dock->remove(gp);
    +//		gp->docked(0);
    +//		dock->redraw();     // update the dock, to show the group has gone...
    +//		Fl::delete_widget(gp);
    +//	}
    +//	else
    +//	{	// remove the group from the floating window, 
    +//		// and remove the floating window
    +//		toolwin *cur_parent = (toolwin *)gp->parent();
    +//		cur_parent->remove(gp);
    +//		//delete cur_parent; // we no longer need the tool window.
    +//		Fl::delete_widget(cur_parent);
    +//		Fl::delete_widget(gp);
    +//	}
    +//}
    +
    +// Constructors for docked/floating window
    +// WITH x, y co-ordinates
    +toolgrp::toolgrp(dockgroup *dk, int floater, int x, int y, int w, int h, const char *lbl)
    +  : Fl_Group(1, 1, w - 2 , h - 2, lbl)
    +{
    +	if((floater) && (dk)) // create floating
    +	{
    +		create_floating(dk, 1, x, y, w, h, lbl);
    +	}
    +	else if(dk) // create docked
    +	{
    +		create_docked(dk);
    +	}
    +//	else //do nothing...
    +}
    +
    +// WITHOUT x, y co-ordinates
    +toolgrp::toolgrp(dockgroup *dk, int floater, int w, int h, const char *lbl)
    +  : Fl_Group(1, 1, w - 2, h - 2, lbl)
    +{
    +	if((floater) && (dk)) // create floating
    +	{
    +		create_floating(dk, 0, 0, 0, w, h, lbl);
    +	}
    +	else if(dk) // create docked
    +	{
    +		create_docked(dk);
    +	}
    +//	else //do nothing...
    +}
    +
    +// construction function
    +void toolgrp::create_dockable_group()
    +{
    +
    +	dragger = new drag_btn(2, 2, 12, h() - 4);
    +	dragger->type(FL_TOGGLE_BUTTON);
    +	dragger->box(FL_ENGRAVED_FRAME);
    +	dragger->tooltip("Drag Box");
    +	dragger->clear_visible_focus();
    +	dragger->when(FL_WHEN_CHANGED);
    +	
    +	inner_group = new Fl_Group(16, 2, w() - 18, h() - 4);
    +	inner_group->box(FL_FLAT_BOX);
    +//	inner_group->box(FL_ENGRAVED_FRAME);
    +}
    +
    +void toolgrp::create_docked(dockgroup *dk)
    +{
    +	// create the group itself
    +	create_dockable_group();
    +	// place it in the dock
    +	dk->add(this);
    +	set_dock(dk); // define where the toolgroup is allowed to dock
    +	docked(-1);	// docked
    +	dk->redraw();
    +	Fl_Group::resizable(inner_group);
    +}
    +
    +void toolgrp::create_floating(dockgroup *dk, int full, int x, int y, int w, int h, const char *lbl)
    +{
    +	toolwin *tw;
    +	// create the group itself
    +	create_dockable_group();
    +	// create a floating toolbar window
    +	// Ensure the window is not created as a child of its own inner group!
    +	Fl_Group::current(0);
    +	if(full)
    +		tw = new toolwin(x, y, w + 4, h + 4, lbl);
    +	else
    +		tw = new toolwin(w + 4, h + 4, lbl);
    +	tw->end();
    +	tw->add(this);  // move the tool group into the floating window
    +	docked(0);		// NOT docked
    +	set_dock(dk);	// define where the toolgroup is allowed to dock
    +	tw->set_inner((void *)this);
    +	tw->show();
    +	Fl_Group::current(inner_group); // leave this group open when we leave the constructor...
    +	Fl_Group::resizable(inner_group);
    +}
    +
    +// function for setting the docked state and checkbox
    +void toolgrp::docked(short r)
    +{ 
    +	_docked = r; 
    +}
    +
    +// methods for hiding/showing *all* the floating windows
    +// show all the active floating windows
    +void toolgrp::show_all(void)
    +{
    +	toolwin::show_all();
    +}
    +
    +// hide all the active floating windows
    +void toolgrp::hide_all(void)
    +{
    +	toolwin::hide_all();
    +}
    +
    diff --git a/src/widgets/toolwin.cxx b/src/widgets/toolwin.cxx
    new file mode 100644
    index 00000000..29beed38
    --- /dev/null
    +++ b/src/widgets/toolwin.cxx
    @@ -0,0 +1,101 @@
    +#include 
    +
    +#include "toolwin.h"
    +#include "toolgrp.h"
    +#include "dock_events.h"
    +
    +#include 
    +
    +#define NTW (toolwin*)0  // Null Tool Window
    +
    +// HACK:: This just stores the toolwindows in a static array. I'm too lazy
    +//        to make a proper linked list to store these in...
    +toolwin* toolwin::active_list[TW_MAX_FLOATERS]; // list of active toolwins
    +short toolwin::active = 0; // count of active tool windows
    +
    +// Dummy close button callback
    +static void cb_ignore(void)
    +{
    +	// Just shrug off the close callback...
    +}
    +
    +// constructors
    +toolwin::toolwin(int x, int y, int w, int h, const char *l) 
    +  : Fl_Double_Window(x, y, w, h, l) 
    +{
    +	create_dockable_window();
    +}
    +
    +toolwin::toolwin(int w, int h, const char *l) 
    +  : Fl_Double_Window(w, h, l) 
    +{
    +	create_dockable_window();
    +}
    +
    +// destructor
    +toolwin::~toolwin()
    +{
    +	active_list[idx] = NTW;
    +	active --;
    +}
    +
    +// construction function
    +void toolwin::create_dockable_window() 
    +{
    +	static int first_window = 1;
    +	tool_group = (void *)0;
    +	// window list intialisation...
    +	// this is a nasty hack, should make a proper list
    +	if(first_window)
    +	{
    +		first_window = 0;
    +		for(short i = 0; i < TW_MAX_FLOATERS; i++)
    +			active_list[i] = NTW;
    +	}
    +	// find an empty index
    +	for(short i = 0; i < TW_MAX_FLOATERS; i++)
    +	{
    +		if(!active_list[i])
    +		{
    +			idx = i;
    +			active_list[idx] = this;
    +			active ++;
    +			clear_border();
    +			set_non_modal();
    +			callback((Fl_Callback *)cb_ignore);
    +			return;
    +		}
    +	}
    +	// if we get here, the list is probably full, what a hack.
    +	// FIX THIS:: At present, we will get a non-modal window with
    +	// decorations as a default instead...
    +	set_non_modal();
    +}
    +
    +// show all the active floating windows
    +void toolwin::show_all(void)
    +{
    +	if (active)
    +	{
    +		for(short i = 0; i < TW_MAX_FLOATERS; i++)
    +		{
    +			if(active_list[i])
    +				active_list[i]->show();
    +		}
    +	}
    +}
    +
    +// hide all the active floating windows
    +void toolwin::hide_all(void)
    +{
    +	if (active)
    +	{
    +		for(short i = 0; i < TW_MAX_FLOATERS; i++)
    +		{
    +			if(active_list[i])
    +				active_list[i]->hide();
    +		}
    +	}
    +}
    +
    +
    diff --git a/src/wwv/analysis.cxx b/src/wwv/analysis.cxx
    index a6b114a1..badfad5e 100644
    --- a/src/wwv/analysis.cxx
    +++ b/src/wwv/analysis.cxx
    @@ -62,7 +62,6 @@ void anal::init()
     
     anal::~anal()
     {
    -	delete hilbert;
     	delete bpfilt;
     	delete ffilt;
     	delete favg;
    @@ -94,6 +93,8 @@ void anal::restart()
     	dspcnt = DSP_CNT;
     	for (int i = 0; i < PIPE_LEN; i++) pipe[i] = 0;
     
    +	if (write_to_csv) stop_csv();
    +
     	start_csv();
     
     }
    @@ -105,14 +106,14 @@ anal::anal()
     	samplerate = ANAL_SAMPLERATE;
     
     	bpfilt = (fftfilt *)0;
    -	hilbert = new C_FIR_filter();
    -	hilbert->init_hilbert(37, 1);
     	ffilt = new Cmovavg(FILT_LEN * samplerate);
     
    -	analysisFilename = HomeDir;
    -	analysisFilename.append("freqanalysis.csv");
    +	analysisFilename = TempDir;
    +	analysisFilename.append("analysis.csv");
     
     	cap &= ~CAP_TX;
    +	write_to_csv = false;
    +
     	restart();
     }
     
    @@ -140,10 +141,22 @@ void anal::start_csv()
     	}
     	fprintf(out, "Clock,Elapsed Time,Freq Error,RF\n");
     	fclose(out);
    +
    +	put_status("Writing csv file");
    +
    +	write_to_csv = true;
    +}
    +
    +void anal::stop_csv()
    +{
    +	write_to_csv = false;
    +	put_status("");
     }
     
     void anal::writeFile()
     {
    +	if (!write_to_csv) return;
    +
     	struct timespec now;
     	struct tm tm;
     
    @@ -163,6 +176,9 @@ void anal::writeFile()
     		tm.tm_hour, tm.tm_min, tm.tm_sec, elapsed, fout,
     		(wf->rfcarrier() + (wf->USB() ? 1.0 : -1.0) * (frequency + fout)));
     	fclose(out);
    +
    +	put_status("Writing csv file");
    +
     }
     
     int anal::rx_process(const double *buf, int len)
    @@ -180,7 +196,6 @@ int anal::rx_process(const double *buf, int len)
     // create analytic signal from sound card input samples
     		z = cmplx( *buf, *buf );
     		buf++;
    -//		hilbert->run(z, z);
     // mix it with the audio carrier frequency to create a baseband signal
     		z = mixer(z);
     // low pass filter using Windowed Sinc - Overlap-Add convolution filter
    @@ -216,7 +231,7 @@ int anal::rx_process(const double *buf, int len)
     					snprintf(msg1, sizeof(msg1), "%12.2f", wf->rfcarrier() + frequency + fout );
     				else
     					snprintf(msg1, sizeof(msg1), "%12.2f", wf->rfcarrier() - frequency - fout );
    -				put_status(msg1, 2.0);
    +				put_Status2(msg1, 2.0);
     				writeFile();
     			}
     // reset the display counter & the pipe pointer
    diff --git a/src/xmlrpcpp/XmlRpcSocket.cpp b/src/xmlrpcpp/XmlRpcSocket.cpp
    index f6f067ad..26e4cf94 100644
    --- a/src/xmlrpcpp/XmlRpcSocket.cpp
    +++ b/src/xmlrpcpp/XmlRpcSocket.cpp
    @@ -59,7 +59,7 @@ static void initialize()
     
     #if defined(_WINDOWS)
         {
    -        WORD wVersionRequested = MAKEWORD( WSA_MAJOR, WSA_MINOR );
    +        WORD wVersionRequested = MAKEWORD( 2, 0 );
             WSADATA wsaData;
             WSAStartup(wVersionRequested, &wsaData);
            	atexit((void(*)(void)) WSACleanup);