1 /***************************************************************************
2  *
3  * Project:  OpenCPN
4  *
5  ***************************************************************************
6  *   Copyright (C) 2010 by David S. Register                               *
7  *                                                                         *
8  *   This program is free software; you can redistribute it and/or modify  *
9  *   it under the terms of the GNU General Public License as published by  *
10  *   the Free Software Foundation; either version 2 of the License, or     *
11  *   (at your option) any later version.                                   *
12  *                                                                         *
13  *   This program is distributed in the hope that it will be useful,       *
14  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
15  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
16  *   GNU General Public License for more details.                          *
17  *                                                                         *
18  *   You should have received a copy of the GNU General Public License     *
19  *   along with this program; if not, write to the                         *
20  *   Free Software Foundation, Inc.,                                       *
21  *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,  USA.         *
22  ***************************************************************************
23  */
24 
25 #include "AIS_Target_Data.h"
26 
27 extern bool bGPSValid;
28 extern bool g_bAISRolloverShowClass;
29 extern bool g_bAISRolloverShowCOG;
30 extern bool g_bAISRolloverShowCPA;
31 extern bool g_bShowMag;
32 extern bool g_bShowTrue;
33 extern MyFrame *gFrame;
34 extern bool g_bAISShowTracks;
35 
36 
37 //    Define and declare a hasmap for ERI Ship type strings, keyed by their UN Codes.
38 WX_DECLARE_HASH_MAP(int, wxString, wxIntegerHash, wxIntegerEqual, ERIShipTypeHash);
39 
40 static ERIShipTypeHash s_ERI_hash;
41 
make_hash_ERI(int key,const wxString & description)42 void make_hash_ERI(int key, const wxString & description)
43 {
44 	s_ERI_hash[key] = description;
45 }
46 
clear_hash_ERI()47 void clear_hash_ERI()
48 {
49     s_ERI_hash.clear();
50 }
51 
FormatTimeAdaptive(int seconds)52 static wxString FormatTimeAdaptive( int seconds )
53 {
54     int m = seconds / 60;
55     if( seconds < 100 )
56         return wxString::Format( _T("%3ds"), seconds );
57     else if( seconds < 3600 ) {
58         int m = seconds / 60;
59         int s = seconds % 60;
60         return wxString::Format( _T("%2dmin %02ds"), m, s );
61     }
62     int h = seconds / 3600;
63     m -= h* 60;
64     return wxString::Format( _T("%2dh %02dmin"), h, m );
65 }
66 
html_escape(const wxString & src)67 static wxString html_escape ( const wxString &src)
68 {
69   // Escape &, <, > as well as single and double quotes for HTML.
70   wxString ret = src;
71 
72   ret.Replace(_T("<"), _T("&lt;"));
73   ret.Replace(_T(">"), _T("&gt;"));
74 
75   // only < and > in 6 bits AIS ascii
76   // ret.Replace(_T("\""), _T("&quot;"));
77   // ret.Replace(_T("&"), _T("&amp;"));
78   // ret.Replace(_T("'"), _T("&#39;"));
79 
80   // Do we care about multiple spaces?
81   //   ret.Replace(_T(" "), _T("&nbsp;"));
82   return ret;
83 }
84 
AIS_Target_Data()85 AIS_Target_Data::AIS_Target_Data()
86 {
87     strncpy(ShipName, "Unknown             ", SHIP_NAME_LEN);
88     strncpy(CallSign, "       ", 8);
89     strncpy(Destination, "                    ", SHIP_NAME_LEN);
90     ShipNameExtension[0] = 0;
91     b_show_AIS_CPA = false;
92 
93     SOG = 555.;
94     COG = 666.;
95     HDG = 511.;
96     ROTAIS = -128;
97     Lat = 0.;
98     Lon = 0.;
99 
100     wxDateTime now = wxDateTime::Now();
101     now.MakeGMT();
102     PositionReportTicks = now.GetTicks();       // Default is my idea of NOW
103     StaticReportTicks = now.GetTicks();
104     b_lost = false;
105     b_removed = false;
106 
107     IMO = 0;
108     MID = 555;
109     MMSI = 666;
110     NavStatus = UNDEFINED;
111     SyncState = 888;
112     SlotTO = 999;
113     ShipType = 19;    // "Unknown"
114 
115     CPA = 100;     // Large values avoid false alarms
116     TCPA = 100;
117 
118     Range_NM = -1.;
119     Brg = -1.;
120 
121     DimA = DimB = DimC = DimD = 0;;
122 
123     ETA_Mo = 0;
124     ETA_Day = 0;
125     ETA_Hr = 24;
126     ETA_Min = 60;
127 
128     Draft = 0.;
129 
130     RecentPeriod = 0;
131 
132     m_utc_hour = 0;
133     m_utc_min = 0;
134     m_utc_sec = 0;
135 
136     Class = AIS_CLASS_A;      // default
137     n_alert_state = AIS_NO_ALERT;
138     b_suppress_audio = false;
139     b_positionDoubtful = false;
140     b_positionOnceValid = false;
141     b_nameValid = false;
142 
143     Euro_Length = 0;            // Extensions for European Inland AIS
144     Euro_Beam = 0;
145     Euro_Draft = 0;
146     strncpy(Euro_VIN, "       ", 8);
147     UN_shiptype = 0;
148 
149     b_isEuroInland = false;
150     b_blue_paddle = false;
151 
152     b_NoTrack = false;
153     b_OwnShip = false;
154     b_PersistTrack = false;
155     b_in_ack_timeout = false;
156 
157     m_ptrack = new AISTargetTrackList;
158     m_ptrack->DeleteContents(true);
159 
160     b_active = false;
161     blue_paddle = 0;
162     bCPA_Valid = false;
163     ROTIND = 0;
164     b_show_track = g_bAISShowTracks;
165     b_SarAircraftPosnReport = false;
166     altitude = 0;
167     b_nameFromCache = false;
168     importance = 0.0;
169     for(unsigned int i=0 ; i < AIS_TARGETDATA_MAX_CANVAS ; i++)
170         last_scale[i] = 50;
171 }
172 
CloneFrom(AIS_Target_Data * q)173 void AIS_Target_Data::CloneFrom( AIS_Target_Data* q )
174 {
175     strncpy(ShipName, q->ShipName, SHIP_NAME_LEN);
176     strncpy(CallSign, q->CallSign, 8);
177     strncpy(Destination, q->Destination, SHIP_NAME_LEN);
178     ShipNameExtension[0] = 0;
179     b_show_AIS_CPA = q->b_show_AIS_CPA;;
180 
181     SOG = q->SOG;
182     COG = q->COG;
183     HDG = q->HDG;
184     ROTAIS = q->ROTAIS;
185     Lat = q->Lat;
186     Lon = q->Lon;
187 
188     PositionReportTicks = q->PositionReportTicks;
189     StaticReportTicks = q->StaticReportTicks;
190     b_lost = q->b_lost;
191     b_removed = q->b_removed;
192 
193     IMO = q->IMO;
194     MID = q->MID;
195     MMSI = q->MMSI;
196     NavStatus = q->NavStatus;
197     SyncState = q->SyncState;
198     SlotTO = q->SlotTO;
199     ShipType = q->ShipType;
200 
201     CPA = q->CPA;
202     TCPA = q->TCPA;
203 
204     Range_NM = q->Range_NM;
205     Brg = q->Brg;
206 
207     DimA = q->DimA;
208     DimB = q->DimB;
209     DimC = q->DimC;
210     DimD = q->DimD;
211 
212     ETA_Mo = q->ETA_Mo;
213     ETA_Day = q->ETA_Day;
214     ETA_Hr = q->ETA_Hr;
215     ETA_Min = q->ETA_Min;
216 
217     Draft = q->Draft;
218 
219     RecentPeriod = q->RecentPeriod;
220 
221     m_utc_hour = q->m_utc_hour;
222     m_utc_min = q->m_utc_min;
223     m_utc_sec = q->m_utc_sec;
224 
225     Class = q->Class;
226     n_alert_state = q->n_alert_state;
227     b_suppress_audio = q->b_suppress_audio;
228     b_positionDoubtful = q->b_positionDoubtful;
229     b_positionOnceValid = q->b_positionOnceValid;
230     b_nameValid = q->b_nameValid;
231 
232     Euro_Length = q->Euro_Length;            // Extensions for European Inland AIS
233     Euro_Beam = q->Euro_Beam;
234     Euro_Draft = q->Euro_Draft;
235     memcpy(Euro_VIN, q->Euro_VIN, EURO_VIN_LEN);
236     UN_shiptype = q->UN_shiptype;
237 
238     b_isEuroInland = q->b_isEuroInland;
239     b_blue_paddle = q->b_blue_paddle;
240 
241     b_OwnShip = q->b_OwnShip;
242     b_in_ack_timeout = q->b_in_ack_timeout;
243 
244     m_ptrack = new AISTargetTrackList;
245     m_ptrack->DeleteContents(true);
246 
247     wxAISTargetTrackListNode *node = q->m_ptrack->GetFirst();
248     while( node ) {
249         AISTargetTrackPoint *ptrack_point = node->GetData();
250         m_ptrack->Append( ptrack_point );
251         node = node->GetNext();
252     }
253 
254 
255     b_active = q->b_active;
256     blue_paddle = q->blue_paddle;
257     bCPA_Valid = q->bCPA_Valid;
258     ROTIND = q->ROTIND;
259     b_show_track = q->b_show_track;
260     b_SarAircraftPosnReport = q->b_SarAircraftPosnReport;
261     altitude = q->altitude;
262 }
263 
264 
~AIS_Target_Data()265 AIS_Target_Data::~AIS_Target_Data()
266 {
267     m_ptrack->Clear();
268     delete m_ptrack;
269 }
270 
GetFullName(void)271 wxString AIS_Target_Data::GetFullName( void )
272 {
273     wxString retName;
274     if( b_nameValid ) {
275         wxString shipName = trimAISField( ShipName );
276         if( shipName == _T("Unknown") )
277             retName = wxGetTranslation( shipName );
278         else
279             retName = shipName;
280 
281         if( strlen( ShipNameExtension ) ) {
282             wxString shipNameExt = trimAISField( ShipNameExtension );
283             retName += shipNameExt;
284         }
285     }
286 
287     return retName;
288 }
289 
290 
BuildQueryResult(void)291 wxString AIS_Target_Data::BuildQueryResult( void )
292 {
293     wxString html;
294     wxDateTime now = wxDateTime::Now();
295 
296     wxString tableStart = _T("\n<table border=0 cellpadding=1 cellspacing=0>\n");
297     wxString tableEnd = _T("</table>\n\n");
298     wxString rowStart = _T("<tr><td><font size=-2>");
299     wxString rowStartH = _T("<tr><td nowrap>");
300     wxString rowSeparator = _T("</font></td><td></td><td><b>");
301     wxString rowSeparatorH = _T("</td><td></td><td>");
302     wxString colSeparator = _T("<td></td>");
303     wxString rowEnd = _T("</b></td></tr>\n");
304     wxString vertSpacer = _T("<tr><td></td></tr><tr><td></td></tr><tr><td></td></tr>\n\n");
305 
306     wxString IMOstr, MMSIstr, ClassStr;
307 
308     html << tableStart << _T("<tr><td nowrap colspan=2>");
309     if( /*( Class != AIS_BASE ) &&*/ ( Class != AIS_SART ) ) {
310         if( b_nameValid ) {
311             html << _T("<font size=+2><i><b>") << GetFullName() ;
312             html << _T("</b></i></font>&nbsp;&nbsp;<b>");
313         }
314     }
315 
316     if( ( Class != AIS_ATON ) && ( Class != AIS_BASE ) && ( Class != AIS_GPSG_BUDDY )
317             && ( Class != AIS_SART ) ) {
318         html << trimAISField( CallSign ) << _T("</b>") << rowEnd;
319 
320         if( Class != AIS_CLASS_B ) {
321             if( IMO > 0 ) IMOstr = wxString::Format( _T("%08d"), abs( IMO ) );
322         }
323     }
324     else html << _T("</b>") << rowEnd;
325 
326     html << vertSpacer;
327 
328     if( Class != AIS_GPSG_BUDDY ) {
329         MMSIstr = wxString::Format( _T("%09d"), abs( MMSI ) );
330     }
331     ClassStr = wxGetTranslation( Get_class_string( false ) );
332 
333     if( Class == AIS_ATON ) {
334         wxString cls(_T("AtoN: ") );
335         cls += Get_vessel_type_string(false);
336         ClassStr = wxGetTranslation( cls );
337     }
338 
339     if (b_SarAircraftPosnReport) {
340         int airtype = (MMSI % 1000) / 100;
341         ClassStr = airtype == 5 ? _("SAR Helicopter") : _("SAR Aircraft");
342     }
343 
344     if( IMOstr.Length() )
345         html << _T("<tr><td colspan=2><table width=100% border=0 cellpadding=0 cellspacing=0>")
346             << rowStart <<_("MMSI") << _T("</font></td><td>&nbsp;</td><td><font size=-2>")
347             << _("Class") << _T("</font></td><td>&nbsp;</td><td align=right><font size=-2>")
348             << _("IMO") << _T("</font></td></tr>")
349             << rowStartH << _T("<b>") << MMSIstr << _T("</b></td><td>&nbsp;</td><td><b>")
350             << ClassStr << _T("</b></td><td>&nbsp;</td><td align=right><b>")
351             << IMOstr << rowEnd << _T("</table></td></tr>");
352 
353     else
354        html << _T("<tr><td colspan=2><table width=100% border=0 cellpadding=0 cellspacing=0>")
355             << rowStart <<_("MMSI") << _T("</font></td><td>&nbsp;</td><td align=right><font size=-2>")
356             << _("Class") << _T("</font></td></tr>")
357             << rowStartH << _T("<b>") << MMSIstr << _T("</b></td><td>&nbsp;</td><td align=right><b>")
358             << ClassStr << rowEnd << _T("</table></td></tr>");
359 
360     if ((Class != AIS_SART) && (Class != AIS_DSC))
361         html << _T("<tr><td colspan=2><table width=100% border=0 cellpadding=0 cellspacing=0>")
362              << rowStart << ((Class == AIS_BASE || Class == AIS_ATON) ? _("Nation") : _("Flag"))
363              << rowEnd << _T("</font></td></tr>")
364              << rowStartH << _T("<b>")<< GetCountryCode(true) << rowEnd << _T("</table></td></tr>");
365 
366     html << vertSpacer;
367 
368     wxString navStatStr;
369     if( ( Class != AIS_BASE ) && ( Class != AIS_CLASS_B ) && ( Class != AIS_SART ) ) {
370         if( ( NavStatus <= 21  ) && ( NavStatus >= 0 ) )
371             navStatStr = wxGetTranslation(ais_get_status(NavStatus));
372     } else if( Class == AIS_SART ) {
373         if( NavStatus == RESERVED_14 ) navStatStr = _("Active");
374         else if( NavStatus == UNDEFINED ) navStatStr = _("Testing");
375     }
376 
377     wxString sart_sub_type;
378     if( Class == AIS_SART ) {
379         int mmsi_start = MMSI / 1000000;
380         switch( mmsi_start ){
381             case 970:
382 //                sart_sub_type = _T("SART");
383                 break;
384             case 972:
385                 sart_sub_type = _T("MOB");
386                 break;
387             case 974:
388                 sart_sub_type = _T("EPIRB");
389                 break;
390             default:
391                 sart_sub_type = _("Unknown");
392                 break;
393         }
394     }
395 
396     wxString AISTypeStr, UNTypeStr, sizeString;
397     if( ( Class != AIS_BASE ) && ( Class != AIS_SART ) && ( Class != AIS_DSC ) ) {
398 
399         //      Ship type
400         AISTypeStr = wxGetTranslation( Get_vessel_type_string() );
401 
402         if( b_isEuroInland && UN_shiptype ) {
403             ERIShipTypeHash::iterator it = s_ERI_hash.find( UN_shiptype );
404             wxString type;
405             if( it == s_ERI_hash.end() ) type = _("Undefined");
406             else
407                 type = it->second;
408 
409             UNTypeStr = wxGetTranslation( type );
410         }
411 
412         if( b_SarAircraftPosnReport ){
413             AISTypeStr.Clear();
414             UNTypeStr.Clear();
415             navStatStr.Clear();
416         }
417 
418 
419         if( Class == AIS_SART ) {
420             if( MSG_14_text.Len() ) {
421                 html << rowStart << _("Safety Broadcast Message") << rowEnd
422                     << rowStartH << _T("<b>") << MSG_14_text << rowEnd;
423             }
424         }
425 
426        //  Dimensions
427 
428         if( NavStatus != ATON_VIRTUAL && Class != AIS_ARPA && Class != AIS_APRS ) {
429             if( ( Class == AIS_CLASS_B ) || ( Class == AIS_ATON ) ) {
430                 sizeString = wxString::Format( _T("%dm x %dm"), ( DimA + DimB ), ( DimC + DimD ) );
431             } else if(!b_SarAircraftPosnReport) {
432                 if( ( DimA + DimB + DimC + DimD ) == 0 ) {
433                     if( b_isEuroInland ) {
434                         if( Euro_Length == 0.0 ) {
435                             if( Euro_Draft > 0.01 ) {
436                                 sizeString << wxString::Format( _T("---m x ---m x %4.1fm"), Euro_Draft );
437                             } else {
438                                 sizeString << _T("---m x ---m x ---m");
439                             }
440                         } else {
441                             if( Euro_Draft > 0.01 ) {
442                                 sizeString
443                                         << wxString::Format( _T("%5.1fm x %4.1fm x %4.1fm"), Euro_Length,
444                                                 Euro_Beam, Euro_Draft );
445                             } else {
446                                 sizeString
447                                         << wxString::Format( _T("%5.1fm x %4.1fm x ---m\n\n"), Euro_Length,
448                                                 Euro_Beam );
449                             }
450                         }
451                     } else {
452                         if( Draft > 0.01 ) {
453                             sizeString << wxString::Format( _T("---m x ---m x %4.1fm"), Draft );
454                         } else {
455                             sizeString << _T("---m x ---m x ---m");
456                         }
457                     }
458                 } else if( Draft < 0.01 ) {
459                     sizeString
460                             << wxString::Format( _T("%dm x %dm x ---m"), ( DimA + DimB ), ( DimC + DimD ) );
461                 } else {
462                     sizeString
463                             << wxString::Format( _T("%dm x %dm x %4.1fm"), ( DimA + DimB ), ( DimC + DimD ),
464                                     Draft );
465                 }
466             }
467         }
468     }
469 
470     if( Class == AIS_SART ) {
471         html << _T("<tr><td colspan=2>") << _T("<b>") << AISTypeStr;
472         if( sart_sub_type.Length() )
473             html << _T(" (") << sart_sub_type << _T("), ");
474         html << navStatStr;
475         html << rowEnd << _T("<tr><td colspan=2>") << _T("<b>") << sizeString << rowEnd;
476     }
477 
478     else if( Class == AIS_ATON )  {
479         html << _T("<tr><td colspan=2>") << _T("<b>") << navStatStr;
480         html << rowEnd << _T("<tr><td colspan=2>") << _T("<b>") << sizeString << rowEnd;
481     }
482 
483     else if( ( Class != AIS_BASE ) && ( Class != AIS_DSC ) ) {
484         html << _T("<tr><td colspan=2>") << _T("<b>") << AISTypeStr;
485         if( navStatStr.Length() )
486             html << _T(", ") << navStatStr;
487         if( UNTypeStr.Length() )
488             html << _T(" (UN Type ") << UNTypeStr << _T(")");
489         html << rowEnd << _T("<tr><td colspan=2>") << _T("<b>") << sizeString << rowEnd;
490     }
491 
492     if( b_positionOnceValid ) {
493         wxString posTypeStr;
494         if( b_positionDoubtful ) posTypeStr << _(" (Last Known)");
495 
496         now.MakeGMT();
497         int target_age = now.GetTicks() - PositionReportTicks;
498      //   wxLogMessage(wxString::Format(_T("** PositionReportTicks %ld %ld %d"),
499      //                                 now.GetTicks(), PositionReportTicks, target_age));
500 
501         html << vertSpacer
502              << rowStart << _("Position") << posTypeStr << _T("</font></td><td align=right><font size=-2>")
503              << _("Report Age") << _T("</font></td></tr>")
504 
505              << rowStartH << _T("<b>") << toSDMM( 1, Lat ) << _T("</b></td><td align=right><b>")
506              << FormatTimeAdaptive( target_age ) << rowEnd
507              << rowStartH << _T("<b>") << toSDMM( 2, Lon ) << rowEnd;
508     }
509 
510     wxString courseStr, sogStr, hdgStr, rotStr, rngStr, brgStr, destStr, etaStr;
511 
512     if( Class == AIS_GPSG_BUDDY ) {
513         long month, year, day;
514         m_date_string.Mid(0,2).ToLong(&day);
515         m_date_string.Mid(2,2).ToLong(&month);
516         m_date_string.Mid(4,2).ToLong(&year);
517         wxDateTime date;
518         date.SetDay(day);
519         date.SetMonth((wxDateTime::Month)(month-1));
520         date.SetYear(year + 2000);
521 
522         wxString f_date = date.FormatISODate();
523 
524         html << vertSpacer << rowStart << _("Report as of") << rowEnd
525              << rowStartH << _T("<b>")
526              << f_date + _T("</b> at <b>")
527              << wxString::Format( _T("%d:%d UTC "), m_utc_hour, m_utc_min )
528              << rowEnd;
529     } else {
530         if( Class == AIS_CLASS_A && !b_SarAircraftPosnReport ) {
531             html << vertSpacer << rowStart << _("Destination")
532                  << _T("</font></td><td align=right><font size=-2>")
533                  << _("ETA (UTC)") << _T("</font></td></tr>\n")
534                  << rowStartH << _T("<b>");
535                  wxString dest =  trimAISField( Destination );
536                  if(dest.Length() )
537                      html << html_escape(dest);
538                  else
539                      html << _T("---");
540                  html << _T("</b></td><td nowrap align=right><b>");
541 
542             if( ( ETA_Mo ) && ( ETA_Hr < 24 ) ) {
543                 int yearOffset = 0;
544                 if( now.GetMonth() > ( ETA_Mo - 1 ) ) yearOffset = 1;
545                 wxDateTime eta( ETA_Day, wxDateTime::Month( ETA_Mo - 1 ),
546                         now.GetYear() + yearOffset, ETA_Hr, ETA_Min );
547                 html << eta.Format( _T("%b %d %H:%M") );
548             }
549             else html << _T("---");
550             html << rowEnd;
551         }
552 
553         if( Class == AIS_CLASS_A || Class == AIS_CLASS_B || Class == AIS_ARPA || Class == AIS_APRS ) {
554             int crs = wxRound( COG );
555             if( crs < 360 ) {
556                 wxString magString, trueString;
557                 if( g_bShowMag )
558                     magString << wxString::Format( wxString("%03d°(M)", wxConvUTF8 ), (int)gFrame->GetMag( crs ) );
559                 if( g_bShowTrue )
560                     trueString << wxString::Format( wxString("%03d°  ", wxConvUTF8 ), (int) crs );
561 
562                 courseStr << trueString << magString;
563             }
564             else if( COG == 360.0 )
565                 courseStr = _T("---");
566             else if( crs == 360 )
567                 courseStr = _T("0&deg;");
568 
569             double speed_show = toUsrSpeed( SOG );
570 
571             if( ( SOG <= 102.2 ) || b_SarAircraftPosnReport ){
572                 if( speed_show < 10.0 )
573                     sogStr = wxString::Format( _T("%.2f "), speed_show ) + getUsrSpeedUnit();
574                 else if( speed_show < 100.0 )
575                     sogStr = wxString::Format( _T("%.1f "), speed_show ) + getUsrSpeedUnit();
576                 else
577                     sogStr = wxString::Format( _T("%.0f "), speed_show ) + getUsrSpeedUnit();
578             }
579 //                sogStr = wxString::Format( _T("%5.2f ") + getUsrSpeedUnit(), toUsrSpeed( SOG ) );
580             else
581                 sogStr = _T("---");
582 
583             if( (int) HDG != 511 )
584                 hdgStr = wxString::Format( _T("%03d&deg;"), (int) HDG );
585             else
586                 hdgStr = _T("---");
587 
588 
589             if( ROTAIS != -128 ) {
590                 if( ROTAIS == 127 ) rotStr << _T("> 5&deg;/30s ") << _("Right");
591                 else if( ROTAIS == -127 ) rotStr << _T("> 5&deg;/30s ") << _("Left");
592                 else {
593                     if( ROTIND > 0 ) rotStr << wxString::Format( _T("%3d&deg;/Min "), ROTIND ) << _("Right");
594                     else if( ROTIND < 0 ) rotStr << wxString::Format( _T("%3d&deg;/Min "), -ROTIND ) << _("Left");
595                     else rotStr = _T("0");
596                 }
597             }
598             else if( !b_SarAircraftPosnReport )
599                 rotStr = _T("---");
600         }
601     }
602 
603     if( b_positionOnceValid && bGPSValid && ( Range_NM >= 0. ) )
604         rngStr = FormatDistanceAdaptive( Range_NM );
605     else
606         rngStr = _T("---");
607 
608     int brg = (int) wxRound( Brg );
609     if( Brg > 359.5 )
610         brg = 0;
611     if( b_positionOnceValid && bGPSValid && ( Brg >= 0. ) && ( Range_NM > 0. ) && ( fabs( Lat ) < 85. ) ){
612         wxString magString, trueString;
613         if( g_bShowMag )
614             magString << wxString::Format( wxString("%03d°(M)", wxConvUTF8 ), (int)gFrame->GetMag( Brg ) );
615         if( g_bShowTrue )
616             trueString << wxString::Format( wxString("%03d°  ", wxConvUTF8 ), (int) Brg );
617 
618         brgStr << trueString << magString;
619     }
620     else
621         brgStr = _T("---");
622 
623     wxString turnRateHdr; // Blank if ATON or BASE or Special Position Report (9)
624     if( ( Class != AIS_ATON ) && ( Class != AIS_BASE ) && ( Class != AIS_DSC ) ) {
625         html << vertSpacer << _T("<tr><td colspan=2><table width=100% border=0 cellpadding=0 cellspacing=0>")
626             << rowStart <<_("Speed") << _T("</font></td><td>&nbsp;</td><td><font size=-2>")
627             << _("Course") << _T("</font></td><td>&nbsp;</td><td align=right><font size=-2>");
628             if( !b_SarAircraftPosnReport )
629                 html << _("Heading") ;
630 
631             html << _T("</font></td></tr>")
632             << rowStartH << _T("<b>") << sogStr << _T("</b></td><td>&nbsp;</td><td><b>")
633             << courseStr << _T("</b></td><td>&nbsp;</td><td align=right><b>");
634             if(!b_SarAircraftPosnReport)
635                 html << hdgStr;
636             html  << rowEnd << _T("</table></td></tr>")
637             << vertSpacer;
638 
639             if( !b_SarAircraftPosnReport )
640                 turnRateHdr = _("Turn Rate");
641     }
642     html << _T("<tr><td colspan=2><table width=100% border=0 cellpadding=0 cellspacing=0>")
643         << rowStart <<_("Range") << _T("</font></td><td>&nbsp;</td><td><font size=-2>")
644         << _("Bearing") << _T("</font></td><td>&nbsp;</td><td align=right><font size=-2>")
645         << turnRateHdr << _T("</font></td></tr>")
646         << rowStartH << _T("<b>") << rngStr << _T("</b></td><td>&nbsp;</td><td><b>")
647         << brgStr << _T("</b></td><td>&nbsp;</td><td align=right><b>");
648 
649         if(!b_SarAircraftPosnReport)
650             html << rotStr;
651         html << rowEnd << _T("</table></td></tr>")
652         << vertSpacer;
653 
654     if( bCPA_Valid ) {
655         wxString tcpaStr;
656         tcpaStr << _T("</b> ") << _("in ") << _T("</td><td align=right><b>") << FormatTimeAdaptive( (int)(TCPA*60.) );
657 
658         html<< /*vertSpacer << */rowStart << _T("<font size=-2>") <<_("CPA") << _T("</font>") << rowEnd
659             << rowStartH << _T("<b>") << FormatDistanceAdaptive( CPA )
660             << tcpaStr << rowEnd;
661     }
662 
663     if( Class != AIS_BASE ) {
664         if( blue_paddle == 1 ) {
665             html << rowStart << _("Inland Blue Flag") << rowEnd
666                  << rowStartH << _T("<b>") << _("Clear") << rowEnd;
667         } else if( blue_paddle == 2 ) {
668             html << rowStart << _("Inland Blue Flag") << rowEnd
669                  << rowStartH << _T("<b>") << _("Set") << rowEnd;
670         }
671     }
672 
673     if(b_SarAircraftPosnReport) {
674         wxString altStr;
675         if(altitude != 4095)
676             altStr.Printf(_T("%4d m"), altitude );
677         else
678             altStr = _("Unknown");
679 
680         html    << rowStart <<_("Altitude") << _T("</font></td><td>&nbsp;</td><td><font size=-0>")
681         << rowStartH << _T("<b>") << altStr << _T("</b></td><td>&nbsp;</td><td><b>")
682         << rowEnd << _T("</table></td></tr>")
683         << vertSpacer;
684     }
685 
686     html << _T("</table>");
687     return html;
688 }
689 
GetRolloverString(void)690 wxString AIS_Target_Data::GetRolloverString( void )
691 {
692     wxString result;
693     wxString t;
694     if( b_nameValid ) {
695         result.Append( _T("\"") );
696         result.Append( GetFullName() );
697         result.Append( _T("\" ") );
698     }
699     if( Class != AIS_GPSG_BUDDY ) {
700         t.Printf( _T("%09d"), abs( MMSI ) );
701         result.Append( t );
702         result.Append( _T(" ") );
703         result.Append( GetCountryCode(false) );
704     }
705     t = trimAISField( CallSign );
706     if( t.Len() ) {
707         result.Append( _T(" (") );
708         result.Append( t );
709         result.Append( _T(")") );
710     }
711     if( g_bAISRolloverShowClass || ( Class == AIS_SART ) ) {
712         if( result.Len() ) result.Append( _T("\n") );
713         result.Append( _T("[") );
714         if( Class == AIS_ATON ) {
715             result.Append( wxGetTranslation( Get_class_string( true ) ) );
716             result.Append(_T(": "));
717             result.Append( wxGetTranslation( Get_vessel_type_string( false ) ) );
718         }
719         else if (b_SarAircraftPosnReport) {
720             int airtype = (MMSI % 1000) / 100;
721             result.Append(airtype == 5 ? _("SAR Helicopter") : _("SAR Aircraft"));
722         }
723         else
724             result.Append( wxGetTranslation( Get_class_string( false ) ) );
725 
726         result.Append( _T("] ") );
727         if( ( Class != AIS_ATON ) && ( Class != AIS_BASE ) ) {
728             if( Class == AIS_SART ) {
729                 int mmsi_start = MMSI / 1000000;
730                 switch( mmsi_start ){
731                     case 970:
732                         break;
733                     case 972:
734                         result += _T("MOB");
735                         break;
736                     case 974:
737                         result += _T("EPIRB");
738                         break;
739                     default:
740                         result += _("Unknown");
741                         break;
742                 }
743             }
744 
745             if( Class != AIS_SART ) {
746                 if( !b_SarAircraftPosnReport )
747                     result.Append( wxGetTranslation( Get_vessel_type_string( false ) ) );
748             }
749 
750             if( ( Class != AIS_CLASS_B ) && ( Class != AIS_SART ) && !b_SarAircraftPosnReport) {
751                 if( ( NavStatus <= 15 ) && ( NavStatus >= 0 ) ) {
752                     result.Append( _T(" (") );
753                     result.Append(wxGetTranslation(ais_get_status(NavStatus)));
754                     result.Append( _T(")") );
755                 }
756             } else if( Class == AIS_SART ) {
757                 result.Append( _T(" (") );
758                 if( NavStatus == RESERVED_14 ) result.Append( _("Active") );
759                 else if( NavStatus == UNDEFINED ) result.Append( _("Testing") );
760 
761                 result.Append( _T(")") );
762             }
763 
764         }
765     }
766 
767     if( g_bAISRolloverShowCOG && (( SOG <= 102.2 ) || b_SarAircraftPosnReport)
768             && ( ( Class != AIS_ATON ) && ( Class != AIS_BASE ) ) ) {
769         if( result.Len() ) result << _T("\n");
770 
771         double speed_show = toUsrSpeed( SOG );
772         if( speed_show < 10.0 )
773             result << wxString::Format( _T("SOG %.2f "), speed_show ) << getUsrSpeedUnit() << _T(" ");
774         else if( speed_show < 100.0 )
775             result << wxString::Format( _T("SOG %.1f "), speed_show ) << getUsrSpeedUnit() << _T(" ");
776         else
777             result << wxString::Format( _T("SOG %.0f "), speed_show ) << getUsrSpeedUnit() << _T(" ");
778 
779         int crs = wxRound( COG );
780         if( b_positionOnceValid ) {
781             if( crs < 360 ) {
782                 wxString magString, trueString;
783                 if( g_bShowMag )
784                     magString << wxString::Format( wxString("%03d°(M)  ", wxConvUTF8 ), (int)gFrame->GetMag( crs ) );
785                 if( g_bShowTrue )
786                     trueString << wxString::Format( wxString("%03d°  ", wxConvUTF8 ), (int) crs );
787 
788                 result << trueString << magString;
789             }
790 
791             else if( COG == 360.0 )
792                 result << _(" COG Unavailable");
793             else if( crs == 360 )
794                 result << wxString( " COG 000°", wxConvUTF8 );
795         } else
796             result << _(" COG Unavailable");
797     }
798 
799     if( g_bAISRolloverShowCPA && bCPA_Valid ) {
800         if( result.Len() ) result << _T("\n");
801         result << _("CPA") << _T(" ") << FormatDistanceAdaptive( CPA )
802         << _T(" ") << _("in") << _T(" ")
803         << wxString::Format( _T("%.0f"), TCPA ) << _T(" ") << _("min");
804     }
805     return result;
806 }
807 
Get_vessel_type_string(bool b_short)808 wxString AIS_Target_Data::Get_vessel_type_string( bool b_short )
809 {
810     int i = 19;
811     if( Class == AIS_ATON ) {
812         i = ShipType + 20;
813     } else
814         switch( ShipType ){
815             case 30:
816                 i = 0;
817                 break;
818             case 31:
819                 i = 1;
820                 break;
821             case 32:
822                 i = 2;
823                 break;
824             case 33:
825                 i = 3;
826                 break;
827             case 34:
828                 i = 4;
829                 break;
830             case 35:
831                 i = 5;
832                 break;
833             case 36:
834                 i = 6;
835                 break;
836             case 37:
837                 i = 7;
838                 break;
839             case 50:
840                 i = 9;
841                 break;
842             case 51:
843                 i = 10;
844                 break;
845             case 52:
846                 i = 11;
847                 break;
848             case 53:
849                 i = 12;
850                 break;
851             case 54:
852                 i = 13;
853                 break;
854             case 55:
855                 i = 14;
856                 break;
857             case 58:
858                 i = 15;
859                 break;
860             default:
861                 i = 19;
862                 break;
863         }
864 
865     if( ( Class == AIS_CLASS_B ) || ( Class == AIS_CLASS_A ) ) {
866         if( ( ShipType >= 40 ) && ( ShipType < 50 ) ) i = 8;
867 
868         if( ( ShipType >= 60 ) && ( ShipType < 70 ) ) i = 16;
869 
870         if( ( ShipType >= 70 ) && ( ShipType < 80 ) ) i = 17;
871 
872         if( ( ShipType >= 80 ) && ( ShipType < 90 ) ) i = 18;
873     } else if( Class == AIS_GPSG_BUDDY )
874         i = 52;
875     else if( Class == AIS_ARPA )
876         i = 55;
877     else if( Class == AIS_APRS )
878         i = 56;
879     else if( Class == AIS_DSC )
880         i = ( ShipType == 12 ) ? 54 : 53;  // 12 is distress
881 
882     if( !b_short )
883         return ais_get_type(i);
884     else
885         return ais_get_short_type(i);
886 }
887 
Get_class_string(bool b_short)888     wxString AIS_Target_Data::Get_class_string( bool b_short )
889 {
890     switch( Class ){
891         case AIS_CLASS_A:
892             return _("A");
893         case AIS_CLASS_B:
894             return _("B");
895         case AIS_ATON:
896             return b_short ? _("AtoN") : _("Aid to Navigation");
897         case AIS_BASE:
898             return b_short ? _("Base") : _("Base Station");
899         case AIS_GPSG_BUDDY:
900             return b_short ? _("Buddy") : _("GPSGate Buddy");
901         case AIS_DSC:
902             if( ShipType == 12 )
903                 return b_short ? _("DSC") : _("DSC Distress");
904             else
905                 return b_short ? _("DSC") : _("DSC Position Report");
906         case AIS_SART:
907             return b_short ? _("SART") : _("SART");
908         case AIS_ARPA:
909             return b_short ? _("ARPA") : _("ARPA");
910         case AIS_APRS:
911             return b_short ? _("APRS") : _("APRS Position Report");
912 
913         default:
914             return b_short ? _("Unk") : _("Unknown");
915     }
916 }
917 
Toggle_AIS_CPA(void)918 void AIS_Target_Data::Toggle_AIS_CPA(void)
919 {
920     b_show_AIS_CPA = !b_show_AIS_CPA ? true : false;
921 }
922 
ToggleShowTrack(void)923 void AIS_Target_Data::ToggleShowTrack(void)
924 {
925     b_show_track = !b_show_track ? true : false;
926 }
927 
928 
929 //Get country name and code according to ITU 2019-02 (http://www.itu.int/en/ITU-R/terrestrial/fmd/Pages/mid.aspx)
GetCountryCode(bool b_CntryLongStr)930 wxString AIS_Target_Data::GetCountryCode( bool b_CntryLongStr )  //false = Short country code, true = Full country name
931 {
932   int nMID = MMSI / 1000000;
933   //SAR Aircraft start with 111 and has a MID at pos 4,5,6
934   if (111 == nMID) nMID = (MMSI - 111000000) / 1000;
935   //Base station start with 00 and has a MID at pos 4,5,6
936   if (Class == AIS_BASE) nMID = MMSI / 10000;
937   //AtoN start with 99 and has a MID at pos 3,4,5
938   if (99 == MMSI / 10000000) nMID = (MMSI - 990000000) / 10000;
939   //Check if a proper MID
940   if (nMID < 201 || nMID > 775) return wxEmptyString;
941 
942 #if wxUSE_XLOCALE || !wxCHECK_VERSION(3,0,0)
943 
944   switch (nMID) {
945     case 201: return b_CntryLongStr ? _("Albania") : _T("AL") ;
946     case 202: return b_CntryLongStr ? _("Andorra") : _T("AD") ;
947     case 203: return b_CntryLongStr ? _("Austria") : _T("AT") ;
948     case 204: return b_CntryLongStr ? _("Azores") : _T("AZ") ;
949     case 205: return b_CntryLongStr ? _("Belgium") : _T("BE") ;
950     case 206: return b_CntryLongStr ? _("Belarus") : _T("BY") ;
951     case 207: return b_CntryLongStr ? _("Bulgaria") : _T("BG") ;
952     case 208: return b_CntryLongStr ? _("Vatican City State") : _T("VA") ;
953     case 209:
954     case 210: return b_CntryLongStr ? _("Cyprus") : _T("CY") ;
955     case 211: return b_CntryLongStr ? _("Germany") : _T("DE") ;
956     case 212: return b_CntryLongStr ? _("Cyprus") : _T("CY") ;
957     case 213: return b_CntryLongStr ? _("Georgia") : _T("GE") ;
958     case 214: return b_CntryLongStr ? _("Moldova") : _T("MD") ;
959     case 215: return b_CntryLongStr ? _("Malta") : _T("MT") ;
960     case 216: return b_CntryLongStr ? _("Armenia") : _T("AM") ;
961     case 218: return b_CntryLongStr ? _("Germany") : _T("DE") ;
962     case 219:
963     case 220: return b_CntryLongStr ? _("Denmark") : _T("DK") ;
964     case 224: return b_CntryLongStr ? _("Spain") : _T("ES") ;
965     case 225: return b_CntryLongStr ? _("Spain") : _T("ES") ;
966     case 226:
967     case 227:
968     case 228: return b_CntryLongStr ? _("France") : _T("FR") ;
969     case 229: return b_CntryLongStr ? _("Malta") : _T("MT") ;
970     case 230: return b_CntryLongStr ? _("Finland") : _T("FI") ;
971     case 231: return b_CntryLongStr ? _("Faroe Islands") : _T("FO") ;
972     case 232:
973     case 233:
974     case 234:
975     case 235: return b_CntryLongStr ? _("Great Britain") : _T("GB") ;
976     case 236: return b_CntryLongStr ? _("Gibraltar") : _T("GI") ;
977     case 237: return b_CntryLongStr ? _("Greece") : _T("GR") ;
978     case 238: return b_CntryLongStr ? _("Croatia") : _T("HR") ;
979     case 239:
980     case 240:
981     case 241: return b_CntryLongStr ? _("Greece") : _T("GR") ;
982     case 242: return b_CntryLongStr ? _("Morocco") : _T("MA") ;
983     case 243: return b_CntryLongStr ? _("Hungary") : _T("HU") ;
984     case 244:
985     case 245:
986     case 246: return b_CntryLongStr ? _("Netherlands") : _T("NL") ;
987     case 247: return b_CntryLongStr ? _("Italy") : _T("IT") ;
988     case 248:
989     case 249: return b_CntryLongStr ? _("Malta") : _T("MT") ;
990     case 250: return b_CntryLongStr ? _("Ireland") : _T("IE") ;
991     case 251: return b_CntryLongStr ? _("Iceland") : _T("IS") ;
992     case 252: return b_CntryLongStr ? _("Liechtenstein") : _T("LI") ;
993     case 253: return b_CntryLongStr ? _("Luxembourg") : _T("LU") ;
994     case 254: return b_CntryLongStr ? _("Monaco") : _T("MC") ;
995     case 255: return b_CntryLongStr ? _("Madeira") : _T("PT") ;
996     case 256: return b_CntryLongStr ? _("Malta") : _T("MT") ;
997     case 257:
998     case 258:
999     case 259: return b_CntryLongStr ? _("Norway") : _T("NO") ;
1000     case 261: return b_CntryLongStr ? _("Poland") : _T("PL") ;
1001     case 262: return b_CntryLongStr ? _("Montenegro") : _T("ME") ;
1002     case 263: return b_CntryLongStr ? _("Portugal") : _T("PT") ;
1003     case 264: return b_CntryLongStr ? _("Romania") : _T("RO") ;
1004     case 265:
1005     case 266: return b_CntryLongStr ? _("Sweden") : _T("SE") ;
1006     case 267: return b_CntryLongStr ? _("Slovak Republic") : _T("SK") ;
1007     case 268: return b_CntryLongStr ? _("San Marino") : _T("SM") ;
1008     case 269: return b_CntryLongStr ? _("Switzerland") : _T("CH") ;
1009     case 270: return b_CntryLongStr ? _("Czech Republic") : _T("CZ") ;
1010     case 271: return b_CntryLongStr ? _("Turkey") : _T("TR") ;
1011     case 272: return b_CntryLongStr ? _("Ukraine") : _T("UA") ;
1012     case 273: return b_CntryLongStr ? _("Russian") : _T("RU") ;
1013     case 274: return b_CntryLongStr ? _("Macedonia") : _T("MK") ;
1014     case 275: return b_CntryLongStr ? _("Latvia") : _T("LV") ;
1015     case 276: return b_CntryLongStr ? _("Estonia") : _T("EE") ;
1016     case 277: return b_CntryLongStr ? _("Lithuania") : _T("LT") ;
1017     case 278: return b_CntryLongStr ? _("Slovenia") : _T("SI") ;
1018     case 279: return b_CntryLongStr ? _("Serbia") : _T("RS") ;
1019     case 301: return b_CntryLongStr ? _("Anguilla") : _T("AI") ;
1020     case 303: return b_CntryLongStr ? _("Alaska") : _T("AK") ;
1021     case 304:
1022     case 305: return b_CntryLongStr ? _("Antigua and Barbuda") : _T("AG") ;
1023     case 306: return b_CntryLongStr ? _("Antilles") : _T("AN") ;
1024     case 307: return b_CntryLongStr ? _("Aruba") : _T("AW") ;
1025     case 308:
1026     case 309: return b_CntryLongStr ? _("Bahamas") : _T("BS") ;
1027     case 310: return b_CntryLongStr ? _("Bermuda") : _T("BM") ;
1028     case 311: return b_CntryLongStr ? _("Bahamas") : _T("BS") ;
1029     case 312: return b_CntryLongStr ? _("Belize") : _T("BZ") ;
1030     case 314: return b_CntryLongStr ? _("Barbados") : _T("BB") ;
1031     case 316: return b_CntryLongStr ? _("Canada") : _T("CA") ;
1032     case 319: return b_CntryLongStr ? _("Cayman Islands") : _T("KY") ;
1033     case 321: return b_CntryLongStr ? _("Costa Rica") : _T("CR") ;
1034     case 323: return b_CntryLongStr ? _("Cuba") : _T("CU") ;
1035     case 325: return b_CntryLongStr ? _("Dominica") : _T("DM") ;
1036     case 327: return b_CntryLongStr ? _("Dominican Republic") : _T("DM") ;
1037     case 329: return b_CntryLongStr ? _("Guadeloupe") : _T("GP") ;
1038     case 330: return b_CntryLongStr ? _("Grenada") : _T("GD") ;
1039     case 331: return b_CntryLongStr ? _("Greenland") : _T("GL") ;
1040     case 332: return b_CntryLongStr ? _("Guatemala") : _T("GT") ;
1041     case 334: return b_CntryLongStr ? _("Honduras") : _T("HN") ;
1042     case 336: return b_CntryLongStr ? _("Haiti") : _T("HT") ;
1043     case 338: return b_CntryLongStr ? _("United States of America") : _T("US") ;
1044     case 339: return b_CntryLongStr ? _("Jamaica") : _T("JM") ;
1045     case 341: return b_CntryLongStr ? _("Saint Kitts and Nevis") : _T("KN") ;
1046     case 343: return b_CntryLongStr ? _("Saint Lucia") : _T("LC") ;
1047     case 345: return b_CntryLongStr ? _("Mexico") : _T("MX") ;
1048     case 347: return b_CntryLongStr ? _("Martinique") : _T("MQ") ;
1049     case 348: return b_CntryLongStr ? _("Montserrat") : _T("MS") ;
1050     case 350: return b_CntryLongStr ? _("Nicaragua") : _T("NI") ;
1051     case 351:
1052     case 352:
1053     case 353:
1054     case 354:
1055     case 355:
1056     case 356:
1057     case 357: return b_CntryLongStr ? _("Panama") : _T("PA") ;
1058     case 358: return b_CntryLongStr ? _("Puerto Rico") : _T("PR") ;
1059     case 359: return b_CntryLongStr ? _("El Salvador") : _T("SV") ;
1060     case 361: return b_CntryLongStr ? _("Saint Pierre and Miquelon") : _T("PM") ;
1061     case 362: return b_CntryLongStr ? _("Trinidad and Tobago") : _T("TT") ;
1062     case 364: return b_CntryLongStr ? _("Turks and Caicos Islands") : _T("TC") ;
1063     case 366:
1064     case 367:
1065     case 368:
1066     case 369: return b_CntryLongStr ? _("United States of America") : _T("US") ;
1067     case 370:
1068     case 371:
1069     case 372:
1070     case 373:
1071     case 374: return b_CntryLongStr ? _("Panama") : _T("PA") ;
1072     case 375:
1073     case 376:
1074     case 377: return b_CntryLongStr ? _("Saint Vincent and the Grenadines") : _T("VC") ;
1075     case 378: return b_CntryLongStr ? _("British Virgin Islands") : _T("VG") ;
1076     case 379: return b_CntryLongStr ? _("United States Virgin Islands") : _T("AE") ;
1077     case 401: return b_CntryLongStr ? _("Afghanistan") : _T("AF") ;
1078     case 403: return b_CntryLongStr ? _("Saudi Arabia") : _T("SA") ;
1079     case 405: return b_CntryLongStr ? _("Bangladesh") : _T("BD") ;
1080     case 408: return b_CntryLongStr ? _("Bahrain") : _T("BH") ;
1081     case 410: return b_CntryLongStr ? _("Bhutan") : _T("BT") ;
1082     case 412:
1083     case 413:
1084     case 414: return b_CntryLongStr ? _("China") : _T("CN") ;
1085     case 416: return b_CntryLongStr ? _("Taiwan") : _T("TW") ;
1086     case 417: return b_CntryLongStr ? _("Sri Lanka") : _T("LK") ;
1087     case 419: return b_CntryLongStr ? _("India") : _T("IN") ;
1088     case 422: return b_CntryLongStr ? _("Iran") : _T("IR") ;
1089     case 423: return b_CntryLongStr ? _("Azerbaijani Republic") : _T("AZ") ;
1090     case 425: return b_CntryLongStr ? _("Iraq") : _T("IQ") ;
1091     case 428: return b_CntryLongStr ? _("Israel") : _T("IL") ;
1092     case 431: return b_CntryLongStr ? _("Japan") : _T("JP") ;
1093     case 432: return b_CntryLongStr ? _("Japan") : _T("JP") ;
1094     case 434: return b_CntryLongStr ? _("Turkmenistan") : _T("TM") ;
1095     case 436: return b_CntryLongStr ? _("Kazakhstan") : _T("KZ") ;
1096     case 437: return b_CntryLongStr ? _("Uzbekistan") : _T("UZ") ;
1097     case 438: return b_CntryLongStr ? _("Jordan") : _T("JO") ;
1098     case 440:
1099     case 441: return b_CntryLongStr ? _("Korea") : _T("KR") ;
1100     case 443: return b_CntryLongStr ? _("Palestine") : _T("PS") ;
1101     case 445: return b_CntryLongStr ? _("People's Rep. of Korea") : _T("KP") ;
1102     case 447: return b_CntryLongStr ? _("Kuwait") : _T("KW") ;
1103     case 450: return b_CntryLongStr ? _("Lebanon") : _T("LB") ;
1104     case 451: return b_CntryLongStr ? _("Kyrgyz Republic") : _T("KG") ;
1105     case 453: return b_CntryLongStr ? _("Macao") : _T("MO") ;
1106     case 455: return b_CntryLongStr ? _("Maldives") : _T("MV") ;
1107     case 457: return b_CntryLongStr ? _("Mongolia") : _T("MN") ;
1108     case 459: return b_CntryLongStr ? _("Nepal") : _T("NP") ;
1109     case 461: return b_CntryLongStr ? _("Oman") : _T("OM") ;
1110     case 463: return b_CntryLongStr ? _("Pakistan") : _T("PK") ;
1111     case 466: return b_CntryLongStr ? _("Qatar") : _T("QA") ;
1112     case 468: return b_CntryLongStr ? _("Syrian Arab Republic") : _T("SY") ;
1113     case 470:
1114     case 471: return b_CntryLongStr ? _("United Arab Emirates") : _T("AE") ;
1115     case 472: return b_CntryLongStr ? _("Tajikistan") : _T("TJ") ;
1116     case 473:
1117     case 475: return b_CntryLongStr ? _("Yemen") : _T("YE") ;
1118     case 477: return b_CntryLongStr ? _("Hong Kong") : _T("HK") ;
1119     case 478: return b_CntryLongStr ? _("Bosnia and Herzegovina") : _T("BA") ;
1120     case 501: return b_CntryLongStr ? _("Adelie Land") : _T("TF") ;
1121     case 503: return b_CntryLongStr ? _("Australia") : _T("AU") ;
1122     case 506: return b_CntryLongStr ? _("Myanmar") : _T("MM") ;
1123     case 508: return b_CntryLongStr ? _("Brunei Darussalam") : _T("BN") ;
1124     case 510: return b_CntryLongStr ? _("Micronesia") : _T("FM") ;
1125     case 511: return b_CntryLongStr ? _("Palau") : _T("PW") ;
1126     case 512: return b_CntryLongStr ? _("New Zealand") : _T("NZ") ;
1127     case 514:
1128     case 515: return b_CntryLongStr ? _("Cambodia") : _T("KH") ;
1129     case 516: return b_CntryLongStr ? _("Christmas Island") : _T("CX") ;
1130     case 518: return b_CntryLongStr ? _("Cook Islands") : _T("CK") ;
1131     case 520: return b_CntryLongStr ? _("Fiji") : _T("FJ") ;
1132     case 523: return b_CntryLongStr ? _("Cocos (Keeling) Islands") : _T("CC") ;
1133     case 525: return b_CntryLongStr ? _("Indonesia") : _T("ID") ;
1134     case 529: return b_CntryLongStr ? _("Kiribati") : _T("KI") ;
1135     case 531: return b_CntryLongStr ? _("Lao People's Dem. Rep.") : _T("LA") ;
1136     case 533: return b_CntryLongStr ? _("Malaysia") : _T("MY") ;
1137     case 536: return b_CntryLongStr ? _("Northern Mariana Islands") : _T("MP") ;
1138     case 538: return b_CntryLongStr ? _("Marshall Islands") : _T("MH") ;
1139     case 540: return b_CntryLongStr ? _("New Caledonia") : _T("NC") ;
1140     case 542: return b_CntryLongStr ? _("Niue") : _T("NU") ;
1141     case 544: return b_CntryLongStr ? _("Nauru") : _T("NR") ;
1142     case 546: return b_CntryLongStr ? _("French Polynesia") : _T("PF") ;
1143     case 548: return b_CntryLongStr ? _("Philippines") : _T("PH") ;
1144     case 553: return b_CntryLongStr ? _("Papua New Guinea") : _T("PG") ;
1145     case 555: return b_CntryLongStr ? _("Pitcairn Island") : _T("PN") ;
1146     case 557: return b_CntryLongStr ? _("Solomon Islands") : _T("SB") ;
1147     case 559: return b_CntryLongStr ? _("American Samoa") : _T("AS") ;
1148     case 561: return b_CntryLongStr ? _("Samoa") : _T("WS") ;
1149     case 563:
1150     case 564:
1151     case 565:
1152     case 566: return b_CntryLongStr ? _("Singapore") : _T("SG") ;
1153     case 567: return b_CntryLongStr ? _("Thailand") : _T("TH") ;
1154     case 570: return b_CntryLongStr ? _("Tonga") : _T("TO") ;
1155     case 572: return b_CntryLongStr ? _("Tuvalu") : _T("TV") ;
1156     case 574: return b_CntryLongStr ? _("Viet Nam") : _T("VN") ;
1157     case 576:
1158     case 577: return b_CntryLongStr ? _("Vanuatu") : _T("VU") ;
1159     case 578: return b_CntryLongStr ? _("Wallis and Futuna Islands") : _T("WF") ;
1160     case 601: return b_CntryLongStr ? _("South Africa") : _T("ZA") ;
1161     case 603: return b_CntryLongStr ? _("Angola") : _T("AO") ;
1162     case 605: return b_CntryLongStr ? _("Algeria") : _T("DZ") ;
1163     case 607: return b_CntryLongStr ? _("Saint Paul") : _T("TF") ;
1164     case 608: return b_CntryLongStr ? _("Ascension Island") : _T("SH") ;
1165     case 609: return b_CntryLongStr ? _("Burundi") : _T("BI") ;
1166     case 610: return b_CntryLongStr ? _("Benin") : _T("BJ") ;
1167     case 611: return b_CntryLongStr ? _("Botswana") : _T("BW") ;
1168     case 612: return b_CntryLongStr ? _("Central African Republic") : _T("CF") ;
1169     case 613: return b_CntryLongStr ? _("Cameroon") : _T("CM") ;
1170     case 615: return b_CntryLongStr ? _("Congo") : _T("CD") ;
1171     case 616: return b_CntryLongStr ? _("Comoros") : _T("KM") ;
1172     case 617: return b_CntryLongStr ? _("Capo Verde") : _T("CV") ;
1173     case 618: return b_CntryLongStr ? _("Crozet Archipelago") : _T("TF") ;
1174     case 619: return b_CntryLongStr ? _("Ivory Coast") : _T("CI") ;
1175     case 620: return b_CntryLongStr ? _("Comoros (Union of the)") : _T("KM") ;
1176     case 621: return b_CntryLongStr ? _("Djibouti") : _T("DJ") ;
1177     case 622: return b_CntryLongStr ? _("Egypt") : _T("EG") ;
1178     case 624: return b_CntryLongStr ? _("Ethiopia") : _T("ET") ;
1179     case 625: return b_CntryLongStr ? _("Eritrea") : _T("ER") ;
1180     case 626: return b_CntryLongStr ? _("Gabonese Republic") : _T("GA") ;
1181     case 627: return b_CntryLongStr ? _("Ghana") : _T("GH") ;
1182     case 629: return b_CntryLongStr ? _("Gambia") : _T("GM") ;
1183     case 630: return b_CntryLongStr ? _("Guinea-Bissau") : _T("GW") ;
1184     case 631: return b_CntryLongStr ? _("Equatorial Guinea") : _T("GQ") ;
1185     case 632: return b_CntryLongStr ? _("Guinea") : _T("GN") ;
1186     case 633: return b_CntryLongStr ? _("Burkina Faso") : _T("BF") ;
1187     case 634: return b_CntryLongStr ? _("Kenya") : _T("KE") ;
1188     case 635: return b_CntryLongStr ? _("Kerguelen Islands") : _T("TF") ;
1189     case 636:
1190     case 637: return b_CntryLongStr ? _("Liberia") : _T("LR") ;
1191     case 638: return b_CntryLongStr ? _("South Sudan (Republic of)") : _T("SS") ;
1192     case 642: return b_CntryLongStr ? _("Libya") : _T("LY") ;
1193     case 644: return b_CntryLongStr ? _("Lesotho") : _T("LS") ;
1194     case 645: return b_CntryLongStr ? _("Mauritius") : _T("MU") ;
1195     case 647: return b_CntryLongStr ? _("Madagascar") : _T("MG") ;
1196     case 649: return b_CntryLongStr ? _("Mali") : _T("ML") ;
1197     case 650: return b_CntryLongStr ? _("Mozambique") : _T("MZ") ;
1198     case 654: return b_CntryLongStr ? _("Mauritania") : _T("MR") ;
1199     case 655: return b_CntryLongStr ? _("Malawi") : _T("MW") ;
1200     case 656: return b_CntryLongStr ? _("Niger") : _T("NE") ;
1201     case 657: return b_CntryLongStr ? _("Nigeria") : _T("NG") ;
1202     case 659: return b_CntryLongStr ? _("Namibia") : _T("NA") ;
1203     case 660: return b_CntryLongStr ? _("Reunion") : _T("RE") ;
1204     case 661: return b_CntryLongStr ? _("Rwanda") : _T("RW") ;
1205     case 662: return b_CntryLongStr ? _("Sudan") : _T("SD") ;
1206     case 663: return b_CntryLongStr ? _("Senegal") : _T("SN") ;
1207     case 664: return b_CntryLongStr ? _("Seychelles") : _T("SC") ;
1208     case 665: return b_CntryLongStr ? _("Saint Helena") : _T("SH") ;
1209     case 666: return b_CntryLongStr ? _("Somali Democratic Republic") : _T("SO") ;
1210     case 667: return b_CntryLongStr ? _("Sierra Leone") : _T("SL") ;
1211     case 668: return b_CntryLongStr ? _("Sao Tome and Principe") : _T("ST") ;
1212     case 669: return b_CntryLongStr ? _("Eswatini") : _T("SZ") ;
1213     case 670: return b_CntryLongStr ? _("Chad") : _T("TD") ;
1214     case 671: return b_CntryLongStr ? _("Togolese Republic") : _T("TG") ;
1215     case 672: return b_CntryLongStr ? _("Tunisia") : _T("TN") ;
1216     case 674: return b_CntryLongStr ? _("Tanzania") : _T("TZ") ;
1217     case 675: return b_CntryLongStr ? _("Uganda") : _T("UG") ;
1218     case 676: return b_CntryLongStr ? _("Dem Rep.of the Congo") : _T("CD") ;
1219     case 677: return b_CntryLongStr ? _("Tanzania") : _T("TZ") ;
1220     case 678: return b_CntryLongStr ? _("Zambia") : _T("ZM") ;
1221     case 679: return b_CntryLongStr ? _("Zimbabwe") : _T("ZW") ;
1222     case 701: return b_CntryLongStr ? _("Argentine Republic") : _T("AR") ;
1223     case 710: return b_CntryLongStr ? _("Brazil") : _T("BR") ;
1224     case 720: return b_CntryLongStr ? _("Bolivia") : _T("BO") ;
1225     case 725: return b_CntryLongStr ? _("Chile") : _T("CL") ;
1226     case 730: return b_CntryLongStr ? _("Colombia") : _T("CO") ;
1227     case 735: return b_CntryLongStr ? _("Ecuador") : _T("EC") ;
1228     case 740: return b_CntryLongStr ? _("Falkland Islands") : _T("FK") ;
1229     case 745: return b_CntryLongStr ? _("France - Guiana") : _T("GY") ;
1230     case 750: return b_CntryLongStr ? _("Guyana") : _T("GY") ;
1231     case 755: return b_CntryLongStr ? _("Paraguay") : _T("PY") ;
1232     case 760: return b_CntryLongStr ? _("Peru") : _T("PE") ;
1233     case 765: return b_CntryLongStr ? _("Suriname") : _T("SR") ;
1234     case 770: return b_CntryLongStr ? _("Uruguay") : _T("UY") ;
1235     case 775: return b_CntryLongStr ? _("Venezuela") : _T("VE") ;
1236 
1237     default: return wxEmptyString;
1238   }
1239 #else
1240   return wxEmptyString;
1241 #endif
1242 
1243 }
1244