You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

garmin_tables.cc 30KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120
  1. /*
  2. Garmin icon tables
  3. Based on information provided by Ian Cowley, Sigurd Humerfelt,
  4. and Garmin MapSource
  5. Copyright (C) 2003-2007 Robert Lipe, robertlipe+source@gpsbabel.org
  6. This program is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2 of the License, or
  9. (at your option) any later version.
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with this program; if not, write to the Free Software
  16. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
  17. */
  18. #include "garmin_tables.h"
  19. #include "src/core/logging.h"
  20. #include "jeeps/gpsmath.h"
  21. #include <stdlib.h> // qsort
  22. #define MYNAME "garmin_tables"
  23. /* MapSource 4.13 */
  24. icon_mapping_t garmin_icon_table[] = {
  25. /* mps pcx desc */
  26. { 107, 16384, "Airport" },
  27. { 73, 8204, "Amusement Park" },
  28. { 55, 169, "Ball Park" },
  29. { 6, 6, "Bank" },
  30. { 13, 13, "Bar" },
  31. { 104, 8244, "Beach" },
  32. { 1, 1, "Bell" },
  33. { 37, 150, "Boat Ramp" },
  34. { 74, 8205, "Bowling" },
  35. { 93, 8233, "Bridge" },
  36. { 94, 8234, "Building" },
  37. { 38, 151, "Campground" },
  38. { 56, 170, "Car" },
  39. { 75, 8206, "Car Rental" },
  40. { 76, 8207, "Car Repair" },
  41. { 95, 8235, "Cemetery" },
  42. { 96, 8236, "Church" },
  43. { 65, 179, "Circle with X" },
  44. { 72, 8203, "City (Capitol)" },
  45. { 71, 8200, "City (Large)" },
  46. { 70, 8199, "City (Medium)" },
  47. { 69, 8198, "City (Small)" },
  48. { 69, 8198, "Small City" },
  49. { 97, 8237, "Civil" },
  50. { 119, 8262, "Contact, Afro" },
  51. { 120, 8272, "Contact, Alien" },
  52. { 121, 8258, "Contact, Ball Cap" },
  53. { 122, 8259, "Contact, Big Ears" },
  54. { 123, 8271, "Contact, Biker" },
  55. { 124, 8273, "Contact, Bug" },
  56. { 125, 8274, "Contact, Cat" },
  57. { 126, 8275, "Contact, Dog" },
  58. { 127, 8263, "Contact, Dreadlocks" },
  59. { 128, 8264, "Contact, Female1" },
  60. { 129, 8265, "Contact, Female2" },
  61. { 130, 8266, "Contact, Female3" },
  62. { 131, 8261, "Contact, Goatee" },
  63. { 132, 8268, "Contact, Kung-Fu" },
  64. { 133, 8276, "Contact, Pig" },
  65. { 134, 8270, "Contact, Pirate" },
  66. { 135, 8267, "Contact, Ranger" },
  67. { 136, 8257, "Contact, Smiley" },
  68. { 137, 8260, "Contact, Spike" },
  69. { 138, 8269, "Contact, Sumo" },
  70. { 52, 165, "Controlled Area" },
  71. { 89, 8220, "Convenience Store" },
  72. { 98, 8238, "Crossing" },
  73. { 51, 164, "Dam" },
  74. { 53, 166, "Danger Area" },
  75. { 87, 8218, "Department Store" },
  76. { 4, 4, "Diver Down Flag 1" },
  77. { 5, 5, "Diver Down Flag 2" },
  78. { 41, 154, "Drinking Water" },
  79. { 63, 177, "Exit" },
  80. { 77, 8208, "Fast Food" },
  81. { 7, 7, "Fishing Area" },
  82. { 78, 8209, "Fitness Center" },
  83. { 64, 178, "Flag" },
  84. { 105, 8245, "Forest" },
  85. { 8, 8, "Gas Station" },
  86. { 117, 8255, "Geocache" },
  87. { 118, 8256, "Geocache Found" },
  88. { 99, 8239, "Ghost Town" },
  89. { 113, 16393, "Glider Area" },
  90. { 68, 8197, "Golf Course" },
  91. { 2, 2, "Diamond, Green" },
  92. { 15, 15, "Square, Green" },
  93. { 108, 16388, "Heliport" },
  94. { 9, 9, "Horn" },
  95. { 57, 171, "Hunting Area" },
  96. { 44, 157, "Information" },
  97. { 100, 8240, "Levee" },
  98. { 12, 12, "Light" },
  99. { 90, 8221, "Live Theater" },
  100. { 59, 173, "Lodging" },
  101. { 59, 173, "Hotel" },
  102. { 20, 21, "Man Overboard" },
  103. { 0, 0, "Anchor" },
  104. { 43, 156, "Medical Facility" },
  105. { 66, 8195, "Mile Marker" },
  106. { 101, 8241, "Military" },
  107. { 60, 174, "Mine" },
  108. { 79, 8210, "Movie Theater" },
  109. { 80, 8211, "Museum" },
  110. { 21, 22, "Navaid, Amber" },
  111. { 22, 23, "Navaid, Black" },
  112. { 23, 24, "Navaid, Blue" },
  113. { 24, 25, "Navaid, Green" },
  114. { 25, 26, "Navaid, Green/Red" },
  115. { 26, 27, "Navaid, Green/White" },
  116. { 27, 28, "Navaid, Orange" },
  117. { 28, 29, "Navaid, Red" },
  118. { 29, 30, "Navaid, Red/Green" },
  119. { 30, 31, "Navaid, Red/White" },
  120. { 31, 32, "Navaid, Violet" },
  121. { 32, 33, "Navaid, White" },
  122. { 33, 34, "Navaid, White/Green" },
  123. { 34, 35, "Navaid, White/Red" },
  124. { 102, 8242, "Oil Field" },
  125. { 115, 16395, "Parachute Area" },
  126. { 46, 159, "Park" },
  127. { 45, 158, "Parking Area" },
  128. { 81, 8212, "Pharmacy" },
  129. { 47, 160, "Picnic Area" },
  130. { 82, 8213, "Pizza" },
  131. { 83, 8214, "Post Office" },
  132. { 109, 16389, "Private Field" },
  133. { 36, 37, "Radio Beacon" },
  134. { 3, 3, "Diamond, Red" },
  135. { 16, 16, "Square, Red" },
  136. { 10, 10, "Residence" },
  137. { 10, 10, "House" },
  138. { 11, 11, "Restaurant" },
  139. { 54, 167, "Restricted Area" },
  140. { 39, 152, "Restroom" },
  141. { 84, 8215, "RV Park" },
  142. { 91, 8226, "Scales" },
  143. { 48, 161, "Scenic Area" },
  144. { 85, 8216, "School" },
  145. { 116, 16402, "Seaplane Base" },
  146. { 19, 19, "Shipwreck" },
  147. { 58, 172, "Shopping Center" },
  148. { 112, 16392, "Short Tower" },
  149. { 40, 153, "Shower" },
  150. { 49, 162, "Skiing Area" },
  151. { 14, 14, "Skull and Crossbones" },
  152. { 110, 16390, "Soft Field" },
  153. { 86, 8217, "Stadium" },
  154. { 106, 8246, "Summit" },
  155. { 50, 163, "Swimming Area" },
  156. { 111, 16391, "Tall Tower" },
  157. { 42, 155, "Telephone" },
  158. { 92, 8227, "Toll Booth" },
  159. { 67, 8196, "TracBack Point" },
  160. { 61, 175, "Trail Head" },
  161. { 62, 176, "Truck Stop" },
  162. { 103, 8243, "Tunnel" },
  163. { 114, 16394, "Ultralight Area" },
  164. { 139, 8282, "Water Hydrant" }, /* new in MapSource V5 */
  165. { 18, 18, "Waypoint" },
  166. { 17, 17, "Buoy, White" },
  167. { 35, 36, "Dot, White" },
  168. { 88, 8219, "Zoo" },
  169. /* Custom icons. The spec reserves 7680-8191 for the custom
  170. * icons on the C units, Quest, 27xx, 276, 296, and other units.
  171. * Note that firmware problems on the earlier unit result in these
  172. * being mangled, so be sure you're on a version from at least
  173. * late 2005.
  174. * { -2, 7680, "Custom 0" },
  175. * ....
  176. * { -2, 8192, "Custom 511" },
  177. */
  178. /* MapSource V6.x */
  179. { 140, 8286, "Flag, Red" },
  180. { 141, 8284, "Flag, Blue" },
  181. { 142, 8285, "Flag, Green" },
  182. { 143, 8289, "Pin, Red" },
  183. { 144, 8287, "Pin, Blue" },
  184. { 145, 8288, "Pin, Green" },
  185. { 146, 8292, "Block, Red" },
  186. { 147, 8290, "Block, Blue" },
  187. { 148, 8291, "Block, Green" },
  188. { 149, 8293, "Bike Trail" },
  189. { 150, 181, "Fishing Hot Spot Facility" },
  190. { 151, 8249, "Police Station"},
  191. { 152, 8251, "Ski Resort" },
  192. { 153, 8252, "Ice Skating" },
  193. { 154, 8253, "Wrecker" },
  194. { 155, 184, "Anchor Prohibited" },
  195. { 156, 185, "Beacon" },
  196. { 157, 186, "Coast Guard" },
  197. { 158, 187, "Reef" },
  198. { 159, 188, "Weed Bed" },
  199. { 160, 189, "Dropoff" },
  200. { 161, 190, "Dock" },
  201. { 162, 191, "Marina" },
  202. { 163, 192, "Bait and Tackle" },
  203. { 164, 193, "Stump" },
  204. /* New in Garmin protocol spec from June 2006. Extracted from
  205. * spec and fed through some horrible awk to add ones we didn't
  206. * have before but normalized for consistency. */
  207. { -1, 8359, "Asian Food" },
  208. { 167, 8296, "Circle, Blue" },
  209. { 168, 8299, "Diamond, Blue" },
  210. { 178, 8317, "Letter A, Blue" },
  211. { 181, 8318, "Letter B, Blue" },
  212. { 184, 8319, "Letter C, Blue" },
  213. { 187, 8320, "Letter D, Blue" },
  214. { 190, 8341, "Number 0, Blue" },
  215. { 193, 8342, "Number 1, Blue" },
  216. { 196, 8343, "Number 2, Blue" },
  217. { 199, 8344, "Number 3, Blue" },
  218. { 202, 8345, "Number 4, Blue" },
  219. { 205, 8346, "Number 5, Blue" },
  220. { 208, 8347, "Number 6, Blue" },
  221. { 211, 8348, "Number 7, Blue" },
  222. { 214, 8349, "Number 8, Blue" },
  223. { 217, 8350, "Number 9, Blue" },
  224. { 171, 8302, "Oval, Blue" },
  225. { 174, 8305, "Rectangle, Blue" },
  226. { 175, 8308, "Square, Blue" },
  227. { 218, 8351, "Triangle, Blue" },
  228. { -1, 8254, "Border Crossing (Port Of Entry)" },
  229. { -1, 182, "Bottom Conditions" },
  230. { -1, 8360, "Deli" },
  231. { -1, 8228, "Elevation point" },
  232. { -1, 8229, "Exit without services" },
  233. { -1, 16398, "First approach fix" },
  234. { -1, 8250, "Gambling/casino" },
  235. { -1, 8232, "Geographic place name, land" },
  236. { -1, 8230, "Geographic place name, Man-made" },
  237. { -1, 8231, "Geographic place name, water" },
  238. { 166, 8295, "Circle, Green" },
  239. { 177, 8313, "Letter A, Green" },
  240. { 180, 8315, "Letter B, Green" },
  241. { 183, 8314, "Letter C, Green" },
  242. { 186, 8316, "Letter D, Green" },
  243. { 189, 8331, "Number 0, Green" },
  244. { 192, 8332, "Number 1, Green" },
  245. { 195, 8333, "Number 2, Green" },
  246. { 198, 8334, "Number 3, Green" },
  247. { 201, 8335, "Number 4, Green" },
  248. { 204, 8336, "Number 5, Green" },
  249. { 207, 8337, "Number 6, Green" },
  250. { 210, 8338, "Number 7, Green" },
  251. { 213, 8339, "Number 8, Green" },
  252. { 216, 8340, "Number 9, Green" },
  253. { 170, 8301, "Oval, Green" },
  254. { 173, 8304, "Rectangle, Green" },
  255. { 219, 8352, "Triangle, Green" },
  256. { -1, 16385, "Intersection" },
  257. { -1, 8201, "Intl freeway hwy" },
  258. { -1, 8202, "Intl national hwy" },
  259. { -1, 8361, "Italian food" },
  260. { -1, 8248, "Large exit without services" },
  261. { -1, 8247, "Large Ramp intersection" },
  262. { -1, 16399, "Localizer Outer Marker" },
  263. { -1, 16400, "Missed approach point" },
  264. { -1, 16386, "Non-directional beacon" },
  265. { -1, 168, "Null" },
  266. { -1, 180, "Open 24 Hours" },
  267. { -1, 8222, "Ramp intersection" },
  268. { 165, 8294, "Circle, Red" },
  269. { 176, 8309, "Letter A, Red" },
  270. { 179, 8310, "Letter B, Red" },
  271. { 182, 8311, "Letter C, Red" },
  272. { 185, 8312, "Letter D, Red" },
  273. { 188, 8321, "Number 0, Red" },
  274. { 191, 8322, "Number 1, Red" },
  275. { 194, 8323, "Number 2, Red" },
  276. { 197, 8324, "Number 3, Red" },
  277. { 200, 8325, "Number 4, Red" },
  278. { 203, 8326, "Number 5, Red" },
  279. { 206, 8327, "Number 6, Red" },
  280. { 209, 8328, "Number 7, Red" },
  281. { 212, 8329, "Number 8, Red" },
  282. { 215, 8330, "Number 9, Red" },
  283. { 169, 8300, "Oval, Red" },
  284. { 172, 8303, "Rectangle, Red" },
  285. { 220, 8353, "Triangle, Red" },
  286. { -1, 8362, "Seafood" },
  287. { -1, 8194, "State Hwy" },
  288. { -1, 8363, "Steak" },
  289. { -1, 8223, "Street Intersection" },
  290. { -1, 16401, "TACAN" },
  291. { -1, 183, "Tide/Current PRediction Station" },
  292. { -1, 191, "U Marina" },
  293. { -1, 8193, "US hwy" },
  294. { -1, 193, "U stump" },
  295. { -1, 16387, "VHF Omni-range" },
  296. { -1, 16397, "VOR-DME" },
  297. { -1, 16396, "VOR/TACAN" },
  298. /* This block new on 1/15 from the Mapsource 6.12 beta */
  299. { 221, -1, "Contact, Blonde" },
  300. { 222, -1, "Contact, Clown" },
  301. { 223, -1, "Contact, Glasses" },
  302. { 224, -1, "Contact, Panda" },
  303. { 225, -1, "Multi-Cache" },
  304. { 226, -1, "Letterbox Cache" },
  305. { 227, -1, "Puzzle Cache" },
  306. { 228, -1, "Library" },
  307. { 229, -1, "Ground Transportation" },
  308. { 230, -1, "City Hall" },
  309. { 231, -1, "Winery" },
  310. { 232, -1, "ATV" },
  311. { 233, -1, "Big Game" },
  312. { 234, -1, "Blind" },
  313. { 235, -1, "Blood Trail" },
  314. { 236, -1, "Cover" },
  315. { 237, -1, "Covey" },
  316. { 238, -1, "Food Source" },
  317. { 239, -1, "Furbearer" },
  318. { 240, -1, "Lodge" },
  319. { 241, -1, "Small Game" },
  320. { 242, -1, "Animal Tracks" },
  321. { 243, -1, "Treed Quarry" },
  322. { 244, -1, "Tree Stand" },
  323. { 245, -1, "Truck" },
  324. { 246, -1, "Upland Game" },
  325. { 247, -1, "Waterfowl" },
  326. { 248, -1, "Water Source" },
  327. { -1, -1, NULL },
  328. };
  329. icon_mapping_t garmin_smart_icon_table[] = {
  330. /* Additional (optional, activated with -Si) icons */
  331. { 92, 8227, "Micro-Cache" }, /* icon for "Toll Booth" */
  332. { 48, 161, "Virtual cache" }, /* icon for "Scenic Area" */
  333. { 86, 8217, "Multi-Cache" }, /* icon for "Stadium" */
  334. { 44, 157, "Unknown Cache" }, /* icon for "Information" */
  335. { 64, 178, "Locationless (Reverse) Cache" }, /* Icon for "Flag" */
  336. { 83, 8214, "Post Office" }, /* Icon for "Post Office" */
  337. { 47, 160, "Event Cache" }, /* Icon for "Event" */
  338. { 90, 8221, "Webcam Cache" }, /* Icon for "Live Theatre" */
  339. { -1, -1, NULL }
  340. };
  341. /* ICAO coutry code table */
  342. /* source: http://en.wikipedia.org/wiki/ICAO_airport_code */
  343. gt_country_code_t gt_country_codes[] = {
  344. { "ZM,", "Mongolia" },
  345. { "ZK,", "North Korea" },
  346. { "Z*,", "China" },
  347. { "Y*,", "Australia" },
  348. { "WS,", "Singapore" },
  349. { "WM,", "Brunei/Malaysia" },
  350. { "WB,", "Malaysia" },
  351. { "WA,WI,WQ,WR,", "Indonesia" },
  352. { "VV,", "Vietnam" },
  353. { "VT,", "Thailand" },
  354. { "VR,", "Maldives" },
  355. { "VQ,", "Bhutan" },
  356. { "VN,", "Nepal" },
  357. { "VM,", "Macau" },
  358. { "VL,", "Laos" },
  359. { "VH,", "Hong Kong" },
  360. { "VG,", "Bangladesh" },
  361. { "VD,", "Kampuchea" },
  362. { "VC,", "Sri Lanka" },
  363. { "VB,VY,", "Myanmar/Burma" },
  364. { "VA,VE,VI,VO,", "India" },
  365. { "UR,", "Kazakhstan/Russia" },
  366. { "UT,", "Kazakhstan/Tadzhikistan/Turkmenistan/Uzbekistan" },
  367. { "UM,", "Belorussia/Russia" },
  368. { "UK,", "Ukraine" },
  369. { "UB,", "Azerbaijan" },
  370. { "UA,", "Kazakhstan/Kirgizia" },
  371. { "U*,", "Russia" },
  372. { "TX,", "Bermuda" },
  373. { "TV,", "St Vincent and the Grenadines" },
  374. { "TU,", "British Virgin Islands" },
  375. { "TT,", "Trinidad and Tobago" },
  376. { "TR,", "Montserrat Island" },
  377. { "TQ,", "Anguilla" },
  378. { "TN,", "Aruba/Neth Antilles" },
  379. { "TL,", "St Lucia" },
  380. { "TK,", "St Kitts/Nevis Islands" },
  381. { "TJ,", "Puerto Rico" },
  382. { "TG,", "Grenada" },
  383. { "TF,", "Guadeloupe/Martinique" },
  384. { "TD,", "Dominica" },
  385. { "TB,", "Barbados" },
  386. { "TA,", "Antigua" },
  387. { "SY,", "Guyana" },
  388. { "SV,", "Venezuela" },
  389. { "SU,", "Uruguay" },
  390. { "SP,", "Peru" },
  391. { "SO,", "French Guiana" },
  392. { "SM,", "Suriname" },
  393. { "SL,", "Bolivia" },
  394. { "SK,", "Colombia/San Andres" },
  395. { "SG,", "Paraguay" },
  396. { "SF,", "Falkland Islands" },
  397. { "SE,", "Ecuador" },
  398. { "SC,", "Chile/Easter Island" },
  399. { "SB,SD,SN,SS,SW,", "Brazil" },
  400. { "SA,", "Argentina" },
  401. { "S1,", "Antarctica (Argentina/Chile)" },
  402. { "RP,", "Philippines" },
  403. { "RK,", "South Korea" },
  404. { "RJ,", "Japan" },
  405. { "RC,", "Taiwan" },
  406. { "PW,", "Wake Island" },
  407. { "PT,", "Caroline Islands/Micronesia/Palau" },
  408. { "PM,", "Midway Islands" },
  409. { "PK,", "Marshall Islands" },
  410. { "PJ,", "Johnston Atoll" },
  411. { "PG,", "Guam/Mariana Islands/Northern Mariana Islands" },
  412. { "PC,", "Kiribati" },
  413. { "P", "Oakland Octa" },
  414. { "OY,", "Yemen Arab Rep" },
  415. { "OT,", "Qatar" },
  416. { "OS,", "Syria" },
  417. { "OR,", "Iraq" },
  418. { "OP,", "Pakistan" },
  419. { "OO,", "Oman" },
  420. { "OM,", "United Arab Emirates" },
  421. { "OL,", "Lebanon" },
  422. { "OK,", "Kuwait" },
  423. { "OJ,", "Jordan" },
  424. { "OI,", "Iran" },
  425. { "OE,", "Saudi Arabia" },
  426. { "OB,", "Bahrain" },
  427. { "OA,", "Afghanistan" },
  428. { "NZ,PL,", "New Zealand" },
  429. { "NW,", "New Caledonia" },
  430. { "NV,", "Vanuatu" },
  431. { "NT,", "French Polynesia/Society Islands/Tuamotu Islands" },
  432. { "NS,", "American Samoa/Western Samoa" },
  433. { "NL,", "Futuna Island/Wallis Island" },
  434. { "NI,", "Niue" },
  435. { "NG,", "Kiribati/Tuvalu" },
  436. { "NF,", "Fiji Island/Tonga" },
  437. { "NC,", "Cook Islands" },
  438. { "MZ,", "Belize" },
  439. { "MY,", "Bahamas" },
  440. { "MW,", "Cayman Islands" },
  441. { "MU,", "Cuba" },
  442. { "MT,", "Haiti" },
  443. { "MS,", "El Salvador" },
  444. { "MR,", "Costa rica" },
  445. { "MP,", "Panama" },
  446. { "MN,", "Nicaragua" },
  447. { "MM,", "Mexico" },
  448. { "MK,", "Jamaica" },
  449. { "MI,TI,", "Virgin Islands (U.S.)" },
  450. { "MH,", "Honduras" },
  451. { "MG,", "Guatemala" },
  452. { "MD,", "Dominican Republic" },
  453. { "MB,", "Turks Island/Caicos Island" },
  454. { "LZ,", "Slovakia" },
  455. { "LY,", "Yugoslavia" },
  456. { "LX,", "Gibraltar" },
  457. { "LW,", "Macedonia" },
  458. { "LV,", "Gaza" },
  459. { "LU,", "Moldova" },
  460. { "LT,", "Turkey" },
  461. { "LS,", "Switzerland" },
  462. { "LR,", "Romania" },
  463. { "LQ,", "Bosnia-Herzegovina" },
  464. { "LP,", "Portugal/Azores/Madeira Islands" },
  465. { "LO,", "Austria" },
  466. { "LN,", "Monaco" },
  467. { "LM,", "Malta" },
  468. { "LL,", "Israel/Jerusalem" },
  469. { "LK,", "Czech" },
  470. { "LI,", "Italy" },
  471. { "LH,", "Hungary" },
  472. { "LG,", "Slovenia" },
  473. { "LG,", "Greece" },
  474. { "LF,", "France" },
  475. { "LF,", "Miquelon Island/St Pierre Island" },
  476. { "LE,", "Spain" },
  477. { "LD,", "Croatia" },
  478. { "LC,", "Cyprus/Turkey (Northern Cyprus)" },
  479. { "LB,", "Bulgaria" },
  480. { "LA,", "Albania" },
  481. { "K*,X*,PA,PB,PF,PJ,PL,PM,PO,PP,PH,PW,", "United States of America" },
  482. { "HU,", "Uganda" },
  483. { "HT,", "Tanzania" },
  484. { "HS,", "Sudan" },
  485. { "HR,", "Rwanda" },
  486. { "HL,", "Libya, Spa Jamahiriya" },
  487. { "HK,", "Kenya" },
  488. { "HH,", "Eritrea" },
  489. { "HE,", "Egypt" },
  490. { "HD,HF,", "Djibouti" },
  491. { "HC,", "Somalia" },
  492. { "HB,", "Burundi" },
  493. { "HA,", "Ethiopia" },
  494. { "GV,", "Cape Verde" },
  495. { "GU,", "Guinea Tepublic" },
  496. { "GQ,", "Mauritania" },
  497. { "GO,", "Senegal" },
  498. { "GM,", "Morocco/Ad Dakhla/La'Youn" },
  499. { "GL,", "Liberia" },
  500. { "GG,", "Guinea-Bissau" },
  501. { "GF,", "Sierra Leone" },
  502. { "GE,", "Melilla" },
  503. { "GC,", "Canary Island" },
  504. { "GB,", "Gambia" },
  505. { "GA,", "Mali" },
  506. { "FZ,", "Democratic Republic of Congo" },
  507. { "FY,", "Namibia" },
  508. { "FX,", "Lesotho" },
  509. { "FW,", "Malawi" },
  510. { "FV,", "Zimbabwe" },
  511. { "FT,", "Chad" },
  512. { "FS,", "Seychelles" },
  513. { "FQ,", "Mozambique" },
  514. { "FP,", "Sao Tome & Principe" },
  515. { "FO,", "Gabon" },
  516. { "FN,", "Angola" },
  517. { "FM,", "Madagascar/Comoros/Reunion/Mayotte Islands" },
  518. { "FL,", "Zambia" },
  519. { "FK,", "Cameroon" },
  520. { "FJ,", "Chagos Archipelago/British Indian Ocean Territory" },
  521. { "FI,", "Mauritius" },
  522. { "FH,", "Ascension Island/St Helena Island" },
  523. { "FG,", "Equitorial Guinea" },
  524. { "FE,", "Central African Republic" },
  525. { "FD,", "Swaziland" },
  526. { "FC,", "Congo" },
  527. { "FB,", "Botswana" },
  528. { "FA,", "South African Republic" },
  529. { "EY,", "Lithuania" },
  530. { "EV,", "Latvia" },
  531. { "ES,", "Sweden" },
  532. { "EP,", "Poland" },
  533. { "EN,", "Norway" },
  534. { "EL,", "Luxembourg" },
  535. { "EK,", "Denmark/Faroe Island" },
  536. { "EI,", "Ireland" },
  537. { "EH,", "Netherlands" },
  538. { "EG,LX,", "United Kingdom" },
  539. { "EF,", "Finland" },
  540. { "EE,", "Estonia" },
  541. { "ED,ET,", "Germany" },
  542. { "EB,", "Belgium" },
  543. { "DX,", "Togo" },
  544. { "DT,", "Tunisia" },
  545. { "DR,", "Niger" },
  546. { "DN,", "Nigeria" },
  547. { "DI,", "Ivory Coast" },
  548. { "DG,", "Ghana" },
  549. { "DF,", "Burkina Faso" },
  550. { "DB,", "Benin" },
  551. { "DA,", "Algeria" },
  552. { "C*,", "Canada" },
  553. { "BI,", "Iceland" },
  554. { "BG,", "Greenland" },
  555. { "AY,", "Papua New Guinea" },
  556. { "AN,", "Nauru" },
  557. { "AG,", "Solomon Island" },
  558. { NULL, NULL }
  559. };
  560. /* gt_waypt_classes: gdb internal order */
  561. const char* gt_waypt_class_names[] = {
  562. "User Waypoint",
  563. "Airport",
  564. "Intersection",
  565. "NDB",
  566. "VOR",
  567. "Runway Threshold",
  568. "Airport Intersection",
  569. "Airport NDB",
  570. "Map Point",
  571. "Map Area",
  572. "Map Intersection",
  573. "Map Address",
  574. "Map Line",
  575. NULL
  576. };
  577. /* gt_display_mode_names: this order is used by most devices */
  578. const char* gt_display_mode_names[] = {
  579. "Symbol & Name",
  580. "Symbol",
  581. "Symbol & Description"
  582. };
  583. typedef struct {
  584. const char* shortname;
  585. const char* longname;
  586. grid_type grid;
  587. } grid_mapping_t;
  588. /* gt_mps_grid_names: !!! degree sign substituted with '*' !!! */
  589. grid_mapping_t gt_mps_grid_names[] = {
  590. { "ddd", "Lat/Lon hddd.ddddd*", grid_lat_lon_ddd },
  591. { "dmm", "Lat/Lon hddd*mm.mmm'", grid_lat_lon_dmm },
  592. { "dms", "Lat/Lon hddd*mm'ss.s\"", grid_lat_lon_dms },
  593. { "bng", "British National Grid", grid_bng },
  594. { "utm", "UTM", grid_utm },
  595. { "swiss", "Swiss grid", grid_swiss },
  596. { NULL, NULL, (grid_type) 0 }
  597. };
  598. /* gt_mps_datum_names: */
  599. typedef struct {
  600. const char* jeeps_name;
  601. const char* mps_name;
  602. } datum_mapping_t;
  603. /* will be continued (when requested) */
  604. static datum_mapping_t gt_mps_datum_names[] = {
  605. { "Alaska-NAD27", "NAD27 Alaska" },
  606. { "Bahamas NAD27", "NAD27 Bahamas" },
  607. { "Canada_Mean(NAD27)", "NAD27 Canada" },
  608. { "Canal_Zone_(NAD27)", "NAD27 Canal Zone" },
  609. { "Carribean NAD27", "NAD27 Caribbean" },
  610. { "Cent America NAD27", "NAD27 Central" },
  611. { "Cuba NAD27", "NAD27 Cuba" },
  612. { "Geodetic Datum 49", "Geodetic Datum '49" },
  613. { "Greenland NAD27", "NAD27 Greenland" },
  614. { "Mexico NAD27", "NAD27 Mexico" },
  615. { "North America 83", "NAD83" },
  616. { "OSGB36", "Ord Srvy Grt Britn" },
  617. { NULL, NULL }
  618. };
  619. typedef struct garmin_color_s {
  620. const char* name;
  621. int32_t rgb;
  622. } garmin_color_t;
  623. static garmin_color_t gt_colors[] = {
  624. { "Unknown", unknown_color },
  625. { "Black", 0x000000 },
  626. { "DarkRed", 0x00008B },
  627. { "DarkGreen", 0x006400 },
  628. { "DarkYellow", 0x008B8B },
  629. { "DarkBlue", 0x8B0000 },
  630. { "DarkMagenta", 0x8B008B },
  631. { "DarkCyan", 0x8B8B00 },
  632. { "LightGray", 0xD3D3D3 },
  633. { "DarkGray", 0xA9A9A9 },
  634. { "Red", 0x0000FF },
  635. { "Green", 0x008000 },
  636. { "Yellow", 0x00FFFF },
  637. { "Blue", 0xFF0000 },
  638. { "Magenta", 0xFF00FF },
  639. { "Cyan", 0xFFFF00 },
  640. { "White", 0xFFFFFF },
  641. { "Transparent", unknown_color }, /* Currently not handled */
  642. { NULL, 0 }
  643. };
  644. #define GT_COLORS_CT ((sizeof(gt_colors) / sizeof(gt_colors[0])) - 1)
  645. unsigned char
  646. gt_switch_display_mode_value(const unsigned char display_mode, const int protoid, const char device)
  647. {
  648. if (device) {
  649. switch (protoid) {
  650. case 103:
  651. case 107:
  652. case 108:
  653. case 109:
  654. case 110:
  655. return display_mode & 3;
  656. break;
  657. case 104:
  658. switch (display_mode) {
  659. case 0:
  660. case 1:
  661. return gt_display_mode_symbol;
  662. case 3:
  663. return gt_display_mode_symbol_and_name;
  664. case 5:
  665. return gt_display_mode_symbol_and_comment;
  666. }
  667. case 155:
  668. switch (display_mode) {
  669. case 1:
  670. return gt_display_mode_symbol;
  671. case 3:
  672. return gt_display_mode_symbol_and_name;
  673. case 5:
  674. return gt_display_mode_symbol_and_comment;
  675. }
  676. }
  677. return gt_display_mode_symbol_and_name;
  678. } else {
  679. switch (protoid) {
  680. case 103:
  681. case 107:
  682. case 108:
  683. case 109:
  684. case 110:
  685. return display_mode & 3;
  686. case 104:
  687. case 155:
  688. switch (display_mode) {
  689. case gt_display_mode_symbol:
  690. return 1;
  691. case gt_display_mode_symbol_and_name:
  692. return 3;
  693. case gt_display_mode_symbol_and_comment:
  694. return 5;
  695. }
  696. }
  697. return 0;
  698. }
  699. }
  700. const QString
  701. gt_find_desc_from_icon_number(const int icon, garmin_formats_e garmin_format)
  702. {
  703. if ((garmin_format == GDB) && (icon >= 500) && (icon <= 563)) {
  704. return QString("Custom %1").arg(icon - 500);
  705. }
  706. if ((garmin_format == PCX) && (icon >= 7680) && (icon <= 8191)) {
  707. return QString("Custom %1").arg(icon - 7680);
  708. }
  709. for (icon_mapping_t* i = garmin_icon_table; i->icon; i++) {
  710. switch (garmin_format) {
  711. case MAPSOURCE:
  712. case GDB:
  713. if (icon == i->mpssymnum) {
  714. return i->icon;
  715. }
  716. break;
  717. case PCX:
  718. case GARMIN_SERIAL:
  719. if (icon == i->pcxsymnum) {
  720. return i->icon;
  721. }
  722. break;
  723. default:
  724. fatal(MYNAME ": unknown garmin format.\n");
  725. }
  726. }
  727. return DEFAULT_ICON_DESCR;
  728. }
  729. int gt_find_icon_number_from_desc(const QString& desc, garmin_formats_e garmin_format)
  730. {
  731. static int find_flag = 0;
  732. icon_mapping_t* i;
  733. int def_icon = DEFAULT_ICON_VALUE;
  734. int n;
  735. if (desc.isNull()) {
  736. return def_icon;
  737. }
  738. /*
  739. * If we were given a numeric icon number as a description
  740. * (i.e. 8255), just return that.
  741. */
  742. n = desc.toInt();
  743. if (n) {
  744. return n;
  745. }
  746. if (desc.startsWith("Custom ", Qt::CaseInsensitive)) {
  747. int base = 0;
  748. if (garmin_format == GDB) {
  749. base = 500;
  750. }
  751. if (garmin_format == PCX) {
  752. base = 7680;
  753. }
  754. if (base) {
  755. n = desc.mid(7).toInt();
  756. return n + base;
  757. }
  758. }
  759. for (i = garmin_smart_icon_table; global_opts.smart_icons && i->icon; i++) {
  760. if (desc.compare(i->icon, Qt::CaseInsensitive) == 0) {
  761. switch (garmin_format) {
  762. case MAPSOURCE:
  763. case GDB:
  764. return i->mpssymnum;
  765. case PCX:
  766. case GARMIN_SERIAL:
  767. return i->pcxsymnum;
  768. default:
  769. fatal(MYNAME ": unknown garmin format.\n");
  770. }
  771. }
  772. }
  773. for (i = garmin_icon_table; i->icon; i++) {
  774. if (desc.compare(i->icon, Qt::CaseInsensitive) == 0) {
  775. switch (garmin_format) {
  776. case MAPSOURCE:
  777. case GDB:
  778. return i->mpssymnum;
  779. case PCX:
  780. case GARMIN_SERIAL:
  781. return i->pcxsymnum;
  782. default:
  783. fatal(MYNAME ": unknown garmin format.\n");
  784. }
  785. }
  786. }
  787. /*
  788. * try to handle some complex icon names: i.e. "Blue Diamond" and "Diamond, Blue"
  789. * "find_flag" prevents us from a possible endless loop
  790. */
  791. if (find_flag == 0) {
  792. const char** prefix;
  793. const char* prefixes[] = {
  794. "White ", "Red ", "Green ", "Blue ", "Black ", NULL
  795. };
  796. // Rewrite "Green Square" to "Square, Green".
  797. for (prefix = prefixes; *prefix != NULL; prefix++) {
  798. if (desc.startsWith(*prefix, Qt::CaseInsensitive)) {
  799. QString buff = desc;
  800. buff.replace(*prefix, "");
  801. buff.append(", ");
  802. buff.append(*prefix);
  803. buff = buff.trimmed();
  804. find_flag = 1;
  805. int result = gt_find_icon_number_from_desc(buff, garmin_format);
  806. find_flag = 0;
  807. return result;
  808. }
  809. }
  810. }
  811. return def_icon;
  812. }
  813. const char*
  814. gt_get_icao_country(const QString& cc)
  815. {
  816. gt_country_code_t* x = &gt_country_codes[0];
  817. if (cc.isEmpty()) {
  818. return NULL;
  819. }
  820. do {
  821. const char* ccx = x->cc;
  822. const QString qccx = x->cc;
  823. while (ccx != NULL) {
  824. if (qccx.left(2) == cc) {
  825. return x->country;
  826. }
  827. if ((ccx[0] == cc[0]) && (ccx[1] == '*')) {
  828. return x->country;
  829. }
  830. ccx = strchr(ccx, ',');
  831. if (ccx == NULL) {
  832. break;
  833. }
  834. ccx++;
  835. }
  836. x++;
  837. } while (x->cc != NULL);
  838. return NULL;
  839. }
  840. const char*
  841. gt_get_icao_cc(const QString& country, const QString& shortname)
  842. {
  843. static char res[3];
  844. gt_country_code_t* x = &gt_country_codes[0];
  845. if (country.isEmpty()) {
  846. const char* test;
  847. if (shortname == NULL) {
  848. return NULL;
  849. }
  850. switch (shortname.length()) {
  851. case 3:
  852. strncpy(res, CSTR(shortname), 1);
  853. break;
  854. case 4:
  855. strncpy(res, CSTR(shortname), 2);
  856. break;
  857. default:
  858. return NULL;
  859. }
  860. test = gt_get_icao_country(res);
  861. if (test != NULL) {
  862. return res;
  863. } else {
  864. return NULL;
  865. }
  866. }
  867. do {
  868. if (country.compare(x->country, Qt::CaseInsensitive) != 0) {
  869. x++;
  870. continue;
  871. }
  872. if (strlen(x->cc) <= 3) {
  873. strncpy(res, x->cc, 3);
  874. if (res[1] == '*') {
  875. res[1] = '\0';
  876. } else {
  877. res[2] = '\0';
  878. }
  879. return res;
  880. }
  881. if (shortname.length() == 4) {
  882. const char* ccx = x->cc;
  883. strncpy(res, CSTR(shortname), 2);
  884. res[2] = '\0';
  885. while (ccx != NULL) {
  886. if (strncmp(ccx, res, 2) == 0) {
  887. return res;
  888. }
  889. if ((ccx[0] == res[0]) && (ccx[1] == '*')) {
  890. return res;
  891. }
  892. ccx = strchr(ccx, ',');
  893. if (ccx == NULL) {
  894. break;
  895. }
  896. ccx++;
  897. }
  898. }
  899. return NULL;
  900. } while (x->country != NULL);
  901. return NULL;
  902. }
  903. grid_type
  904. gt_lookup_grid_type(const char* grid_name, const QString& module)
  905. {
  906. grid_mapping_t* g;
  907. for (g = gt_mps_grid_names; (g->shortname); g++) {
  908. if (QString::compare(grid_name, g->shortname, Qt::CaseInsensitive) == 0 ||
  909. QString::compare(grid_name, g->longname,Qt::CaseInsensitive) == 0) {
  910. return g->grid;
  911. }
  912. }
  913. Fatal() << module << ": Unsupported grid (" << grid_name <<
  914. ". See GPSBabel help for supported grids.\n";
  915. return grid_unknown; /* (warnings) */
  916. }
  917. const char*
  918. gt_get_mps_grid_longname(const grid_type grid, const char* module)
  919. {
  920. if ((grid < GRID_INDEX_MIN) || (grid > GRID_INDEX_MAX))
  921. fatal("%s: Grid index out of range %d (%d..%d)!",
  922. module, (int) grid,
  923. (int)GRID_INDEX_MIN, (int)GRID_INDEX_MAX);
  924. return gt_mps_grid_names[grid].longname;
  925. }
  926. const char*
  927. gt_get_mps_datum_name(const int datum_index)
  928. {
  929. const char* result;
  930. datum_mapping_t* d;
  931. result = GPS_Math_Get_Datum_Name(datum_index);
  932. for (d = gt_mps_datum_names; (d->jeeps_name); d++)
  933. if (QString::compare(result, d->jeeps_name, Qt::CaseInsensitive) == 0) {
  934. return d->mps_name;
  935. }
  936. return result;
  937. }
  938. int
  939. gt_lookup_datum_index(const char* datum_str, const QString& module)
  940. {
  941. datum_mapping_t* d;
  942. int result;
  943. const char* name = datum_str;
  944. for (d = gt_mps_datum_names; (d->jeeps_name); d++) {
  945. if (QString::compare(name, d->mps_name, Qt::CaseInsensitive) == 0) {
  946. name = d->jeeps_name;
  947. break;
  948. }
  949. }
  950. result = GPS_Lookup_Datum_Index(name);
  951. // Didn't get a hit? Try again after modifying the lookup.
  952. if (result < 0) {
  953. QString tmp = QString(datum_str) + " mean";
  954. result = GPS_Lookup_Datum_Index(tmp);
  955. }
  956. if (result < 0) {
  957. Fatal() << module << ": Unsupported datum (" << datum_str <<
  958. "). See GPSBabel help for supported datums.";
  959. }
  960. return result;
  961. }
  962. uint32_t
  963. gt_color_value(const unsigned int garmin_index)
  964. {
  965. if ((garmin_index < GT_COLORS_CT)) {
  966. return gt_colors[garmin_index].rgb;
  967. } else {
  968. return unknown_color; /* -1 */
  969. }
  970. }
  971. uint32_t
  972. gt_color_value_by_name(const QString& name)
  973. {
  974. unsigned int i;
  975. for (i = 0; i < GT_COLORS_CT; i++)
  976. if (QString::compare(gt_colors[i].name, name, Qt::CaseInsensitive) == 0) {
  977. return gt_colors[i].rgb;
  978. }
  979. return gt_colors[0].rgb;
  980. }
  981. int
  982. gt_color_index_by_name(const QString& name)
  983. {
  984. unsigned int i;
  985. for (i = 0; i < GT_COLORS_CT; i++)
  986. if (QString::compare(gt_colors[i].name, name, Qt::CaseInsensitive) == 0) {
  987. return i;
  988. }
  989. return 0; /* unknown */
  990. }
  991. int
  992. gt_color_index_by_rgb(const int rgb)
  993. {
  994. unsigned int i;
  995. for (i = 0; i < GT_COLORS_CT; i++)
  996. if (rgb == gt_colors[i].rgb) {
  997. return i;
  998. }
  999. return 0; /* unknown */
  1000. }
  1001. const char*
  1002. gt_color_name(const unsigned int garmin_index)
  1003. {
  1004. if ((garmin_index < GT_COLORS_CT)) {
  1005. return gt_colors[garmin_index].name;
  1006. } else {
  1007. return gt_colors[0].name;
  1008. }
  1009. }
  1010. #if MAKE_TABLE
  1011. /*
  1012. * Used to generate icon tables in appendix.
  1013. * cc -DMAKE_TABLE garmin_tables.c fatal.o util.o globals.o -lm
  1014. */
  1015. int cet_utf8_to_ucs4(const char* str, int* bytes, int* value)
  1016. {
  1017. fatal("Should not be here.");
  1018. }
  1019. int
  1020. sortem(const void* a, const void* b)
  1021. {
  1022. const icon_mapping_t* aa = a;
  1023. const icon_mapping_t* bb = b;
  1024. // return aa->mpssymnum - bb->mpssymnum;
  1025. return strcmp(aa->icon, bb->icon);
  1026. }
  1027. main()
  1028. {
  1029. icon_mapping_t* i;
  1030. qsort(garmin_icon_table, sizeof(garmin_icon_table) / sizeof(garmin_icon_table[0]) - 1, sizeof(garmin_icon_table[0]), sortem);
  1031. for (i = garmin_icon_table; i->icon; i++) {
  1032. // printf("%03d\t%s\n", i->mpssymnum, i->icon);
  1033. printf("<member>%s</member>\n", i->icon);
  1034. }
  1035. }
  1036. #endif