1 /***************************************************************************
2  *
3  * Project:  OpenCPN
4  * Purpose:  Navigation Utility Functions
5  * Author:   David Register
6  *
7  ***************************************************************************
8  *   Copyright (C) 2010 by David S. Register                               *
9  *                                                                         *
10  *   This program is free software; you can redistribute it and/or modify  *
11  *   it under the terms of the GNU General Public License as published by  *
12  *   the Free Software Foundation; either version 2 of the License, or     *
13  *   (at your option) any later version.                                   *
14  *                                                                         *
15  *   This program is distributed in the hope that it will be useful,       *
16  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
17  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
18  *   GNU General Public License for more details.                          *
19  *                                                                         *
20  *   You should have received a copy of the GNU General Public License     *
21  *   along with this program; if not, write to the                         *
22  *   Free Software Foundation, Inc.,                                       *
23  *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,  USA.         *
24  **************************************************************************/
25 
26 #include "wx/wxprec.h"
27 
28 #ifdef __MINGW32__
29 #undef IPV6STRICT    // mingw FTBS fix:  missing struct ip_mreq
30 #include <windows.h>
31 #endif
32 
33 #ifndef  WX_PRECOMP
34 #include "wx/wx.h"
35 #endif //precompiled headers
36 
37 #include <wx/tokenzr.h>
38 #include <wx/sstream.h>
39 #include <wx/image.h>
40 #include <wx/filename.h>
41 #include <wx/graphics.h>
42 #include <wx/dir.h>
43 #include <wx/listbook.h>
44 #include <wx/timectrl.h>
45 
46 #include "dychart.h"
47 
48 #include <stdlib.h>
49 //#include <math.h>
50 #include <time.h>
51 #include <locale>
52 #include <list>
53 
54 #include <wx/listimpl.cpp>
55 #include <wx/progdlg.h>
56 
57 #include "config.h"
58 #include "chart1.h"
59 #include "navutil.h"
60 #include "chcanv.h"
61 #include "georef.h"
62 #include "cutil.h"
63 #include "styles.h"
64 #include "routeman.h"
65 #include "s52utils.h"
66 #include "chartbase.h"
67 #include "ocpndc.h"
68 #include "geodesic.h"
69 #include "datastream.h"
70 #include "multiplexer.h"
71 #include "ais.h"
72 #include "Route.h"
73 #include "Select.h"
74 #include "FontMgr.h"
75 #include "OCPN_Sound.h"
76 #include "Layer.h"
77 #include "NavObjectCollection.h"
78 #include "NMEALogWindow.h"
79 #include "AIS_Decoder.h"
80 #include "OCPNPlatform.h"
81 #include "Track.h"
82 #include "chartdb.h"
83 #include "CanvasConfig.h"
84 
85 #include "s52plib.h"
86 #include "cm93.h"
87 
88 #ifdef ocpnUSE_GL
89 #include "glChartCanvas.h"
90 #endif
91 
92 #ifdef __OCPN__ANDROID__
93 #include "androidUTIL.h"
94 #endif
95 
96 #ifdef __WXOSX__
97 #include "DarkMode.h"
98 #endif
99 
100 //    Statics
101 
102 extern OCPNPlatform     *g_Platform;
103 extern MyFrame          *gFrame;
104 
105 extern double           g_ChartNotRenderScaleFactor;
106 extern int              g_restore_stackindex;
107 extern int              g_restore_dbindex;
108 extern RouteList        *pRouteList;
109 extern TrackList        *pTrackList;
110 extern LayerList        *pLayerList;
111 extern int              g_LayerIdx;
112 extern MyConfig         *pConfig;
113 extern double           vLat, vLon, gLat, gLon;
114 extern double           kLat, kLon;
115 extern double           initial_scale_ppm, initial_rotation;
116 extern ColorScheme      global_color_scheme;
117 extern int              g_nbrightness;
118 extern bool             g_bShowTrue, g_bShowMag;
119 extern double           g_UserVar;
120 extern bool             g_bShowStatusBar;
121 extern bool             g_bUIexpert;
122 extern bool             g_bFullscreen;
123 extern int              g_nDepthUnitDisplay;
124 extern wxString         g_winPluginDir;
125 
126 
127 extern wxArrayOfConnPrm *g_pConnectionParams;
128 
129 extern wxString         g_SENCPrefix;
130 extern wxString         g_UserPresLibData;
131 
132 extern wxString         *pInit_Chart_Dir;
133 extern wxString         gWorldMapLocation;
134 extern WayPointman      *pWayPointMan;
135 
136 extern bool             s_bSetSystemTime;
137 extern bool             g_bDisplayGrid;         //Flag indicating if grid is to be displayed
138 extern bool             g_bPlayShipsBells;
139 extern int              g_iSoundDeviceIndex;
140 extern bool             g_bFullscreenToolbar;
141 extern bool             g_bShowLayers;
142 extern bool             g_bTransparentToolbar;
143 extern bool             g_bPermanentMOBIcon;
144 
145 extern bool             g_bShowDepthUnits;
146 extern bool             g_bAutoAnchorMark;
147 extern bool             g_bskew_comp;
148 extern bool             g_bopengl;
149 extern bool             g_bdisable_opengl;
150 extern bool             g_bSoftwareGL;
151 extern bool             g_bShowFPS;
152 extern bool             g_bsmoothpanzoom;
153 extern bool             g_fog_overzoom;
154 extern double           g_overzoom_emphasis_base;
155 extern bool             g_oz_vector_scale;
156 extern double           g_plus_minus_zoom_factor;
157 extern bool             g_bShowOutlines;
158 extern bool             g_bShowActiveRouteHighway;
159 extern bool             g_bShowRouteTotal;
160 extern int              g_nNMEADebug;
161 extern int              g_nAWDefault;
162 extern int              g_nAWMax;
163 extern int              g_nTrackPrecision;
164 
165 extern int              g_iSDMMFormat;
166 extern int              g_iDistanceFormat;
167 extern int              g_iSpeedFormat;
168 
169 extern int              g_nframewin_x;
170 extern int              g_nframewin_y;
171 extern int              g_nframewin_posx;
172 extern int              g_nframewin_posy;
173 extern bool             g_bframemax;
174 
175 extern double           g_PlanSpeed;
176 extern wxString         g_VisibleLayers;
177 extern wxString         g_InvisibleLayers;
178 extern wxString         g_VisiNameinLayers;
179 extern wxString         g_InVisiNameinLayers;
180 
181 extern wxArrayString    *pMessageOnceArray;
182 
183 // LIVE ETA OPTION
184 extern bool             g_bShowLiveETA;
185 extern double           g_defaultBoatSpeed;
186 extern double           g_defaultBoatSpeedUserUnit;
187 
188 //    AIS Global configuration
189 extern bool             g_bCPAMax;
190 extern double           g_CPAMax_NM;
191 extern bool             g_bCPAWarn;
192 extern double           g_CPAWarn_NM;
193 extern bool             g_bTCPA_Max;
194 extern double           g_TCPA_Max;
195 extern bool             g_bMarkLost;
196 extern double           g_MarkLost_Mins;
197 extern bool             g_bRemoveLost;
198 extern double           g_RemoveLost_Mins;
199 extern bool             g_bShowCOG;
200 extern double           g_ShowCOG_Mins;
201 extern bool             g_bAISShowTracks;
202 extern bool             g_bTrackCarryOver;
203 extern bool             g_bTrackDaily;
204 extern int              g_track_rotate_time;
205 extern int              g_track_rotate_time_type;
206 extern double           g_AISShowTracks_Mins;
207 extern double           g_AISShowTracks_Limit;
208 extern bool             g_bHideMoored;
209 extern double           g_ShowMoored_Kts;
210 extern bool             g_bAllowShowScaled;
211 extern bool             g_bShowScaled;
212 extern int              g_ShowScaled_Num;
213 extern bool             g_bAIS_CPA_Alert;
214 extern bool             g_bAIS_CPA_Alert_Audio;
215 extern int              g_ais_alert_dialog_x, g_ais_alert_dialog_y;
216 extern int              g_ais_alert_dialog_sx, g_ais_alert_dialog_sy;
217 extern int              g_ais_query_dialog_x, g_ais_query_dialog_y;
218 extern wxString         g_sAIS_Alert_Sound_File;
219 extern bool             g_bAIS_CPA_Alert_Suppress_Moored;
220 extern bool             g_bAIS_ACK_Timeout;
221 extern double           g_AckTimeout_Mins;
222 extern wxString         g_AisTargetList_perspective;
223 extern int              g_AisTargetList_range;
224 extern int              g_AisTargetList_sortColumn;
225 extern bool             g_bAisTargetList_sortReverse;
226 extern wxString         g_AisTargetList_column_spec;
227 extern wxString         g_AisTargetList_column_order;
228 extern bool             g_bShowAreaNotices;
229 extern bool             g_bDrawAISSize;
230 extern bool             g_bDrawAISRealtime;
231 extern double           g_AIS_RealtPred_Kts;
232 extern bool             g_bShowAISName;
233 extern int              g_Show_Target_Name_Scale;
234 extern bool             g_bWplIsAprsPosition;
235 extern bool             g_benableAISNameCache;
236 extern bool             g_bUseOnlyConfirmedAISName;
237 extern int              g_ScaledNumWeightSOG;
238 extern int              g_ScaledNumWeightCPA;
239 extern int              g_ScaledNumWeightTCPA;
240 extern int              g_ScaledNumWeightRange;
241 extern int              g_ScaledNumWeightSizeOfT;
242 extern int              g_ScaledSizeMinimal;
243 
244 extern int              g_S57_dialog_sx, g_S57_dialog_sy;
245 int                     g_S57_extradialog_sx, g_S57_extradialog_sy;
246 
247 extern int              g_iNavAidRadarRingsNumberVisible;
248 extern float            g_fNavAidRadarRingsStep;
249 extern int              g_pNavAidRadarRingsStepUnits;
250 extern int              g_iWaypointRangeRingsNumber;
251 extern float            g_fWaypointRangeRingsStep;
252 extern int              g_iWaypointRangeRingsStepUnits;
253 extern wxColour         g_colourWaypointRangeRingsColour;
254 extern bool             g_bWayPointPreventDragging;
255 extern bool             g_bConfirmObjectDelete;
256 extern wxColour         g_colourOwnshipRangeRingsColour;
257 extern int              g_iWpt_ScaMin;
258 extern bool             g_bUseWptScaMin;
259 extern bool             g_bOverruleScaMin;
260 extern bool             g_bShowWptName;
261 
262 
263 extern bool             g_bEnableZoomToCursor;
264 extern wxString         g_toolbarConfig;
265 extern double           g_TrackIntervalSeconds;
266 extern double           g_TrackDeltaDistance;
267 extern int              gps_watchdog_timeout_ticks;
268 
269 extern int              g_nCacheLimit;
270 extern int              g_memCacheLimit;
271 
272 extern bool             g_bGDAL_Debug;
273 extern bool             g_bDebugCM93;
274 extern bool             g_bDebugS57;
275 
276 extern double           g_ownship_predictor_minutes;
277 extern double           g_ownship_HDTpredictor_miles;
278 
279 extern bool             g_own_ship_sog_cog_calc;
280 extern int              g_own_ship_sog_cog_calc_damp_sec;
281 
282 extern bool             g_bShowMenuBar;
283 extern bool             g_bShowCompassWin;
284 
285 extern s52plib          *ps52plib;
286 
287 extern int              g_cm93_zoom_factor;
288 extern bool             g_b_legacy_input_filter_behaviour;
289 extern bool             g_bShowDetailSlider;
290 extern int              g_detailslider_dialog_x, g_detailslider_dialog_y;
291 
292 extern bool             g_bUseGreenShip;
293 
294 extern int              g_OwnShipIconType;
295 extern double           g_n_ownship_length_meters;
296 extern double           g_n_ownship_beam_meters;
297 extern double           g_n_gps_antenna_offset_y;
298 extern double           g_n_gps_antenna_offset_x;
299 extern int              g_n_ownship_min_mm;
300 extern double           g_n_arrival_circle_radius;
301 
302 extern bool             g_bPreserveScaleOnX;
303 extern bool             g_bsimplifiedScalebar;
304 
305 extern bool             g_bUseGLL;
306 
307 extern wxString         g_locale;
308 extern wxString         g_localeOverride;
309 
310 
311 extern bool             g_bCourseUp;
312 extern bool             g_bLookAhead;
313 extern int              g_COGAvgSec;
314 extern bool             g_bMagneticAPB;
315 extern bool             g_bShowChartBar;
316 
317 extern int              g_MemFootMB;
318 
319 extern int              g_nCOMPortCheck;
320 
321 
322 extern wxString         g_AW1GUID;
323 extern wxString         g_AW2GUID;
324 extern int              g_BSBImgDebug;
325 
326 extern int             n_NavMessageShown;
327 extern wxString        g_config_version_string;
328 
329 extern wxString        g_CmdSoundString;
330 
331 extern bool             g_bAISRolloverShowClass;
332 extern bool             g_bAISRolloverShowCOG;
333 extern bool             g_bAISRolloverShowCPA;
334 
335 extern bool             g_bDebugGPSD;
336 
337 extern bool             g_bfilter_cogsog;
338 extern int              g_COGFilterSec;
339 extern int              g_SOGFilterSec;
340 
341 int                     g_navobjbackups;
342 
343 extern bool             g_bQuiltEnable;
344 extern bool             g_bFullScreenQuilt;
345 extern bool             g_bQuiltStart;
346 
347 extern int              g_SkewCompUpdatePeriod;
348 
349 extern int              g_maintoolbar_x;
350 extern int              g_maintoolbar_y;
351 extern long             g_maintoolbar_orient;
352 
353 
354 extern int              g_lastClientRectx;
355 extern int              g_lastClientRecty;
356 extern int              g_lastClientRectw;
357 extern int              g_lastClientRecth;
358 
359 extern bool             g_bHighliteTracks;
360 extern int              g_cog_predictor_width;
361 extern int              g_ais_cog_predictor_width;
362 
363 extern int              g_route_line_width;
364 extern int              g_track_line_width;
365 extern wxColour         g_colourTrackLineColour;
366 extern wxString         g_default_wp_icon;
367 extern wxString         g_default_routepoint_icon;
368 
369 extern ChartGroupArray  *g_pGroupArray;
370 
371 extern bool             g_bDebugOGL;
372 extern int              g_tcwin_scale;
373 extern wxString         g_GPS_Ident;
374 extern bool             g_bGarminHostUpload;
375 extern wxString         g_uploadConnection;
376 
377 extern ocpnStyle::StyleManager* g_StyleManager;
378 extern wxArrayString    TideCurrentDataSet;
379 extern wxString         g_TCData_Dir;
380 
381 extern bool             g_btouch;
382 extern bool             g_bresponsive;
383 
384 extern bool             g_bGLexpert;
385 
386 extern int              g_SENC_LOD_pixels;
387 extern ArrayOfMMSIProperties   g_MMSI_Props_Array;
388 
389 extern int              g_chart_zoom_modifier;
390 extern int              g_chart_zoom_modifier_vector;
391 
392 extern int              g_NMEAAPBPrecision;
393 
394 extern wxString         g_TalkerIdText;
395 extern bool             g_bShowTrackPointTime;
396 
397 extern int              g_maxWPNameLength;
398 
399 extern bool             g_bAdvanceRouteWaypointOnArrivalOnly;
400 extern double           g_display_size_mm;
401 extern double           g_config_display_size_mm;
402 extern bool             g_config_display_size_manual;
403 
404 extern float            g_selection_radius_mm;
405 extern float            g_selection_radius_touch_mm;
406 
407 extern bool             g_benable_rotate;
408 extern bool             g_bEmailCrashReport;
409 
410 extern int              g_default_font_size;
411 extern wxString         g_default_font_facename;
412 
413 extern bool             g_bAutoHideToolbar;
414 extern int              g_nAutoHideToolbar;
415 extern int              g_GUIScaleFactor;
416 extern int              g_ChartScaleFactor;
417 extern float            g_ChartScaleFactorExp;
418 extern int              g_ShipScaleFactor;
419 extern float            g_ShipScaleFactorExp;
420 extern int              g_ENCSoundingScaleFactor;
421 
422 
423 extern bool             g_bInlandEcdis;
424 extern int              g_iENCToolbarPosX;
425 extern int              g_iENCToolbarPosY;
426 extern bool             g_bRollover;
427 
428 extern bool             g_bSpaceDropMark;
429 
430 extern bool             g_bShowTide;
431 extern bool             g_bShowCurrent;
432 
433 extern bool             g_benableUDPNullHeader;
434 
435 extern wxString         g_uiStyle;
436 extern bool             g_btrackContinuous;
437 extern bool             g_useMUI;
438 
439 int                     g_nCPUCount;
440 
441 extern bool             g_bDarkDecorations;
442 extern unsigned int     g_canvasConfig;
443 extern arrayofCanvasConfigPtr g_canvasConfigArray;
444 extern wxString         g_lastAppliedTemplateGUID;
445 
446 extern int              g_route_prop_x, g_route_prop_y;
447 extern int              g_route_prop_sx, g_route_prop_sy;
448 extern int              g_AndroidVersionCode;
449 
450 extern wxString         g_compatOS;
451 extern wxString         g_compatOsVersion;
452 
453 wxString                g_gpx_path;
454 bool                    g_bLayersLoaded;
455 bool                    g_bShowMuiZoomButtons = true;
456 
457 wxString                g_catalog_custom_url;
458 wxString                g_catalog_channel;
459 
460 #ifdef ocpnUSE_GL
461 extern ocpnGLOptions g_GLOptions;
462 #endif
463 
464 #if !defined(NAN)
465 static const long long lNaN = 0xfff8000000000000;
466 #define NAN (*(double*)&lNaN)
467 #endif
468 
469 
470 
471 // Layer helper function
472 
GetLayerName(int id)473 wxString GetLayerName( int id )
474 {
475     wxString name( _T("unknown layer") );
476     if( id <= 0 ) return ( name );
477     LayerList::iterator it;
478     int index = 0;
479     for( it = ( *pLayerList ).begin(); it != ( *pLayerList ).end(); ++it, ++index ) {
480         Layer *lay = (Layer *) ( *it );
481         if( lay->m_LayerID == id )
482             return ( lay->m_LayerName );
483     }
484     return ( name );
485 }
486 
487 //Helper conditional file name dir slash
488 void appendOSDirSlash(wxString* pString);
489 
490 
491 //-----------------------------------------------------------------------------
492 //          MyConfig Implementation
493 //-----------------------------------------------------------------------------
494 
MyConfig(const wxString & LocalFileName)495 MyConfig::MyConfig( const wxString &LocalFileName ) :
496     wxFileConfig( _T (""), _T (""), LocalFileName, _T (""),  wxCONFIG_USE_LOCAL_FILE )
497 {
498     //    Create the default NavObjectCollection FileName
499     wxFileName config_file( LocalFileName );
500     m_sNavObjSetFile = config_file.GetPath( wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR );
501     m_sNavObjSetFile += _T ( "navobj.xml" );
502     m_sNavObjSetChangesFile = m_sNavObjSetFile + _T ( ".changes" );
503 
504     m_pNavObjectInputSet = NULL;
505     m_pNavObjectChangesSet = NULL;
506 
507     m_bSkipChangeSetUpdate = false;
508 }
509 
CreateRotatingNavObjBackup()510 void MyConfig::CreateRotatingNavObjBackup()
511 {
512 
513     // Avoid nonsense log errors...
514 #ifdef __OCPN__ANDROID__
515     wxLogNull logNo;
516 #endif
517 
518     //Rotate navobj backups, but just in case there are some changes in the current version
519     //to prevent the user trying to "fix" the problem by continuously starting the
520     //application to overwrite all of his good backups...
521     if( g_navobjbackups > 0 ) {
522         wxFile f;
523         wxString oldname = m_sNavObjSetFile;
524         wxString newname = wxString::Format( _T("%s.1"), m_sNavObjSetFile.c_str() );
525 
526         wxFileOffset s_diff = 1;
527         if( ::wxFileExists( newname ) ) {
528 
529             if( f.Open(oldname) ){
530                 s_diff = f.Length();
531                 f.Close();
532             }
533 
534             if( f.Open(newname) ){
535                 s_diff -= f.Length();
536                 f.Close();
537             }
538         }
539 
540 
541         if ( s_diff != 0 )
542         {
543             for( int i = g_navobjbackups - 1; i >= 1; i-- )
544             {
545                 oldname = wxString::Format( _T("%s.%d"), m_sNavObjSetFile.c_str(), i );
546                 newname = wxString::Format( _T("%s.%d"), m_sNavObjSetFile.c_str(), i + 1 );
547                 if( wxFile::Exists( oldname ) )
548                     wxCopyFile( oldname, newname );
549             }
550 
551             if( wxFile::Exists( m_sNavObjSetFile ) )
552             {
553                 newname = wxString::Format( _T("%s.1"), m_sNavObjSetFile.c_str() );
554                 wxCopyFile( m_sNavObjSetFile, newname );
555             }
556         }
557     }
558     //try to clean the backups the user doesn't want - breaks if he deleted some by hand as it tries to be effective...
559     for( int i = g_navobjbackups + 1; i <= 99; i++ )
560         if( wxFile::Exists( wxString::Format( _T("%s.%d"), m_sNavObjSetFile.c_str(), i ) ) ) wxRemoveFile(
561                 wxString::Format( _T("%s.%d"), m_sNavObjSetFile.c_str(), i ) );
562         else
563             break;
564 }
565 
LoadMyConfig()566 int MyConfig::LoadMyConfig()
567 {
568     int display_width, display_height;
569     wxDisplaySize( &display_width, &display_height );
570 
571     //  Set up any defaults not set elsewhere
572     g_useMUI = true;
573     g_TalkerIdText = _T("EC");
574     g_maxWPNameLength = 6;
575     g_NMEAAPBPrecision = 3;
576 
577     #ifdef ocpnUSE_GL
578     g_GLOptions.m_bUseAcceleratedPanning = true;
579     g_GLOptions.m_GLPolygonSmoothing = true;
580     g_GLOptions.m_GLLineSmoothing = true;
581     g_GLOptions.m_iTextureDimension = 512;
582     g_GLOptions.m_iTextureMemorySize = 128;
583     if(!g_bGLexpert){
584         g_GLOptions.m_iTextureMemorySize = wxMax(128, g_GLOptions.m_iTextureMemorySize);
585         g_GLOptions.m_bTextureCompressionCaching = g_GLOptions.m_bTextureCompression;
586     }
587     #endif
588 
589     g_maintoolbar_orient = wxTB_HORIZONTAL;
590     g_iENCToolbarPosX = -1;
591     g_iENCToolbarPosY = -1;
592     g_restore_dbindex = -1;
593     g_ChartNotRenderScaleFactor = 1.5;
594     g_detailslider_dialog_x = 200L;
595     g_detailslider_dialog_y = 200L;
596     g_SENC_LOD_pixels = 2;
597     g_SkewCompUpdatePeriod = 10;
598 
599     g_bShowStatusBar = 1;
600     g_bShowCompassWin = 1;
601     g_iSoundDeviceIndex = -1;
602     g_bFullscreenToolbar = 1;
603     g_bTransparentToolbar =  0;
604     g_bShowLayers = 1;
605     g_bShowDepthUnits = 1;
606     g_bShowActiveRouteHighway = 1;
607     g_bShowChartBar = 1;
608     g_defaultBoatSpeed = 6.0;
609     g_ownship_predictor_minutes = 5;
610     g_cog_predictor_width = 3;
611     g_ownship_HDTpredictor_miles = 1;
612     g_n_ownship_min_mm = 5;
613     g_own_ship_sog_cog_calc_damp_sec = 1;
614     g_bFullScreenQuilt = 1;
615     g_track_rotate_time_type =  TIME_TYPE_COMPUTER;
616     g_bHighliteTracks = 1;
617     g_bPreserveScaleOnX = 1;
618     g_navobjbackups = 5;
619     g_benableAISNameCache = true;
620     g_n_arrival_circle_radius = 0.05;
621     g_plus_minus_zoom_factor = 2.0;
622 
623     g_AISShowTracks_Mins = 20;
624     g_AISShowTracks_Limit = 300.0;
625     g_ShowScaled_Num = 10;
626     g_ScaledNumWeightSOG = 50;
627     g_ScaledNumWeightCPA = 60;
628     g_ScaledNumWeightTCPA = 25;
629     g_ScaledNumWeightRange = 75;
630     g_ScaledNumWeightSizeOfT = 25;
631     g_ScaledSizeMinimal = 50;
632     g_Show_Target_Name_Scale = 250000;
633     g_bWplIsAprsPosition = 1;
634     g_ais_cog_predictor_width = 3;
635     g_ais_alert_dialog_sx = 200;
636     g_ais_alert_dialog_sy = 200;
637     g_ais_alert_dialog_x = 200;
638     g_ais_alert_dialog_y = 200;
639     g_ais_query_dialog_x = 200;
640     g_ais_query_dialog_y = 200;
641     g_AisTargetList_range = 40;
642     g_AisTargetList_sortColumn = 2; // Column #2 is MMSI
643     g_S57_dialog_sx = 400;
644     g_S57_dialog_sy = 400;
645     g_S57_extradialog_sx = 400;
646     g_S57_extradialog_sy = 400;
647 
648     //    Reasonable starting point
649     vLat = START_LAT;                   // display viewpoint
650     vLon = START_LON;
651     gLat = START_LAT;                   // GPS position, as default
652     gLon = START_LON;
653     initial_scale_ppm = .0003;        // decent initial value
654     initial_rotation = 0;
655 
656     g_iNavAidRadarRingsNumberVisible = 0;
657     g_fNavAidRadarRingsStep = 1.0;
658     g_pNavAidRadarRingsStepUnits = 0;
659     g_colourOwnshipRangeRingsColour = *wxRED;
660     g_iWaypointRangeRingsNumber = 0;
661     g_fWaypointRangeRingsStep = 1.0;
662     g_iWaypointRangeRingsStepUnits = 0;
663     g_colourWaypointRangeRingsColour = wxColour( *wxRED );
664     g_bConfirmObjectDelete = true;
665 
666     g_TrackIntervalSeconds = 60.0;
667     g_TrackDeltaDistance = 0.10;
668     g_route_line_width = 2;
669     g_track_line_width = 2;
670     g_colourTrackLineColour = wxColour( 243, 229, 47 );         //Yellow
671 
672     g_tcwin_scale = 100;
673     g_default_wp_icon = _T("triangle");
674     g_default_routepoint_icon = _T("diamond");
675 
676     g_nAWDefault = 50;
677     g_nAWMax = 1852;
678 
679     // Load the raw value, with no defaults, and no processing
680     int ret_Val = LoadMyConfigRaw();
681 
682     //  Perform any required post processing and validation
683     if(!ret_Val){
684         g_ChartScaleFactorExp = g_Platform->getChartScaleFactorExp( g_ChartScaleFactor );
685         g_ShipScaleFactorExp = g_Platform->getChartScaleFactorExp( g_ShipScaleFactor );
686 
687         g_COGFilterSec = wxMin(g_COGFilterSec, MAX_COGSOG_FILTER_SECONDS);
688         g_COGFilterSec = wxMax(g_COGFilterSec, 1);
689         g_SOGFilterSec = g_COGFilterSec;
690 
691         if(!g_bShowTrue && !g_bShowMag)
692             g_bShowTrue = true;
693         g_COGAvgSec = wxMin(g_COGAvgSec, MAX_COG_AVERAGE_SECONDS);        // Bound the array size
694 
695         if( g_bInlandEcdis )
696             g_bLookAhead=1;
697 
698         if ( g_bdisable_opengl )
699             g_bopengl = false;
700 
701         #ifdef ocpnUSE_GL
702             if(!g_bGLexpert){
703             g_GLOptions.m_iTextureMemorySize = wxMax(128, g_GLOptions.m_iTextureMemorySize);
704             g_GLOptions.m_bTextureCompressionCaching = g_GLOptions.m_bTextureCompression;
705         }
706         #endif
707 
708         g_chart_zoom_modifier = wxMin(g_chart_zoom_modifier,5);
709         g_chart_zoom_modifier = wxMax(g_chart_zoom_modifier,-5);
710         g_chart_zoom_modifier_vector = wxMin(g_chart_zoom_modifier_vector,5);
711         g_chart_zoom_modifier_vector = wxMax(g_chart_zoom_modifier_vector,-5);
712         g_cm93_zoom_factor = wxMin(g_cm93_zoom_factor,CM93_ZOOM_FACTOR_MAX_RANGE);
713         g_cm93_zoom_factor = wxMax(g_cm93_zoom_factor,(-CM93_ZOOM_FACTOR_MAX_RANGE));
714 
715         if( ( g_detailslider_dialog_x < 0 ) || ( g_detailslider_dialog_x > display_width ) )
716             g_detailslider_dialog_x = 5;
717         if( ( g_detailslider_dialog_y < 0 ) || ( g_detailslider_dialog_y > display_height ) )
718             g_detailslider_dialog_y =  5;
719 
720         g_defaultBoatSpeedUserUnit = toUsrSpeed(g_defaultBoatSpeed, -1);
721         g_n_ownship_min_mm = wxMax(g_n_ownship_min_mm, 5);
722         if( g_navobjbackups > 99 ) g_navobjbackups = 99;
723         if( g_navobjbackups < 0 ) g_navobjbackups = 0;
724         g_n_arrival_circle_radius = wxClip(g_n_arrival_circle_radius, 0.001, 0.6);
725 
726         g_selection_radius_mm = wxMax(g_selection_radius_mm, 0.5);
727         g_selection_radius_touch_mm = wxMax(g_selection_radius_touch_mm, 1.0);
728 
729         g_Show_Target_Name_Scale = wxMax( 5000, g_Show_Target_Name_Scale );
730 
731         if( ( g_ais_alert_dialog_x < 0 ) || ( g_ais_alert_dialog_x > display_width ) )
732             g_ais_alert_dialog_x = 5;
733         if( ( g_ais_alert_dialog_y < 0 ) || ( g_ais_alert_dialog_y > display_height ) )
734             g_ais_alert_dialog_y = 5;
735         if( ( g_ais_query_dialog_x < 0 ) || ( g_ais_query_dialog_x > display_width ) )
736             g_ais_query_dialog_x = 5;
737         if( ( g_ais_query_dialog_y < 0 ) || ( g_ais_query_dialog_y > display_height ) )
738             g_ais_query_dialog_y = 5;
739 
740         SwitchInlandEcdisMode( g_bInlandEcdis );
741         if ( g_bInlandEcdis )
742             global_color_scheme = GLOBAL_COLOR_SCHEME_DUSK; //startup in duskmode if inlandEcdis
743 
744         //    Multicanvas Settings
745         LoadCanvasConfigs();
746     }
747 
748     return ret_Val;
749 }
750 
LoadMyConfigRaw(bool bAsTemplate)751 int MyConfig::LoadMyConfigRaw( bool bAsTemplate )
752 {
753 
754     int read_int;
755     wxString val;
756 
757     int display_width, display_height;
758     wxDisplaySize( &display_width, &display_height );
759 
760 //    Global options and settings
761     SetPath( _T ( "/Settings" ) );
762 
763     Read( _T ( "LastAppliedTemplate" ), &g_lastAppliedTemplateGUID );
764     Read( _T ( "CompatOS" ), &g_compatOS );
765     Read( _T ( "CompatOsVersion" ), &g_compatOsVersion );
766 
767     // Some undocumented values
768     Read( _T ( "ConfigVersionString" ), &g_config_version_string );
769 #ifdef SYSTEM_SOUND_CMD
770     Read(_T("CmdSoundString"), &g_CmdSoundString, wxString(SYSTEM_SOUND_CMD) );
771     if ( wxIsEmpty( g_CmdSoundString ) )
772         g_CmdSoundString = wxString( SYSTEM_SOUND_CMD );
773 #endif /* SYSTEM_SOUND_CMD */
774     Read( _T ( "NavMessageShown" ), &n_NavMessageShown );
775 
776     Read( _T ( "AndroidVersionCode" ), &g_AndroidVersionCode );
777 
778     Read( _T ( "UIexpert" ), &g_bUIexpert );
779 
780     Read( _T ( "UIStyle" ), &g_uiStyle  );
781 
782     Read( _T ( "NCacheLimit" ), &g_nCacheLimit );
783 
784     Read( _T ( "InlandEcdis" ), &g_bInlandEcdis );// First read if in iENC mode as this will override some config settings
785 
786     Read( _T ("DarkDecorations" ), &g_bDarkDecorations );
787 
788     Read( _T( "SpaceDropMark" ), &g_bSpaceDropMark );
789 
790     int mem_limit = 0;
791     Read( _T ( "MEMCacheLimit" ), &mem_limit );
792     if(mem_limit > 0)
793         g_memCacheLimit = mem_limit * 1024;       // convert from MBytes to kBytes
794 
795     Read( _T ( "UseModernUI5" ), &g_useMUI );
796 
797     Read( _T( "NCPUCount" ), &g_nCPUCount);
798 
799     Read( _T ( "DebugGDAL" ), &g_bGDAL_Debug );
800     Read( _T ( "DebugNMEA" ), &g_nNMEADebug );
801     Read( _T ( "AnchorWatchDefault" ), &g_nAWDefault );
802     Read( _T ( "AnchorWatchMax" ), &g_nAWMax );
803     Read( _T ( "GPSDogTimeout" ), &gps_watchdog_timeout_ticks );
804     Read( _T ( "DebugCM93" ), &g_bDebugCM93 );
805     Read( _T ( "DebugS57" ), &g_bDebugS57 );         // Show LUP and Feature info in object query
806     Read( _T ( "DebugBSBImg" ), &g_BSBImgDebug );
807     Read( _T ( "DebugGPSD" ), &g_bDebugGPSD );
808 
809     Read( _T ( "DefaultFontSize"), &g_default_font_size );
810     Read( _T ( "DefaultFontFacename"), &g_default_font_facename );
811 
812     Read( _T ( "UseGreenShipIcon" ), &g_bUseGreenShip );
813 
814 
815     Read( _T ( "AutoHideToolbar" ), &g_bAutoHideToolbar );
816     Read( _T ( "AutoHideToolbarSecs" ), &g_nAutoHideToolbar );
817 
818     Read( _T ( "UseSimplifiedScalebar" ), &g_bsimplifiedScalebar );
819     Read( _T ( "ShowTide" ), &g_bShowTide );
820     Read( _T ( "ShowCurrent" ), &g_bShowCurrent );
821 
822     int size_mm = -1;
823     Read( _T ( "DisplaySizeMM" ), &size_mm );
824 
825     Read( _T ( "SelectionRadiusMM" ), &g_selection_radius_mm);
826     Read( _T ( "SelectionRadiusTouchMM" ), &g_selection_radius_touch_mm);
827 
828     if(!bAsTemplate){
829         if(size_mm > 0){
830             g_config_display_size_mm = size_mm;
831             if((size_mm > 100) && (size_mm < 2000)){
832                 g_display_size_mm = size_mm;
833             }
834         }
835         Read( _T ( "DisplaySizeManual" ), &g_config_display_size_manual );
836     }
837 
838     Read( _T ( "GUIScaleFactor" ), &g_GUIScaleFactor );
839 
840     Read( _T ( "ChartObjectScaleFactor" ), &g_ChartScaleFactor );
841     Read( _T ( "ShipScaleFactor" ), &g_ShipScaleFactor );
842     Read( _T ( "ENCSoundingScaleFactor" ), &g_ENCSoundingScaleFactor );
843 
844     // Plugin catalog handler persistent variables.
845     Read( "CatalogCustomURL", &g_catalog_custom_url);
846     Read( "CatalogChannel", &g_catalog_channel);
847 
848 
849     //  NMEA connection options.
850     if( !bAsTemplate ){
851         Read( _T ( "FilterNMEA_Avg" ), &g_bfilter_cogsog );
852         Read( _T ( "FilterNMEA_Sec" ), &g_COGFilterSec );
853         Read( _T ( "GPSIdent" ), &g_GPS_Ident );
854         Read( _T ( "UseGarminHostUpload" ),  &g_bGarminHostUpload );
855         Read( _T ( "UseNMEA_GLL" ), &g_bUseGLL );
856         Read( _T ( "UseMagAPB" ), &g_bMagneticAPB );
857         Read( _T ( "TrackContinuous" ), &g_btrackContinuous, false );
858     }
859 
860     Read( _T ( "ShowTrue" ), &g_bShowTrue );
861     Read( _T ( "ShowMag" ), &g_bShowMag );
862 
863     wxString umv;
864     Read( _T ( "UserMagVariation" ), &umv );
865     if(umv.Len()) umv.ToDouble( &g_UserVar );
866 
867     Read( _T ( "ScreenBrightness" ), &g_nbrightness );
868 
869     Read( _T ( "MemFootprintTargetMB" ), &g_MemFootMB );
870 
871     Read( _T ( "WindowsComPortMax" ), &g_nCOMPortCheck );
872 
873     Read( _T ( "ChartQuilting" ), &g_bQuiltEnable );
874     Read( _T ( "ChartQuiltingInitial" ), &g_bQuiltStart );
875 
876     Read( _T ( "CourseUpMode" ), &g_bCourseUp );
877     Read( _T ( "COGUPAvgSeconds" ), &g_COGAvgSec );
878     Read( _T ( "LookAheadMode" ), &g_bLookAhead );
879     Read( _T ( "SkewToNorthUp" ), &g_bskew_comp );
880 
881     Read( _T ( "ShowFPS" ), &g_bShowFPS );
882 
883     Read( _T( "NMEAAPBPrecision" ), &g_NMEAAPBPrecision );
884 
885     Read( _T( "TalkerIdText" ), &g_TalkerIdText );
886     Read( _T( "MaxWaypointNameLength" ), &g_maxWPNameLength );
887 
888     Read( _T( "ShowTrackPointTime" ), &g_bShowTrackPointTime, true );
889     /* opengl options */
890 #ifdef ocpnUSE_GL
891     if(!bAsTemplate ){
892         Read( _T ( "OpenGLExpert" ), &g_bGLexpert, false );
893         Read( _T ( "UseAcceleratedPanning" ), &g_GLOptions.m_bUseAcceleratedPanning, true );
894         Read( _T ( "GPUTextureCompression" ), &g_GLOptions.m_bTextureCompression);
895         Read( _T ( "GPUTextureCompressionCaching" ), &g_GLOptions.m_bTextureCompressionCaching);
896         Read( _T ( "PolygonSmoothing" ), &g_GLOptions.m_GLPolygonSmoothing);
897         Read( _T ( "LineSmoothing" ), &g_GLOptions.m_GLLineSmoothing);
898         Read( _T ( "GPUTextureDimension" ), &g_GLOptions.m_iTextureDimension );
899         Read( _T ( "GPUTextureMemSize" ), &g_GLOptions.m_iTextureMemorySize );
900         Read( _T ( "DebugOpenGL" ), &g_bDebugOGL );
901         Read( _T ( "OpenGL" ), &g_bopengl );
902         Read( _T ( "SoftwareGL" ), &g_bSoftwareGL );
903     }
904 #endif
905 
906     Read( _T ( "SmoothPanZoom" ), &g_bsmoothpanzoom );
907 
908     Read( _T ( "ToolbarX"), &g_maintoolbar_x );
909     Read( _T ( "ToolbarY" ), &g_maintoolbar_y );
910     Read( _T ( "ToolbarOrient" ), &g_maintoolbar_orient );
911     Read( _T ( "GlobalToolbarConfig" ), &g_toolbarConfig );
912 
913     Read( _T ( "iENCToolbarX"), &g_iENCToolbarPosX );
914     Read( _T ( "iENCToolbarY"), &g_iENCToolbarPosY );
915 
916     Read( _T ( "AnchorWatch1GUID" ), &g_AW1GUID );
917     Read( _T ( "AnchorWatch2GUID" ), &g_AW2GUID );
918 
919     Read( _T ( "InitialStackIndex" ), &g_restore_stackindex );
920     Read( _T ( "InitialdBIndex" ), &g_restore_dbindex );
921 
922     Read( _T ( "ChartNotRenderScaleFactor" ), &g_ChartNotRenderScaleFactor );
923 
924     Read( _T ( "MobileTouch" ), &g_btouch );
925     Read( _T ( "ResponsiveGraphics" ), &g_bresponsive );
926     Read( _T ( "EnableRolloverBlock" ), &g_bRollover );
927 
928     Read( _T ( "ZoomDetailFactor" ), &g_chart_zoom_modifier );
929     Read( _T ( "ZoomDetailFactorVector" ), &g_chart_zoom_modifier_vector );
930     Read( _T ( "PlusMinusZoomFactor" ), &g_plus_minus_zoom_factor, 2.0);
931 
932     Read( _T ( "CM93DetailFactor" ), &g_cm93_zoom_factor );
933 
934     Read( _T ( "CM93DetailZoomPosX" ), &g_detailslider_dialog_x );
935     Read( _T ( "CM93DetailZoomPosY" ), &g_detailslider_dialog_y );
936     Read( _T ( "ShowCM93DetailSlider" ), &g_bShowDetailSlider );
937 
938     Read( _T ( "SENC_LOD_Pixels" ), &g_SENC_LOD_pixels );
939 
940     Read( _T ( "SkewCompUpdatePeriod" ), &g_SkewCompUpdatePeriod );
941 
942     Read( _T ( "SetSystemTime" ), &s_bSetSystemTime );
943     Read( _T ( "ShowStatusBar" ), &g_bShowStatusBar );
944 #ifndef __WXOSX__
945     Read( _T ( "ShowMenuBar" ), &g_bShowMenuBar );
946 #endif
947     Read( _T ( "Fullscreen" ), &g_bFullscreen );
948     Read( _T ( "ShowCompassWindow" ), &g_bShowCompassWin );
949     Read( _T ( "ShowGrid" ), &g_bDisplayGrid );
950     Read( _T ( "PlayShipsBells" ), &g_bPlayShipsBells );
951     Read( _T ( "SoundDeviceIndex" ), &g_iSoundDeviceIndex );
952     Read( _T ( "FullscreenToolbar" ), &g_bFullscreenToolbar );
953     Read( _T ( "PermanentMOBIcon" ), &g_bPermanentMOBIcon );
954     Read( _T ( "ShowLayers" ), &g_bShowLayers );
955     Read( _T ( "ShowDepthUnits" ), &g_bShowDepthUnits );
956     Read( _T ( "AutoAnchorDrop" ), &g_bAutoAnchorMark );
957     Read( _T ( "ShowChartOutlines" ), &g_bShowOutlines );
958     Read( _T ( "ShowActiveRouteHighway" ), &g_bShowActiveRouteHighway );
959     Read( _T ( "ShowActiveRouteTotal" ), &g_bShowRouteTotal );
960     Read( _T ( "MostRecentGPSUploadConnection" ), &g_uploadConnection);
961     Read( _T ( "ShowChartBar" ), &g_bShowChartBar );
962     Read( _T ( "SDMMFormat" ), &g_iSDMMFormat ); //0 = "Degrees, Decimal minutes"), 1 = "Decimal degrees", 2 = "Degrees,Minutes, Seconds"
963 
964     Read( _T ( "DistanceFormat" ), &g_iDistanceFormat ); //0 = "Nautical miles"), 1 = "Statute miles", 2 = "Kilometers", 3 = "Meters"
965     Read( _T ( "SpeedFormat" ), &g_iSpeedFormat ); //0 = "kts"), 1 = "mph", 2 = "km/h", 3 = "m/s"
966 
967     // LIVE ETA OPTION
968     Read( _T ( "LiveETA" ), &g_bShowLiveETA );
969     Read( _T ( "DefaultBoatSpeed" ), &g_defaultBoatSpeed );
970 
971     Read( _T ( "OwnshipCOGPredictorMinutes" ), &g_ownship_predictor_minutes );
972     Read( _T ( "OwnshipCOGPredictorWidth" ), &g_cog_predictor_width );
973     Read( _T ( "OwnshipHDTPredictorMiles" ), &g_ownship_HDTpredictor_miles );
974 
975     Read( _T ( "OwnShipIconType" ), &g_OwnShipIconType );
976     Read( _T ( "OwnShipLength" ), &g_n_ownship_length_meters );
977     Read( _T ( "OwnShipWidth" ), &g_n_ownship_beam_meters );
978     Read( _T ( "OwnShipGPSOffsetX" ), &g_n_gps_antenna_offset_x );
979     Read( _T ( "OwnShipGPSOffsetY" ), &g_n_gps_antenna_offset_y );
980     Read( _T ( "OwnShipMinSize" ), &g_n_ownship_min_mm );
981     Read( _T ( "OwnShipSogCogCalc" ), &g_own_ship_sog_cog_calc );
982     Read( _T ( "OwnShipSogCogCalcDampSec"), &g_own_ship_sog_cog_calc_damp_sec );
983 
984     wxString racr;
985     Read( _T ( "RouteArrivalCircleRadius" ), &racr );
986     if(racr.Len())
987         racr.ToDouble( &g_n_arrival_circle_radius);
988 
989     Read( _T ( "FullScreenQuilt" ), &g_bFullScreenQuilt );
990 
991     Read( _T ( "StartWithTrackActive" ), &g_bTrackCarryOver );
992     Read( _T ( "AutomaticDailyTracks" ), &g_bTrackDaily );
993     Read( _T ( "TrackRotateAt" ), &g_track_rotate_time );
994     Read( _T ( "TrackRotateTimeType" ), &g_track_rotate_time_type );
995     Read( _T ( "HighlightTracks" ), &g_bHighliteTracks );
996 
997     wxString stps;
998     Read( _T ( "PlanSpeed" ), &stps );
999     if(!stps.IsEmpty())
1000         stps.ToDouble( &g_PlanSpeed );
1001 
1002     Read( _T ( "VisibleLayers" ), &g_VisibleLayers );
1003     Read( _T ( "InvisibleLayers" ), &g_InvisibleLayers );
1004     Read( _T ( "VisNameInLayers" ), &g_VisiNameinLayers );
1005     Read( _T ( "InvisNameInLayers" ), &g_InVisiNameinLayers );
1006 
1007     Read( _T ( "PreserveScaleOnX" ), &g_bPreserveScaleOnX );
1008 
1009     Read( _T ( "ShowMUIZoomButtons" ), &g_bShowMuiZoomButtons );
1010 
1011     Read( _T ( "Locale" ), &g_locale );
1012     Read( _T ( "LocaleOverride" ), &g_localeOverride );
1013 
1014     //We allow 0-99 backups ov navobj.xml
1015     Read( _T ( "KeepNavobjBackups" ), &g_navobjbackups );
1016 
1017     NMEALogWindow::Get().SetSize(Read(_T("NMEALogWindowSizeX"), 600L), Read(_T("NMEALogWindowSizeY"), 400L));
1018     NMEALogWindow::Get().SetPos(Read(_T("NMEALogWindowPosX"), 10L), Read(_T("NMEALogWindowPosY"), 10L));
1019     NMEALogWindow::Get().CheckPos(display_width, display_height);
1020 
1021     // Boolean to cater for legacy Input COM Port filer behaviour, i.e. show msg filtered but put msg on bus.
1022     Read( _T ( "LegacyInputCOMPortFilterBehaviour" ), &g_b_legacy_input_filter_behaviour );
1023 
1024     // Boolean to cater for sailing when not approaching waypoint
1025     Read( _T( "AdvanceRouteWaypointOnArrivalOnly" ), &g_bAdvanceRouteWaypointOnArrivalOnly);
1026 
1027     Read( _T ( "EnableRotateKeys" ),  &g_benable_rotate );
1028     Read( _T ( "EmailCrashReport" ),  &g_bEmailCrashReport );
1029 
1030     g_benableAISNameCache = true;
1031     Read( _T ( "EnableAISNameCache" ),  &g_benableAISNameCache );
1032 
1033     Read( _T ( "EnableUDPNullHeader" ),  &g_benableUDPNullHeader );
1034 
1035     SetPath( _T ( "/Settings/GlobalState" ) );
1036 
1037     Read( _T ( "FrameWinX" ), &g_nframewin_x );
1038     Read( _T ( "FrameWinY" ), &g_nframewin_y );
1039     Read( _T ( "FrameWinPosX" ), &g_nframewin_posx );
1040     Read( _T ( "FrameWinPosY" ), &g_nframewin_posy );
1041     Read( _T ( "FrameMax" ), &g_bframemax );
1042 
1043     Read( _T ( "ClientPosX" ), &g_lastClientRectx );
1044     Read( _T ( "ClientPosY" ), &g_lastClientRecty );
1045     Read( _T ( "ClientSzX" ), &g_lastClientRectw );
1046     Read( _T ( "ClientSzY" ), &g_lastClientRecth );
1047 
1048     Read( _T( "RoutePropSizeX" ), &g_route_prop_sx );
1049     Read( _T( "RoutePropSizeY" ), &g_route_prop_sy );
1050     Read( _T( "RoutePropPosX" ), &g_route_prop_x );
1051     Read( _T( "RoutePropPosY" ), &g_route_prop_y );
1052 
1053     read_int = -1;
1054     Read( _T ( "S52_DEPTH_UNIT_SHOW" ), &read_int );   // default is metres
1055     if(read_int >= 0){
1056         read_int = wxMax(read_int, 0);                      // qualify value
1057         read_int = wxMin(read_int, 2);
1058         g_nDepthUnitDisplay = read_int;
1059     }
1060 
1061     //    AIS
1062     wxString s;
1063     SetPath( _T ( "/Settings/AIS" ) );
1064 
1065     g_bUseOnlyConfirmedAISName = false;
1066     Read( _T ( "UseOnlyConfirmedAISName" ),  &g_bUseOnlyConfirmedAISName );
1067 
1068     Read( _T ( "bNoCPAMax" ), &g_bCPAMax );
1069 
1070     Read( _T ( "NoCPAMaxNMi" ), &s );
1071     s.ToDouble( &g_CPAMax_NM );
1072 
1073     Read( _T ( "bCPAWarn" ), &g_bCPAWarn );
1074 
1075     Read( _T ( "CPAWarnNMi" ), &s );
1076     s.ToDouble( &g_CPAWarn_NM );
1077 
1078     Read( _T ( "bTCPAMax" ), &g_bTCPA_Max );
1079 
1080     Read( _T ( "TCPAMaxMinutes" ), &s );
1081     s.ToDouble( &g_TCPA_Max );
1082 
1083     Read( _T ( "bMarkLostTargets" ), &g_bMarkLost );
1084 
1085     Read( _T ( "MarkLost_Minutes" ), &s );
1086     s.ToDouble( &g_MarkLost_Mins );
1087 
1088     Read( _T ( "bRemoveLostTargets" ), &g_bRemoveLost );
1089 
1090     Read( _T ( "RemoveLost_Minutes" ), &s );
1091     s.ToDouble( &g_RemoveLost_Mins );
1092 
1093     Read( _T ( "bShowCOGArrows" ), &g_bShowCOG );
1094 
1095     Read( _T ( "CogArrowMinutes" ), &s );
1096     s.ToDouble( &g_ShowCOG_Mins );
1097 
1098     Read( _T ( "bShowTargetTracks" ), &g_bAISShowTracks );
1099 
1100 
1101     if( Read( _T ( "TargetTracksLimit" ), &s ) ) {
1102         s.ToDouble( &g_AISShowTracks_Limit );
1103         g_AISShowTracks_Limit = wxMax(300.0, g_AISShowTracks_Limit);
1104     }
1105     if( Read( _T ( "TargetTracksMinutes" ), &s ) ) {
1106         s.ToDouble( &g_AISShowTracks_Mins );
1107         g_AISShowTracks_Mins = wxMax(1.0, g_AISShowTracks_Mins);
1108         g_AISShowTracks_Mins = wxMin(g_AISShowTracks_Limit, g_AISShowTracks_Mins);
1109     }
1110 
1111     Read( _T ( "bHideMooredTargets" ), &g_bHideMoored );
1112     if(Read( _T ( "MooredTargetMaxSpeedKnots" ), &s ))
1113         s.ToDouble( &g_ShowMoored_Kts );
1114 
1115     Read(_T ("bShowScaledTargets"), &g_bAllowShowScaled );
1116     Read( _T ( "AISScaledNumber" ), &g_ShowScaled_Num );
1117     Read( _T ( "AISScaledNumberWeightSOG" ), &g_ScaledNumWeightSOG );
1118     Read( _T ( "AISScaledNumberWeightCPA" ), &g_ScaledNumWeightCPA );
1119     Read( _T ( "AISScaledNumberWeightTCPA" ), &g_ScaledNumWeightTCPA );
1120     Read( _T ( "AISScaledNumberWeightRange" ),& g_ScaledNumWeightRange );
1121     Read( _T ( "AISScaledNumberWeightSizeOfTarget" ), &g_ScaledNumWeightSizeOfT );
1122     Read( _T ( "AISScaledSizeMinimal" ), &g_ScaledSizeMinimal );
1123     Read(_T("AISShowScaled"), &g_bShowScaled );
1124 
1125     Read( _T ( "bShowAreaNotices" ), &g_bShowAreaNotices );
1126     Read( _T ( "bDrawAISSize" ), &g_bDrawAISSize );
1127     Read( _T ( "bDrawAISRealtime" ), &g_bDrawAISRealtime );
1128     Read( _T ( "bShowAISName" ), &g_bShowAISName );
1129     Read( _T ( "AISRealtimeMinSpeedKnots" ), &g_AIS_RealtPred_Kts, 0.7 );
1130     Read( _T ( "bAISAlertDialog" ), &g_bAIS_CPA_Alert );
1131     Read( _T ( "ShowAISTargetNameScale" ), &g_Show_Target_Name_Scale );
1132     Read( _T ( "bWplIsAprsPositionReport" ), &g_bWplIsAprsPosition );
1133     Read( _T ( "AISCOGPredictorWidth" ), &g_ais_cog_predictor_width );
1134 
1135     Read( _T ( "bAISAlertAudio" ), &g_bAIS_CPA_Alert_Audio );
1136     Read( _T ( "AISAlertAudioFile" ), &g_sAIS_Alert_Sound_File );
1137     Read( _T ( "bAISAlertSuppressMoored" ), &g_bAIS_CPA_Alert_Suppress_Moored );
1138 
1139     Read( _T ( "bAISAlertAckTimeout" ), &g_bAIS_ACK_Timeout );
1140     if(Read( _T ( "AlertAckTimeoutMinutes" ), &s ))
1141         s.ToDouble( &g_AckTimeout_Mins );
1142 
1143     Read( _T ( "AlertDialogSizeX" ), &g_ais_alert_dialog_sx );
1144     Read( _T ( "AlertDialogSizeY" ), &g_ais_alert_dialog_sy );
1145     Read( _T ( "AlertDialogPosX" ), &g_ais_alert_dialog_x );
1146     Read( _T ( "AlertDialogPosY" ), &g_ais_alert_dialog_y );
1147     Read( _T ( "QueryDialogPosX" ), &g_ais_query_dialog_x );
1148     Read( _T ( "QueryDialogPosY" ), &g_ais_query_dialog_y );
1149 
1150     Read( _T ( "AISTargetListPerspective" ), &g_AisTargetList_perspective );
1151     Read( _T ( "AISTargetListRange" ), &g_AisTargetList_range );
1152     Read( _T ( "AISTargetListSortColumn" ), &g_AisTargetList_sortColumn );
1153     Read( _T ( "bAISTargetListSortReverse" ), &g_bAisTargetList_sortReverse );
1154     Read( _T ( "AISTargetListColumnSpec" ), &g_AisTargetList_column_spec );
1155     Read( _T ("AISTargetListColumnOrder"), &g_AisTargetList_column_order);
1156 
1157     Read( _T ( "bAISRolloverShowClass" ), &g_bAISRolloverShowClass );
1158     Read( _T ( "bAISRolloverShowCOG" ), &g_bAISRolloverShowCOG );
1159     Read( _T ( "bAISRolloverShowCPA" ), &g_bAISRolloverShowCPA );
1160 
1161     Read( _T ( "S57QueryDialogSizeX" ), &g_S57_dialog_sx );
1162     Read( _T ( "S57QueryDialogSizeY" ), &g_S57_dialog_sy );
1163     Read( _T ( "S57QueryExtraDialogSizeX" ), &g_S57_extradialog_sx );
1164     Read( _T ( "S57QueryExtraDialogSizeY" ), &g_S57_extradialog_sy );
1165 
1166 
1167     wxString strpres( _T ( "PresentationLibraryData" ) );
1168     wxString valpres;
1169     SetPath( _T ( "/Directories" ) );
1170     Read( strpres, &valpres );              // Get the File name
1171     if(!valpres.IsEmpty())
1172         g_UserPresLibData = valpres;
1173 
1174     wxString strs( _T ( "SENCFileLocation" ) );
1175     SetPath( _T ( "/Directories" ) );
1176     wxString vals;
1177     Read( strs, &vals );              // Get the Directory name
1178     if(!vals.IsEmpty())
1179         g_SENCPrefix = vals;
1180 
1181     SetPath( _T ( "/Directories" ) );
1182     wxString vald;
1183     Read( _T ( "InitChartDir" ), &vald );           // Get the Directory name
1184 
1185     wxString dirnamed( vald );
1186     if( !dirnamed.IsEmpty() ) {
1187         if( pInit_Chart_Dir->IsEmpty() )   // on second pass, don't overwrite
1188         {
1189             pInit_Chart_Dir->Clear();
1190             pInit_Chart_Dir->Append( vald );
1191         }
1192     }
1193 
1194     Read( _T ( "GPXIODir" ), &g_gpx_path );           // Get the Directory name
1195     Read( _T ( "TCDataDir" ), &g_TCData_Dir );           // Get the Directory name
1196     Read( _T ( "BasemapDir"), &gWorldMapLocation );
1197     Read( _T ( "pluginInstallDir"), &g_winPluginDir );
1198     wxLogMessage("winPluginDir, read from ini file: %s",
1199                  g_winPluginDir.mb_str().data());
1200 
1201 
1202     SetPath( _T ( "/Settings/GlobalState" ) );
1203 
1204     if(Read( _T ( "nColorScheme" ), &read_int ))
1205         global_color_scheme = (ColorScheme) read_int;
1206 
1207     if(! bAsTemplate ){
1208         SetPath( _T ( "/Settings/NMEADataSource" ) );
1209 
1210         wxString connectionconfigs;
1211         Read ( _T( "DataConnections" ),  &connectionconfigs );
1212         if(!connectionconfigs.IsEmpty()){
1213             wxArrayString confs = wxStringTokenize(connectionconfigs, _T("|"));
1214             g_pConnectionParams->Clear();
1215             for (size_t i = 0; i < confs.Count(); i++)
1216             {
1217                 ConnectionParams * prm = new ConnectionParams(confs[i]);
1218                 if (!prm->Valid) {
1219                     wxLogMessage( _T( "Skipped invalid DataStream config") );
1220                     delete prm;
1221                     continue;
1222                 }
1223                 g_pConnectionParams->Add(prm);
1224             }
1225         }
1226     }
1227 
1228 
1229 
1230     SetPath( _T ( "/Settings/GlobalState" ) );
1231     wxString st;
1232 
1233     double st_lat, st_lon;
1234     if( Read( _T ( "VPLatLon" ), &st ) ) {
1235         sscanf( st.mb_str( wxConvUTF8 ), "%lf,%lf", &st_lat, &st_lon );
1236 
1237         //    Sanity check the lat/lon...both have to be reasonable.
1238         if( fabs( st_lon ) < 360. ) {
1239             while( st_lon < -180. )
1240                 st_lon += 360.;
1241 
1242             while( st_lon > 180. )
1243                 st_lon -= 360.;
1244 
1245             vLon = st_lon;
1246         }
1247 
1248         if( fabs( st_lat ) < 90.0 ) vLat = st_lat;
1249 
1250         s.Printf( _T ( "Setting Viewpoint Lat/Lon %g, %g" ), vLat, vLon );
1251         wxLogMessage( s );
1252 
1253     }
1254 
1255     double st_view_scale, st_rotation;
1256     if( Read( wxString( _T ( "VPScale" ) ), &st ) ) {
1257         sscanf( st.mb_str( wxConvUTF8 ), "%lf", &st_view_scale );
1258 //    Sanity check the scale
1259         st_view_scale = fmax ( st_view_scale, .001/32 );
1260         st_view_scale = fmin ( st_view_scale, 4 );
1261         initial_scale_ppm = st_view_scale;
1262     }
1263 
1264     if( Read( wxString( _T ( "VPRotation" ) ), &st ) ) {
1265         sscanf( st.mb_str( wxConvUTF8 ), "%lf", &st_rotation );
1266 //    Sanity check the rotation
1267         st_rotation = fmin ( st_rotation, 360 );
1268         st_rotation = fmax ( st_rotation, 0 );
1269         initial_rotation = st_rotation * PI / 180.;
1270     }
1271 
1272     wxString sll;
1273     double lat, lon;
1274     if( Read( _T ( "OwnShipLatLon" ), &sll ) ) {
1275         sscanf( sll.mb_str( wxConvUTF8 ), "%lf,%lf", &lat, &lon );
1276 
1277         //    Sanity check the lat/lon...both have to be reasonable.
1278         if( fabs( lon ) < 360. ) {
1279             while( lon < -180. )
1280                 lon += 360.;
1281 
1282             while( lon > 180. )
1283                 lon -= 360.;
1284 
1285             gLon = lon;
1286         }
1287 
1288         if( fabs( lat ) < 90.0 ) gLat = lat;
1289 
1290         s.Printf( _T ( "Setting Ownship Lat/Lon %g, %g" ), gLat, gLon );
1291         wxLogMessage( s );
1292 
1293     }
1294 
1295 //    Fonts
1296 
1297     //  Load the persistent Auxiliary Font descriptor Keys
1298     SetPath ( _T ( "/Settings/AuxFontKeys" ) );
1299 
1300     wxString strk;
1301     long dummyk;
1302     wxString kval;
1303     bool bContk = GetFirstEntry( strk, dummyk );
1304     bool bNewKey = false;
1305     while( bContk ) {
1306         Read( strk, &kval );
1307         bNewKey = FontMgr::Get().AddAuxKey(kval);
1308         if(!bAsTemplate && !bNewKey) {
1309             DeleteEntry( strk );
1310             dummyk--;
1311         }
1312         bContk = GetNextEntry( strk, dummyk );
1313     }
1314 
1315 #ifdef __WXX11__
1316     SetPath ( _T ( "/Settings/X11Fonts" ) );
1317 #endif
1318 
1319 #ifdef __WXGTK__
1320     SetPath ( _T ( "/Settings/GTKFonts" ) );
1321 #endif
1322 
1323 #ifdef __WXMSW__
1324     SetPath( _T ( "/Settings/MSWFonts" ) );
1325 #endif
1326 
1327 #ifdef __WXMAC__
1328     SetPath ( _T ( "/Settings/MacFonts" ) );
1329 #endif
1330 
1331 #ifdef __WXQT__
1332     SetPath ( _T ( "/Settings/QTFonts" ) );
1333 #endif
1334 
1335     wxString str;
1336     long dummy;
1337     wxString *pval = new wxString;
1338     wxArrayString deleteList;
1339 
1340     bool bCont = GetFirstEntry( str, dummy );
1341     while( bCont ) {
1342         Read( str, pval );
1343 
1344         if( str.StartsWith( _T("Font") ) ) {
1345             // Convert pre 3.1 setting. Can't delete old entries from inside the
1346             // GetNextEntry() loop, so we need to save those and delete outside.
1347             deleteList.Add( str );
1348             wxString oldKey = pval->BeforeFirst( _T(':') );
1349             str = FontMgr::GetFontConfigKey( oldKey );
1350         }
1351 
1352         if( pval->IsEmpty() || pval->StartsWith(_T(":")) ) {
1353             deleteList.Add( str );
1354         }
1355         else
1356             FontMgr::Get().LoadFontNative( &str, pval );
1357 
1358         bCont = GetNextEntry( str, dummy );
1359     }
1360 
1361     for( unsigned int i=0; i<deleteList.Count(); i++ ) {
1362         DeleteEntry( deleteList[i] );
1363     }
1364     deleteList.Clear();
1365     delete pval;
1366 
1367 //  Tide/Current Data Sources
1368     SetPath( _T ( "/TideCurrentDataSources" ) );
1369     if( GetNumberOfEntries() ) {
1370         TideCurrentDataSet.Clear();
1371         wxString str, val;
1372         long dummy;
1373         bool bCont = GetFirstEntry( str, dummy );
1374         while( bCont ) {
1375             Read( str, &val );              // Get a file name
1376             TideCurrentDataSet.Add(val);
1377             bCont = GetNextEntry( str, dummy );
1378         }
1379     }
1380 
1381 
1382 
1383     //    Groups
1384     LoadConfigGroups( g_pGroupArray );
1385 
1386 //     //    Multicanvas Settings
1387 //     LoadCanvasConfigs();
1388 
1389     SetPath( _T ( "/Settings/Others" ) );
1390 
1391     // Radar rings
1392     Read( _T ( "RadarRingsNumberVisible" ), &val );
1393     if( val.Length() > 0 ) g_iNavAidRadarRingsNumberVisible = atoi( val.mb_str() );
1394 
1395     Read( _T ( "RadarRingsStep" ), &val );
1396     if( val.Length() > 0 ) g_fNavAidRadarRingsStep = atof( val.mb_str() );
1397 
1398     Read( _T ( "RadarRingsStepUnits" ), &g_pNavAidRadarRingsStepUnits );
1399 
1400     wxString l_wxsOwnshipRangeRingsColour;
1401     Read( _T ( "RadarRingsColour" ), &l_wxsOwnshipRangeRingsColour );
1402     if(l_wxsOwnshipRangeRingsColour.Length()) g_colourOwnshipRangeRingsColour.Set( l_wxsOwnshipRangeRingsColour );
1403 
1404     // Waypoint Radar rings
1405     Read( _T ( "WaypointRangeRingsNumber" ), &val );
1406     if( val.Length() > 0 ) g_iWaypointRangeRingsNumber = atoi( val.mb_str() );
1407 
1408     Read( _T ( "WaypointRangeRingsStep" ), &val );
1409     if( val.Length() > 0 ) g_fWaypointRangeRingsStep = atof( val.mb_str() );
1410 
1411     Read( _T ( "WaypointRangeRingsStepUnits" ), &g_iWaypointRangeRingsStepUnits );
1412 
1413     wxString l_wxsWaypointRangeRingsColour;
1414     Read( _T( "WaypointRangeRingsColour" ), &l_wxsWaypointRangeRingsColour );
1415     g_colourWaypointRangeRingsColour.Set( l_wxsWaypointRangeRingsColour );
1416 
1417     if ( !Read( _T("WaypointUseScaMin"), &g_bUseWptScaMin ) ) g_bUseWptScaMin = false;
1418     if ( !Read( _T("WaypointScaMinValue"), &g_iWpt_ScaMin ) ) g_iWpt_ScaMin = 2147483646;
1419     if ( !Read( _T("WaypointUseScaMinOverrule"), &g_bOverruleScaMin ) ) g_bOverruleScaMin = false;
1420     if ( !Read( _T("WaypointsShowName"), &g_bShowWptName ) ) g_bShowWptName = true;
1421 
1422 
1423 
1424     //  Support Version 3.0 and prior config setting for Radar Rings
1425     bool b300RadarRings= true;
1426     if(Read ( _T ( "ShowRadarRings" ), &b300RadarRings )){
1427         if(!b300RadarRings)
1428             g_iNavAidRadarRingsNumberVisible = 0;
1429     }
1430 
1431     Read( _T ( "ConfirmObjectDeletion" ), &g_bConfirmObjectDelete );
1432 
1433     // Waypoint dragging with mouse
1434     g_bWayPointPreventDragging = false;
1435     Read( _T ( "WaypointPreventDragging" ), &g_bWayPointPreventDragging );
1436 
1437     g_bEnableZoomToCursor = false;
1438     Read( _T ( "EnableZoomToCursor" ), &g_bEnableZoomToCursor );
1439 
1440     val.Clear();
1441     Read( _T ( "TrackIntervalSeconds" ), &val );
1442     if( val.Length() > 0 ) {
1443         double tval = atof( val.mb_str() );
1444         if( tval >= 2. ) g_TrackIntervalSeconds = tval;
1445     }
1446 
1447     val.Clear();
1448     Read( _T ( "TrackDeltaDistance" ), &val );
1449     if( val.Length() > 0 ) {
1450         double tval = atof( val.mb_str() );
1451         if( tval >= 0.05 ) g_TrackDeltaDistance = tval;
1452     }
1453 
1454     Read( _T ( "TrackPrecision" ), &g_nTrackPrecision );
1455 
1456     Read( _T ( "NavObjectFileName" ), m_sNavObjSetFile );
1457 
1458     Read( _T ( "RouteLineWidth" ), &g_route_line_width );
1459     Read( _T ( "TrackLineWidth" ), &g_track_line_width );
1460 
1461     wxString l_wxsTrackLineColour;
1462     if(Read( _T( "TrackLineColour" ), &l_wxsTrackLineColour ))
1463         g_colourTrackLineColour.Set( l_wxsTrackLineColour );
1464 
1465     Read( _T ( "TideCurrentWindowScale" ), &g_tcwin_scale );
1466     Read( _T ( "DefaultWPIcon" ), &g_default_wp_icon );
1467     Read( _T ( "DefaultRPIcon" ), &g_default_routepoint_icon );
1468 
1469     SetPath( _T ( "/MMSIProperties" ) );
1470     int iPMax = GetNumberOfEntries();
1471     if( iPMax ) {
1472         g_MMSI_Props_Array.Empty();
1473         wxString str, val;
1474         long dummy;
1475         bool bCont = pConfig->GetFirstEntry( str, dummy );
1476         while( bCont ) {
1477             pConfig->Read( str, &val );              // Get an entry
1478 
1479             MMSIProperties *pProps = new MMSIProperties( val );
1480             g_MMSI_Props_Array.Add(pProps);
1481 
1482             bCont = pConfig->GetNextEntry( str, dummy );
1483 
1484         }
1485     }
1486 
1487     return ( 0 );
1488 }
1489 
LoadS57Config()1490 void MyConfig::LoadS57Config()
1491 {
1492     if( !ps52plib )
1493         return;
1494 
1495     int read_int;
1496     double dval;
1497     SetPath( _T ( "/Settings/GlobalState" ) );
1498 
1499     Read( _T ( "bShowS57Text" ), &read_int, 1 );
1500     ps52plib->SetShowS57Text( !( read_int == 0 ) );
1501 
1502     Read( _T ( "bShowS57ImportantTextOnly" ), &read_int, 0 );
1503     ps52plib->SetShowS57ImportantTextOnly( !( read_int == 0 ) );
1504 
1505     Read( _T ( "bShowLightDescription" ), &read_int, 0 );
1506     ps52plib->SetShowLdisText( !( read_int == 0 ) );
1507 
1508     Read( _T ( "bExtendLightSectors" ), &read_int, 0 );
1509     ps52plib->SetExtendLightSectors( !( read_int == 0 ) );
1510 
1511     Read( _T ( "nDisplayCategory" ), &read_int, (enum _DisCat) STANDARD );
1512     ps52plib->SetDisplayCategory((enum _DisCat) read_int );
1513 
1514     Read( _T ( "nSymbolStyle" ), &read_int, (enum _LUPname) PAPER_CHART );
1515     ps52plib->m_nSymbolStyle = (LUPname) read_int;
1516 
1517     Read( _T ( "nBoundaryStyle" ), &read_int, PLAIN_BOUNDARIES );
1518     ps52plib->m_nBoundaryStyle = (LUPname) read_int;
1519 
1520     Read( _T ( "bShowSoundg" ), &read_int, 1 );
1521     ps52plib->m_bShowSoundg = !( read_int == 0 );
1522 
1523     Read( _T ( "bShowMeta" ), &read_int, 0 );
1524     ps52plib->m_bShowMeta = !( read_int == 0 );
1525 
1526     Read( _T ( "bUseSCAMIN" ), &read_int, 1 );
1527     ps52plib->m_bUseSCAMIN = !( read_int == 0 );
1528 
1529     Read( _T ( "bShowAtonText" ), &read_int, 1 );
1530     ps52plib->m_bShowAtonText = !( read_int == 0 );
1531 
1532     Read( _T ( "bDeClutterText" ), &read_int, 0 );
1533     ps52plib->m_bDeClutterText = !( read_int == 0 );
1534 
1535     Read( _T ( "bShowNationalText" ), &read_int, 0 );
1536     ps52plib->m_bShowNationalTexts = !( read_int == 0 );
1537 
1538     Read( _T ( "ENCSoundingScaleFactor" ), &read_int, 0 );
1539     ps52plib->m_nSoundingFactor = read_int;
1540 
1541 
1542     if( Read( _T ( "S52_MAR_SAFETY_CONTOUR" ), &dval, 3.0 ) ) {
1543         S52_setMarinerParam( S52_MAR_SAFETY_CONTOUR, dval );
1544         S52_setMarinerParam( S52_MAR_SAFETY_DEPTH, dval ); // Set safety_contour and safety_depth the same
1545     }
1546 
1547     if( Read( _T ( "S52_MAR_SHALLOW_CONTOUR" ), &dval, 2.0 ) ) S52_setMarinerParam(
1548         S52_MAR_SHALLOW_CONTOUR, dval );
1549 
1550     if( Read( _T ( "S52_MAR_DEEP_CONTOUR" ), &dval, 6.0 ) ) S52_setMarinerParam(
1551         S52_MAR_DEEP_CONTOUR, dval );
1552 
1553     if( Read( _T ( "S52_MAR_TWO_SHADES" ), &dval, 0.0 ) ) S52_setMarinerParam(
1554         S52_MAR_TWO_SHADES, dval );
1555 
1556     ps52plib->UpdateMarinerParams();
1557 
1558     SetPath( _T ( "/Settings/GlobalState" ) );
1559     Read( _T ( "S52_DEPTH_UNIT_SHOW" ), &read_int, 1 );   // default is metres
1560     read_int = wxMax(read_int, 0);                      // qualify value
1561     read_int = wxMin(read_int, 2);
1562     ps52plib->m_nDepthUnitDisplay = read_int;
1563     g_nDepthUnitDisplay = read_int;
1564 
1565 //    S57 Object Class Visibility
1566 
1567     OBJLElement *pOLE;
1568 
1569     SetPath( _T ( "/Settings/ObjectFilter" ) );
1570 
1571     int iOBJMax = GetNumberOfEntries();
1572     if( iOBJMax ) {
1573 
1574         wxString str;
1575         long val;
1576         long dummy;
1577 
1578         wxString sObj;
1579 
1580         bool bCont = pConfig->GetFirstEntry( str, dummy );
1581         while( bCont ) {
1582             pConfig->Read( str, &val );              // Get an Object Viz
1583 
1584             bool bNeedNew = true;
1585 
1586             if( str.StartsWith( _T ( "viz" ), &sObj ) ) {
1587                 for( unsigned int iPtr = 0; iPtr < ps52plib->pOBJLArray->GetCount(); iPtr++ ) {
1588                     pOLE = (OBJLElement *) ( ps52plib->pOBJLArray->Item( iPtr ) );
1589                     if( !strncmp( pOLE->OBJLName, sObj.mb_str(), 6 ) ) {
1590                         pOLE->nViz = val;
1591                         bNeedNew = false;
1592                         break;
1593                     }
1594                 }
1595 
1596                 if( bNeedNew ) {
1597                     pOLE = (OBJLElement *) calloc( sizeof(OBJLElement), 1 );
1598                     memcpy( pOLE->OBJLName, sObj.mb_str(), OBJL_NAME_LEN );
1599                     pOLE->nViz = 1;
1600 
1601                     ps52plib->pOBJLArray->Add( (void *) pOLE );
1602                 }
1603             }
1604             bCont = pConfig->GetNextEntry( str, dummy );
1605         }
1606     }
1607 }
1608 
LoadNavObjects()1609 void MyConfig::LoadNavObjects()
1610 {
1611     //      next thing to do is read tracks, etc from the NavObject XML file,
1612     wxLogMessage( _T("Loading navobjects from navobj.xml") );
1613     CreateRotatingNavObjBackup();
1614 
1615     if( NULL == m_pNavObjectInputSet )
1616         m_pNavObjectInputSet = new NavObjectCollection1();
1617 
1618     int wpt_dups = 0;
1619     if( ::wxFileExists( m_sNavObjSetFile ) &&
1620         m_pNavObjectInputSet->load_file( m_sNavObjSetFile.fn_str() ) )
1621         m_pNavObjectInputSet->LoadAllGPXObjects(false, wpt_dups);
1622 
1623     wxLogMessage( _T("Done loading navobjects, %d duplicate waypoints ignored"), wpt_dups );
1624     delete m_pNavObjectInputSet;
1625 
1626     if( ::wxFileExists( m_sNavObjSetChangesFile ) ) {
1627 
1628         wxULongLong size = wxFileName::GetSize(m_sNavObjSetChangesFile);
1629 
1630         //We crashed last time :(
1631         //That's why this file still exists...
1632         //Let's reconstruct the unsaved changes
1633         NavObjectChanges *pNavObjectChangesSet = new NavObjectChanges();
1634         pNavObjectChangesSet->load_file( m_sNavObjSetChangesFile.fn_str() );
1635 
1636         //  Remove the file before applying the changes,
1637         //  just in case the changes file itself causes a fault.
1638         //  If it does fault, at least the next restart will proceed without fault.
1639         if( ::wxFileExists( m_sNavObjSetChangesFile ) )
1640             ::wxRemoveFile( m_sNavObjSetChangesFile );
1641 
1642         if(size != 0){
1643             wxLogMessage( _T("Applying NavObjChanges") );
1644             pNavObjectChangesSet->ApplyChanges();
1645             UpdateNavObj();
1646         }
1647 
1648         delete pNavObjectChangesSet;
1649 
1650     }
1651 
1652     m_pNavObjectChangesSet = new NavObjectChanges(m_sNavObjSetChangesFile);
1653 }
1654 
LoadLayers(wxString & path)1655 bool MyConfig::LoadLayers(wxString &path)
1656 {
1657     wxArrayString file_array;
1658     wxDir dir;
1659     Layer *l;
1660     dir.Open( path );
1661     if( dir.IsOpened() ) {
1662         wxString filename;
1663         bool cont = dir.GetFirst( &filename );
1664         while( cont ) {
1665             file_array.Clear();
1666             filename.Prepend( wxFileName::GetPathSeparator() );
1667             filename.Prepend( path );
1668             wxFileName f( filename );
1669             size_t nfiles = 0;
1670             if( f.GetExt().IsSameAs( wxT("gpx") ) )
1671                 file_array.Add( filename); // single-gpx-file layer
1672             else{
1673                 if(wxDir::Exists( filename ) ){
1674                     wxDir dir( filename );
1675                     if( dir.IsOpened() ){
1676                         nfiles = dir.GetAllFiles( filename, &file_array, wxT("*.gpx") );      // layers subdirectory set
1677                     }
1678                 }
1679             }
1680 
1681             if( file_array.GetCount() ){
1682                 l = new Layer();
1683                 l->m_LayerID = ++g_LayerIdx;
1684                 l->m_LayerFileName = file_array[0];
1685                 if( file_array.GetCount() <= 1 )
1686                     wxFileName::SplitPath( file_array[0], NULL, NULL, &( l->m_LayerName ), NULL, NULL );
1687                 else
1688                     wxFileName::SplitPath( filename, NULL, NULL, &( l->m_LayerName ), NULL, NULL );
1689 
1690                 bool bLayerViz = g_bShowLayers;
1691 
1692                 if( g_VisibleLayers.Contains( l->m_LayerName ) )
1693                     bLayerViz = true;
1694                 if( g_InvisibleLayers.Contains( l->m_LayerName ) )
1695                     bLayerViz = false;
1696 
1697                 l->m_bHasVisibleNames = wxCHK_UNDETERMINED;
1698                 if (g_VisiNameinLayers.Contains(l->m_LayerName))
1699                     l->m_bHasVisibleNames = wxCHK_CHECKED;
1700                 if (g_InVisiNameinLayers.Contains(l->m_LayerName))
1701                     l->m_bHasVisibleNames = wxCHK_UNCHECKED;
1702 
1703                 l->m_bIsVisibleOnChart = bLayerViz;
1704 
1705                 wxString laymsg;
1706                 laymsg.Printf( wxT("New layer %d: %s"), l->m_LayerID, l->m_LayerName.c_str() );
1707                 wxLogMessage( laymsg );
1708 
1709                 pLayerList->Insert( l );
1710 
1711                 //  Load the entire file array as a single layer
1712 
1713                 for( unsigned int i = 0; i < file_array.GetCount(); i++ ) {
1714                     wxString file_path = file_array[i];
1715 
1716                     if( ::wxFileExists( file_path ) ) {
1717                         NavObjectCollection1 *pSet = new NavObjectCollection1;
1718                         pSet->load_file(file_path.fn_str());
1719                         long nItems = pSet->LoadAllGPXObjectsAsLayer(l->m_LayerID, bLayerViz, l->m_bHasVisibleNames);
1720                         l->m_NoOfItems += nItems;
1721                         l->m_LayerType = _("Persistent");
1722 
1723                         wxString objmsg;
1724                         objmsg.Printf( wxT("Loaded GPX file %s with %ld items."), file_path.c_str(), nItems );
1725                         wxLogMessage( objmsg );
1726 
1727                         delete pSet;
1728                     }
1729                 }
1730             }
1731 
1732             cont = dir.GetNext( &filename );
1733         }
1734     }
1735     g_bLayersLoaded = true;
1736 
1737     return true;
1738 }
1739 
LoadChartDirArray(ArrayOfCDI & ChartDirArray)1740 bool MyConfig::LoadChartDirArray( ArrayOfCDI &ChartDirArray )
1741 {
1742     //    Chart Directories
1743     SetPath( _T ( "/ChartDirectories" ) );
1744     int iDirMax = GetNumberOfEntries();
1745     if( iDirMax ) {
1746         ChartDirArray.Empty();
1747         wxString str, val;
1748         long dummy;
1749         int nAdjustChartDirs = 0;
1750         int iDir = 0;
1751         bool bCont = pConfig->GetFirstEntry( str, dummy );
1752         while( bCont ) {
1753             pConfig->Read( str, &val );              // Get a Directory name
1754 
1755             wxString dirname( val );
1756             if( !dirname.IsEmpty() ) {
1757 
1758                 /*     Special case for first time run after Windows install with sample chart data...
1759                  We desire that the sample configuration file opencpn.ini should not contain any
1760                  installation dependencies, so...
1761                  Detect and update the sample [ChartDirectories] entries to point to the Shared Data directory
1762                  For instance, if the (sample) opencpn.ini file should contain shortcut coded entries like:
1763 
1764                  [ChartDirectories]
1765                  ChartDir1=SampleCharts\\MaptechRegion7
1766 
1767                  then this entry will be updated to be something like:
1768                  ChartDir1=c:\Program Files\opencpn\SampleCharts\\MaptechRegion7
1769 
1770                  */
1771                 if( dirname.Find( _T ( "SampleCharts" ) ) == 0 ) // only update entries starting with "SampleCharts"
1772                         {
1773                     nAdjustChartDirs++;
1774 
1775                     pConfig->DeleteEntry( str );
1776                     wxString new_dir = dirname.Mid( dirname.Find( _T ( "SampleCharts" ) ) );
1777                     new_dir.Prepend( g_Platform->GetSharedDataDir() );
1778                     dirname = new_dir;
1779                 }
1780 
1781                 ChartDirInfo cdi;
1782                 cdi.fullpath = dirname.BeforeFirst( '^' );
1783                 cdi.magic_number = dirname.AfterFirst( '^' );
1784 
1785                 ChartDirArray.Add( cdi );
1786                 iDir++;
1787             }
1788 
1789             bCont = pConfig->GetNextEntry( str, dummy );
1790         }
1791 
1792         if( nAdjustChartDirs ) pConfig->UpdateChartDirs( ChartDirArray );
1793     }
1794 
1795     return true;
1796 }
1797 
AddNewRoute(Route * pr)1798 void MyConfig::AddNewRoute( Route *pr )
1799 {
1800 //    if( pr->m_bIsInLayer )
1801 //        return true;
1802     if( !m_bSkipChangeSetUpdate )
1803         m_pNavObjectChangesSet->AddRoute( pr, "add" );
1804 }
1805 
UpdateRoute(Route * pr)1806 void MyConfig::UpdateRoute( Route *pr )
1807 {
1808 //    if( pr->m_bIsInLayer ) return true;
1809     if( !m_bSkipChangeSetUpdate )
1810             m_pNavObjectChangesSet->AddRoute( pr, "update" );
1811 }
1812 
DeleteConfigRoute(Route * pr)1813 void MyConfig::DeleteConfigRoute( Route *pr )
1814 {
1815 //    if( pr->m_bIsInLayer )
1816 //        return true;
1817     if( !m_bSkipChangeSetUpdate )
1818             m_pNavObjectChangesSet->AddRoute( pr, "delete" );
1819 }
1820 
AddNewTrack(Track * pt)1821 void MyConfig::AddNewTrack( Track *pt )
1822 {
1823     if( !pt->m_bIsInLayer && !m_bSkipChangeSetUpdate )
1824         m_pNavObjectChangesSet->AddTrack( pt, "add" );
1825 }
1826 
UpdateTrack(Track * pt)1827 void MyConfig::UpdateTrack( Track *pt )
1828 {
1829     if( pt->m_bIsInLayer && !m_bSkipChangeSetUpdate )
1830         m_pNavObjectChangesSet->AddTrack( pt, "update" );
1831 }
1832 
DeleteConfigTrack(Track * pt)1833 void MyConfig::DeleteConfigTrack( Track *pt )
1834 {
1835     if( !pt->m_bIsInLayer && !m_bSkipChangeSetUpdate )
1836         m_pNavObjectChangesSet->AddTrack( pt, "delete" );
1837 }
1838 
AddNewWayPoint(RoutePoint * pWP,int crm)1839 void MyConfig::AddNewWayPoint( RoutePoint *pWP, int crm )
1840 {
1841     if( !pWP->m_bIsInLayer && pWP->m_bIsolatedMark && !m_bSkipChangeSetUpdate )
1842         m_pNavObjectChangesSet->AddWP( pWP, "add" );
1843 }
1844 
UpdateWayPoint(RoutePoint * pWP)1845 void MyConfig::UpdateWayPoint( RoutePoint *pWP )
1846 {
1847     if( !pWP->m_bIsInLayer && !m_bSkipChangeSetUpdate )
1848         m_pNavObjectChangesSet->AddWP( pWP, "update" );
1849 }
1850 
DeleteWayPoint(RoutePoint * pWP)1851 void MyConfig::DeleteWayPoint( RoutePoint *pWP )
1852 {
1853     if( !pWP->m_bIsInLayer && !m_bSkipChangeSetUpdate )
1854         m_pNavObjectChangesSet->AddWP( pWP, "delete" );
1855 }
1856 
AddNewTrackPoint(TrackPoint * pWP,const wxString & parent_GUID)1857 void MyConfig::AddNewTrackPoint( TrackPoint *pWP, const wxString& parent_GUID )
1858 {
1859     if( !m_bSkipChangeSetUpdate )
1860         m_pNavObjectChangesSet->AddTrackPoint( pWP, "add", parent_GUID );
1861 }
1862 
UpdateChartDirs(ArrayOfCDI & dir_array)1863 bool MyConfig::UpdateChartDirs( ArrayOfCDI& dir_array )
1864 {
1865     wxString key, dir;
1866     wxString str_buf;
1867 
1868     SetPath( _T ( "/ChartDirectories" ) );
1869     int iDirMax = GetNumberOfEntries();
1870     if( iDirMax ) {
1871 
1872         long dummy;
1873 
1874         for( int i = 0; i < iDirMax; i++ ) {
1875             GetFirstEntry( key, dummy );
1876             DeleteEntry( key, false );
1877         }
1878     }
1879 
1880     iDirMax = dir_array.GetCount();
1881 
1882     for( int iDir = 0; iDir < iDirMax; iDir++ ) {
1883         ChartDirInfo cdi = dir_array[iDir];
1884 
1885         wxString dirn = cdi.fullpath;
1886         dirn.Append( _T("^") );
1887         dirn.Append( cdi.magic_number );
1888 
1889         str_buf.Printf( _T ( "ChartDir%d" ), iDir + 1 );
1890 
1891         Write( str_buf, dirn );
1892 
1893     }
1894 
1895     // Avoid nonsense log errors...
1896     #ifdef __OCPN__ANDROID__
1897     wxLogNull logNo;
1898     #endif
1899 
1900     Flush();
1901     return true;
1902 }
1903 
CreateConfigGroups(ChartGroupArray * pGroupArray)1904 void MyConfig::CreateConfigGroups( ChartGroupArray *pGroupArray )
1905 {
1906     if( !pGroupArray ) return;
1907 
1908     SetPath( _T ( "/Groups" ) );
1909     Write( _T ( "GroupCount" ), (int) pGroupArray->GetCount() );
1910 
1911     for( unsigned int i = 0; i < pGroupArray->GetCount(); i++ ) {
1912         ChartGroup *pGroup = pGroupArray->Item( i );
1913         wxString s;
1914         s.Printf( _T("Group%d"), i + 1 );
1915         s.Prepend( _T ( "/Groups/" ) );
1916         SetPath( s );
1917 
1918         Write( _T ( "GroupName" ), pGroup->m_group_name );
1919         Write( _T ( "GroupItemCount" ), (int) pGroup->m_element_array.size() );
1920 
1921         for( unsigned int j = 0; j < pGroup->m_element_array.size(); j++ ) {
1922             wxString sg;
1923             sg.Printf( _T("Group%d/Item%d"), i + 1, j );
1924             sg.Prepend( _T ( "/Groups/" ) );
1925             SetPath( sg );
1926             Write( _T ( "IncludeItem" ), pGroup->m_element_array[j]->m_element_name );
1927 
1928             wxString t;
1929             wxArrayString u = pGroup->m_element_array[j]->m_missing_name_array;
1930             if( u.GetCount() ) {
1931                 for( unsigned int k = 0; k < u.GetCount(); k++ ) {
1932                     t += u[k];
1933                     t += _T(";");
1934                 }
1935                 Write( _T ( "ExcludeItems" ), t );
1936             }
1937         }
1938     }
1939 }
1940 
DestroyConfigGroups(void)1941 void MyConfig::DestroyConfigGroups( void )
1942 {
1943     DeleteGroup( _T ( "/Groups" ) );                //zap
1944 }
1945 
LoadConfigGroups(ChartGroupArray * pGroupArray)1946 void MyConfig::LoadConfigGroups( ChartGroupArray *pGroupArray )
1947 {
1948     SetPath( _T ( "/Groups" ) );
1949     unsigned int group_count;
1950     Read( _T ( "GroupCount" ), (int *) &group_count, 0 );
1951 
1952     for( unsigned int i = 0; i < group_count; i++ ) {
1953         ChartGroup *pGroup = new ChartGroup;
1954         wxString s;
1955         s.Printf( _T("Group%d"), i + 1 );
1956         s.Prepend( _T ( "/Groups/" ) );
1957         SetPath( s );
1958 
1959         wxString t;
1960         Read( _T ( "GroupName" ), &t );
1961         pGroup->m_group_name = t;
1962 
1963         unsigned int item_count;
1964         Read( _T ( "GroupItemCount" ), (int *) &item_count );
1965         for( unsigned int j = 0; j < item_count; j++ ) {
1966             wxString sg;
1967             sg.Printf( _T("Group%d/Item%d"), i + 1, j );
1968             sg.Prepend( _T ( "/Groups/" ) );
1969             SetPath( sg );
1970 
1971             wxString v;
1972             Read( _T ( "IncludeItem" ), &v );
1973             ChartGroupElement *pelement = new ChartGroupElement{v};
1974             pGroup->m_element_array.emplace_back( pelement );
1975 
1976             wxString u;
1977             if( Read( _T ( "ExcludeItems" ), &u ) ) {
1978                 if( !u.IsEmpty() ) {
1979                     wxStringTokenizer tk( u, _T(";") );
1980                     while( tk.HasMoreTokens() ) {
1981                         wxString token = tk.GetNextToken();
1982                         pelement->m_missing_name_array.Add( token );
1983                     }
1984                 }
1985             }
1986         }
1987         pGroupArray->Add( pGroup );
1988     }
1989 
1990 }
1991 
LoadCanvasConfigs(bool bApplyAsTemplate)1992 void MyConfig::LoadCanvasConfigs( bool bApplyAsTemplate )
1993 {
1994     wxString s;
1995     canvasConfig *pcc;
1996 
1997     SetPath( _T ( "/Canvas" ) );
1998 
1999     //  If the canvas config has never been set/persisted, use the global settings
2000     if(!HasEntry( _T ( "CanvasConfig" ))){
2001 
2002         pcc = new canvasConfig(0);
2003         pcc->LoadFromLegacyConfig( this );
2004         g_canvasConfigArray.Add(pcc);
2005 
2006         return;
2007     }
2008 
2009     Read( _T ( "CanvasConfig" ), (int *)&g_canvasConfig, 0 );
2010 
2011     // Do not recreate canvasConfigs when applying config dynamically
2012     if(g_canvasConfigArray.GetCount() == 0){            // This is initial load from startup
2013         s.Printf( _T("/Canvas/CanvasConfig%d"), 1 );
2014         SetPath( s );
2015         canvasConfig *pcca = new canvasConfig(0);
2016         LoadConfigCanvas(pcca, bApplyAsTemplate);
2017         g_canvasConfigArray.Add(pcca);
2018 
2019         s.Printf( _T("/Canvas/CanvasConfig%d"), 2 );
2020         SetPath( s );
2021         pcca = new canvasConfig(1);
2022         LoadConfigCanvas(pcca, bApplyAsTemplate);
2023         g_canvasConfigArray.Add(pcca);
2024     } else {                                            // This is a dynamic (i.e. Template) load
2025         canvasConfig *pcca = g_canvasConfigArray[0];
2026         s.Printf( _T("/Canvas/CanvasConfig%d"), 1 );
2027         SetPath( s );
2028         LoadConfigCanvas(pcca, bApplyAsTemplate);
2029 
2030         if(g_canvasConfigArray.GetCount() > 1){
2031             canvasConfig *pcca = g_canvasConfigArray[1];
2032             s.Printf( _T("/Canvas/CanvasConfig%d"), 2 );
2033             SetPath( s );
2034             LoadConfigCanvas(pcca, bApplyAsTemplate);
2035         } else {
2036             s.Printf( _T("/Canvas/CanvasConfig%d"), 2 );
2037             SetPath( s );
2038             pcca = new canvasConfig(1);
2039             LoadConfigCanvas(pcca, bApplyAsTemplate);
2040             g_canvasConfigArray.Add(pcca);
2041         }
2042     }
2043 }
2044 
LoadConfigCanvas(canvasConfig * cConfig,bool bApplyAsTemplate)2045 void MyConfig::LoadConfigCanvas( canvasConfig *cConfig, bool bApplyAsTemplate )
2046 {
2047     wxString st;
2048     double st_lat, st_lon;
2049 
2050     if(!bApplyAsTemplate){
2051         //    Reasonable starting point
2052         cConfig->iLat = START_LAT;                   // display viewpoint
2053         cConfig->iLon = START_LON;
2054 
2055         if( Read( _T ( "canvasVPLatLon" ), &st ) ) {
2056             sscanf( st.mb_str( wxConvUTF8 ), "%lf,%lf", &st_lat, &st_lon );
2057 
2058             //    Sanity check the lat/lon...both have to be reasonable.
2059             if( fabs( st_lon ) < 360. ) {
2060                 while( st_lon < -180. )
2061                     st_lon += 360.;
2062 
2063                 while( st_lon > 180. )
2064                     st_lon -= 360.;
2065 
2066                 cConfig->iLon = st_lon;
2067             }
2068 
2069             if( fabs( st_lat ) < 90.0 )
2070                 cConfig->iLat = st_lat;
2071         }
2072 
2073         cConfig->iScale = .0003;        // decent initial value
2074         cConfig->iRotation = 0;
2075 
2076         double st_view_scale;
2077         if( Read( wxString( _T ( "canvasVPScale" ) ), &st ) ) {
2078             sscanf( st.mb_str( wxConvUTF8 ), "%lf", &st_view_scale );
2079             //    Sanity check the scale
2080             st_view_scale = fmax ( st_view_scale, .001/32 );
2081             st_view_scale = fmin ( st_view_scale, 4 );
2082             cConfig->iScale = st_view_scale;
2083         }
2084 
2085         double st_rotation;
2086         if( Read( wxString( _T ( "canvasVPRotation" ) ), &st ) ) {
2087             sscanf( st.mb_str( wxConvUTF8 ), "%lf", &st_rotation );
2088             //    Sanity check the rotation
2089             st_rotation = fmin ( st_rotation, 360 );
2090             st_rotation = fmax ( st_rotation, 0 );
2091             cConfig->iRotation = st_rotation * PI / 180.;
2092         }
2093 
2094         Read( _T ( "canvasInitialdBIndex" ), &cConfig->DBindex, 0 );
2095         Read( _T ( "canvasbFollow" ), &cConfig->bFollow, 0 );
2096 
2097         Read( _T ( "canvasCourseUp" ), &cConfig->bCourseUp, 0 );
2098         Read( _T ( "canvasHeadUp" ), &cConfig->bHeadUp, 0 );
2099         Read( _T ( "canvasLookahead" ), &cConfig->bLookahead, 0 );
2100     }
2101 
2102     Read( _T ( "ActiveChartGroup" ), &cConfig->GroupID, 0 );
2103 
2104     // Special check for group selection when applied as template
2105     if(cConfig->GroupID && bApplyAsTemplate){
2106         if( cConfig->GroupID > (int) g_pGroupArray->GetCount() )
2107             cConfig->GroupID = 0;
2108     }
2109 
2110     Read( _T ( "canvasShowTides" ), &cConfig->bShowTides, 0 );
2111     Read( _T ( "canvasShowCurrents" ), &cConfig->bShowCurrents, 0 );
2112 
2113 
2114     Read( _T ( "canvasQuilt" ), &cConfig->bQuilt, 1 );
2115     Read( _T ( "canvasShowGrid" ), &cConfig->bShowGrid, 0 );
2116     Read( _T ( "canvasShowOutlines" ), &cConfig->bShowOutlines, 0 );
2117     Read( _T ( "canvasShowDepthUnits" ), &cConfig->bShowDepthUnits, 0 );
2118 
2119     Read( _T ( "canvasShowAIS" ), &cConfig->bShowAIS, 1 );
2120     Read( _T ( "canvasAttenAIS" ), &cConfig->bAttenAIS, 0 );
2121 
2122     // ENC options
2123     Read( _T ( "canvasShowENCText" ), &cConfig->bShowENCText, 1 );
2124     Read( _T ( "canvasENCDisplayCategory" ), &cConfig->nENCDisplayCategory, STANDARD );
2125     Read( _T ( "canvasENCShowDepths" ), &cConfig->bShowENCDepths, 1 );
2126     Read( _T ( "canvasENCShowBuoyLabels" ), &cConfig->bShowENCBuoyLabels, 1 );
2127     Read( _T ( "canvasENCShowLightDescriptions" ), &cConfig->bShowENCLightDescriptions, 1 );
2128     Read( _T ( "canvasENCShowLights" ), &cConfig->bShowENCLights, 1 );
2129 
2130 
2131     int sx, sy;
2132     Read( _T ( "canvasSizeX" ), &sx, 0 );
2133     Read( _T ( "canvasSizeY" ), &sy, 0 );
2134     cConfig->canvasSize = wxSize(sx, sy);
2135 
2136 
2137 
2138 
2139 }
2140 
2141 
SaveCanvasConfigs()2142 void MyConfig::SaveCanvasConfigs( )
2143 {
2144     SetPath( _T ( "/Canvas" ) );
2145     Write( _T ( "CanvasConfig" ), (int )g_canvasConfig );
2146 
2147     wxString s;
2148     canvasConfig *pcc;
2149 
2150     switch( g_canvasConfig ){
2151 
2152         case 0:
2153         default:
2154 
2155             s.Printf( _T("/Canvas/CanvasConfig%d"), 1 );
2156             SetPath( s );
2157 
2158             if(g_canvasConfigArray.GetCount() > 0 ){
2159                 pcc = g_canvasConfigArray.Item(0);
2160                 if(pcc){
2161                     SaveConfigCanvas(pcc);
2162                 }
2163             }
2164             break;
2165 
2166         case 1:
2167 
2168             if(g_canvasConfigArray.GetCount() > 1 ){
2169 
2170                 s.Printf( _T("/Canvas/CanvasConfig%d"), 1 );
2171                 SetPath( s );
2172                 pcc = g_canvasConfigArray.Item(0);
2173                 if(pcc){
2174                     SaveConfigCanvas(pcc);
2175                 }
2176 
2177                 s.Printf( _T("/Canvas/CanvasConfig%d"), 2 );
2178                 SetPath( s );
2179                 pcc = g_canvasConfigArray.Item(1);
2180                 if(pcc){
2181                     SaveConfigCanvas(pcc);
2182                 }
2183             }
2184             break;
2185 
2186     }
2187 }
2188 
2189 
SaveConfigCanvas(canvasConfig * cConfig)2190 void MyConfig::SaveConfigCanvas( canvasConfig *cConfig )
2191 {
2192     wxString st1;
2193 
2194     if(cConfig->canvas){
2195         ViewPort vp = cConfig->canvas->GetVP();
2196 
2197         if( vp.IsValid() ) {
2198             st1.Printf( _T ( "%10.4f,%10.4f" ), vp.clat, vp.clon );
2199             Write( _T ( "canvasVPLatLon" ), st1 );
2200             st1.Printf( _T ( "%g" ), vp.view_scale_ppm );
2201             Write( _T ( "canvasVPScale" ), st1 );
2202             st1.Printf( _T ( "%i" ), ((int)(vp.rotation * 180 / PI)) % 360 );
2203             Write( _T ( "canvasVPRotation" ), st1 );
2204         }
2205 
2206         int restore_dbindex = 0;
2207         ChartStack *pcs = cConfig->canvas->GetpCurrentStack();
2208         if(pcs)
2209             restore_dbindex = pcs->GetCurrentEntrydbIndex();
2210         if( cConfig->canvas->GetQuiltMode())
2211             restore_dbindex = cConfig->canvas->GetQuiltReferenceChartIndex();
2212         Write( _T ( "canvasInitialdBIndex" ), restore_dbindex );
2213 
2214         Write( _T ( "canvasbFollow" ), cConfig->canvas->m_bFollow );
2215         Write( _T ( "ActiveChartGroup" ), cConfig->canvas->m_groupIndex );
2216 
2217         Write( _T ( "canvasToolbarConfig" ), cConfig->canvas->GetToolbarConfigString() );
2218         Write( _T ( "canvasShowToolbar" ), 0 );  //cConfig->canvas->GetToolbarEnable() );
2219 
2220         Write( _T ( "canvasQuilt" ), cConfig->canvas->GetQuiltMode() );
2221         Write( _T ( "canvasShowGrid" ), cConfig->canvas->GetShowGrid() );
2222         Write( _T ( "canvasShowOutlines" ), cConfig->canvas->GetShowOutlines() );
2223         Write( _T ( "canvasShowDepthUnits" ), cConfig->canvas->GetShowDepthUnits() );
2224 
2225         Write( _T ( "canvasShowAIS" ), cConfig->canvas->GetShowAIS() );
2226         Write( _T ( "canvasAttenAIS" ), cConfig->canvas->GetAttenAIS() );
2227 
2228         Write( _T ( "canvasShowTides" ), cConfig->canvas->GetbShowTide() );
2229         Write( _T ( "canvasShowCurrents" ), cConfig->canvas->GetbShowCurrent() );
2230 
2231         // ENC options
2232         Write( _T ( "canvasShowENCText" ), cConfig->canvas->GetShowENCText() );
2233         Write( _T ( "canvasENCDisplayCategory" ), cConfig->canvas->GetENCDisplayCategory() );
2234         Write( _T ( "canvasENCShowDepths" ), cConfig->canvas->GetShowENCDepth() );
2235         Write( _T ( "canvasENCShowBuoyLabels" ), cConfig->canvas->GetShowENCBuoyLabels() );
2236         Write( _T ( "canvasENCShowLightDescriptions" ), cConfig->canvas->GetShowENCLightDesc() );
2237         Write( _T ( "canvasENCShowLights" ), cConfig->canvas->GetShowENCLights() );
2238 
2239         Write( _T ( "canvasCourseUp" ), cConfig->canvas->GetUpMode() == COURSE_UP_MODE );
2240         Write( _T ( "canvasHeadUp" ), cConfig->canvas->GetUpMode() == HEAD_UP_MODE );
2241         Write( _T ( "canvasLookahead" ), cConfig->canvas->GetLookahead() );
2242 
2243 
2244         int width = cConfig->canvas->GetSize().x;
2245         //         if(cConfig->canvas->IsPrimaryCanvas()){
2246 //             width = wxMax(width, gFrame->GetClientSize().x / 10);
2247 //         }
2248 //         else{
2249 //             width = wxMin(width, gFrame->GetClientSize().x  * 9 / 10);
2250 //         }
2251 
2252         Write( _T ( "canvasSizeX" ), width );
2253         Write( _T ( "canvasSizeY" ), cConfig->canvas->GetSize().y );
2254 
2255     }
2256 }
2257 
2258 
2259 
UpdateSettings()2260 void MyConfig::UpdateSettings()
2261 {
2262     //  Temporarily suppress logging of trivial non-fatal wxLogSysError() messages provoked by Android security...
2263 #ifdef __OCPN__ANDROID__
2264     wxLogNull logNo;
2265 #endif
2266 
2267 
2268 //    Global options and settings
2269     SetPath( _T ( "/Settings" ) );
2270 
2271     Write( _T ( "LastAppliedTemplate" ), g_lastAppliedTemplateGUID );
2272     Write( _T ( "CompatOS" ), g_compatOS);
2273     Write( _T ( "CompatOsVersion" ), g_compatOsVersion);
2274     Write( _T ( "ConfigVersionString" ), g_config_version_string );
2275 #ifdef SYSTEM_SOUND_CMD
2276     if ( wxIsEmpty( g_CmdSoundString ) )
2277         g_CmdSoundString = wxString( SYSTEM_SOUND_CMD );
2278     Write( _T( "CmdSoundString" ), g_CmdSoundString );
2279 #endif /* SYSTEM_SOUND_CMD */
2280     Write( _T ( "NavMessageShown" ), n_NavMessageShown );
2281     Write( _T ( "InlandEcdis" ), g_bInlandEcdis );
2282 
2283     Write( _T ( "DarkDecorations"), g_bDarkDecorations );
2284 
2285     Write( _T ( "AndroidVersionCode" ), g_AndroidVersionCode );
2286 
2287     Write( _T ( "UIexpert" ), g_bUIexpert );
2288     Write( _T( "SpaceDropMark" ), g_bSpaceDropMark );
2289 //    Write( _T ( "UIStyle" ), g_StyleManager->GetStyleNextInvocation() );      //Not desired for O5 MUI
2290 
2291     Write( _T ( "ShowStatusBar" ), g_bShowStatusBar );
2292 #ifndef __WXOSX__
2293     Write( _T ( "ShowMenuBar" ), g_bShowMenuBar );
2294 #endif
2295     Write( _T ( "DefaultFontSize" ), g_default_font_size );
2296     Write( _T ( "DefaultFontFacename" ), g_default_font_facename );
2297 
2298     Write( _T ( "Fullscreen" ), g_bFullscreen );
2299     Write( _T ( "ShowCompassWindow" ), g_bShowCompassWin );
2300     Write( _T ( "SetSystemTime" ), s_bSetSystemTime );
2301     Write( _T ( "ShowGrid" ), g_bDisplayGrid );
2302     Write( _T ( "PlayShipsBells" ), g_bPlayShipsBells );
2303     Write( _T ( "SoundDeviceIndex" ), g_iSoundDeviceIndex );
2304     Write( _T ( "FullscreenToolbar" ), g_bFullscreenToolbar );
2305     Write( _T ( "TransparentToolbar" ), g_bTransparentToolbar );
2306     Write( _T ( "PermanentMOBIcon" ), g_bPermanentMOBIcon );
2307     Write( _T ( "ShowLayers" ), g_bShowLayers );
2308     Write( _T ( "AutoAnchorDrop" ), g_bAutoAnchorMark );
2309     Write( _T ( "ShowChartOutlines" ), g_bShowOutlines );
2310     Write( _T ( "ShowActiveRouteTotal" ), g_bShowRouteTotal );
2311     Write( _T ( "ShowActiveRouteHighway" ), g_bShowActiveRouteHighway );
2312     Write( _T ( "SDMMFormat" ), g_iSDMMFormat );
2313     Write( _T ( "MostRecentGPSUploadConnection" ), g_uploadConnection );
2314     Write( _T ( "ShowChartBar" ), g_bShowChartBar );
2315 
2316     Write( _T ( "GUIScaleFactor" ), g_GUIScaleFactor );
2317     Write( _T ( "ChartObjectScaleFactor" ), g_ChartScaleFactor );
2318     Write( _T ( "ShipScaleFactor" ), g_ShipScaleFactor );
2319     Write( _T ( "ENCSoundingScaleFactor" ), g_ENCSoundingScaleFactor );
2320 
2321     // Plugin catalog persistent values.
2322     Write( _T( "CatalogCustomURL"), g_catalog_custom_url);
2323     Write( _T( "CatalogChannel"), g_catalog_channel);
2324 
2325     Write( _T ( "FilterNMEA_Avg" ), g_bfilter_cogsog );
2326     Write( _T ( "FilterNMEA_Sec" ), g_COGFilterSec );
2327 
2328     Write( _T ( "TrackContinuous" ), g_btrackContinuous );
2329 
2330     Write( _T ( "ShowTrue" ), g_bShowTrue );
2331     Write( _T ( "ShowMag" ), g_bShowMag );
2332     Write( _T ( "UserMagVariation" ), wxString::Format( _T("%.2f"), g_UserVar ) );
2333 
2334     Write( _T ( "CM93DetailFactor" ), g_cm93_zoom_factor );
2335     Write( _T ( "CM93DetailZoomPosX" ), g_detailslider_dialog_x );
2336     Write( _T ( "CM93DetailZoomPosY" ), g_detailslider_dialog_y );
2337     Write( _T ( "ShowCM93DetailSlider" ), g_bShowDetailSlider );
2338 
2339     Write( _T ( "SkewToNorthUp" ), g_bskew_comp );
2340     Write( _T ( "OpenGL" ), g_bopengl );
2341     Write( _T ( "SoftwareGL" ), g_bSoftwareGL );
2342     Write( _T ( "ShowFPS" ), g_bShowFPS );
2343 
2344     Write( _T ( "ZoomDetailFactor" ), g_chart_zoom_modifier );
2345     Write( _T ( "ZoomDetailFactorVector" ), g_chart_zoom_modifier_vector );
2346 
2347     Write( _T ( "FogOnOverzoom" ), g_fog_overzoom );
2348     Write( _T ( "OverzoomVectorScale" ), g_oz_vector_scale );
2349     Write( _T ( "OverzoomEmphasisBase" ), g_overzoom_emphasis_base );
2350     Write( _T ( "PlusMinusZoomFactor" ), g_plus_minus_zoom_factor );
2351     Write( _T ( "ShowMUIZoomButtons" ), g_bShowMuiZoomButtons );
2352 
2353 #ifdef ocpnUSE_GL
2354     /* opengl options */
2355     Write( _T ( "UseAcceleratedPanning" ), g_GLOptions.m_bUseAcceleratedPanning );
2356 
2357     Write( _T ( "GPUTextureCompression" ), g_GLOptions.m_bTextureCompression);
2358     Write( _T ( "GPUTextureCompressionCaching" ), g_GLOptions.m_bTextureCompressionCaching);
2359     Write( _T ( "GPUTextureDimension" ), g_GLOptions.m_iTextureDimension );
2360     Write( _T ( "GPUTextureMemSize" ), g_GLOptions.m_iTextureMemorySize );
2361     Write( _T ( "PolygonSmoothing" ), g_GLOptions.m_GLPolygonSmoothing);
2362     Write( _T ( "LineSmoothing" ), g_GLOptions.m_GLLineSmoothing);
2363 #endif
2364     Write( _T ( "SmoothPanZoom" ), g_bsmoothpanzoom );
2365 
2366     Write( _T ( "CourseUpMode" ), g_bCourseUp );
2367     if (!g_bInlandEcdis ) Write( _T ( "LookAheadMode" ), g_bLookAhead );
2368     Write( _T ( "COGUPAvgSeconds" ), g_COGAvgSec );
2369     Write( _T ( "UseMagAPB" ), g_bMagneticAPB );
2370 
2371     Write( _T ( "OwnshipCOGPredictorMinutes" ), g_ownship_predictor_minutes );
2372     Write( _T ( "OwnshipCOGPredictorWidth" ), g_cog_predictor_width );
2373     Write( _T ( "OwnshipHDTPredictorMiles" ), g_ownship_HDTpredictor_miles );
2374     Write( _T ( "OwnShipIconType" ), g_OwnShipIconType );
2375     Write( _T ( "OwnShipLength" ), g_n_ownship_length_meters );
2376     Write( _T ( "OwnShipWidth" ), g_n_ownship_beam_meters );
2377     Write( _T ( "OwnShipGPSOffsetX" ), g_n_gps_antenna_offset_x );
2378     Write( _T ( "OwnShipGPSOffsetY" ), g_n_gps_antenna_offset_y );
2379     Write( _T ( "OwnShipMinSize" ), g_n_ownship_min_mm );
2380     Write( _T ( "OwnShipSogCogCalc" ), g_own_ship_sog_cog_calc );
2381     Write( _T ( "OwnShipSogCogCalcDampSec"), g_own_ship_sog_cog_calc_damp_sec );
2382 
2383     wxString racr;
2384  //   racr.Printf( _T ( "%g" ), g_n_arrival_circle_radius );
2385  //   Write( _T ( "RouteArrivalCircleRadius" ), racr );
2386     Write( _T ( "RouteArrivalCircleRadius" ), wxString::Format( _T("%.2f"), g_n_arrival_circle_radius ));
2387 
2388     Write( _T ( "ChartQuilting" ), g_bQuiltEnable );
2389 
2390     Write( _T ( "NMEALogWindowSizeX" ), NMEALogWindow::Get().GetSizeW());
2391     Write( _T ( "NMEALogWindowSizeY" ), NMEALogWindow::Get().GetSizeH());
2392     Write( _T ( "NMEALogWindowPosX" ), NMEALogWindow::Get().GetPosX());
2393     Write( _T ( "NMEALogWindowPosY" ), NMEALogWindow::Get().GetPosY());
2394 
2395     Write( _T ( "PreserveScaleOnX" ), g_bPreserveScaleOnX );
2396 
2397     Write( _T ( "StartWithTrackActive" ), g_bTrackCarryOver );
2398     Write( _T ( "AutomaticDailyTracks" ), g_bTrackDaily );
2399     Write( _T ( "TrackRotateAt" ), g_track_rotate_time );
2400     Write( _T ( "TrackRotateTimeType" ), g_track_rotate_time_type );
2401     Write( _T ( "HighlightTracks" ), g_bHighliteTracks );
2402 
2403     Write( _T ( "InitialStackIndex" ), g_restore_stackindex );
2404     Write( _T ( "InitialdBIndex" ), g_restore_dbindex );
2405 
2406     Write( _T( "NMEAAPBPrecision" ), g_NMEAAPBPrecision );
2407 
2408     Write( _T("TalkerIdText"), g_TalkerIdText );
2409     Write( _T("ShowTrackPointTime"), g_bShowTrackPointTime );
2410 
2411     Write( _T ( "AnchorWatch1GUID" ), g_AW1GUID );
2412     Write( _T ( "AnchorWatch2GUID" ), g_AW2GUID );
2413 
2414     Write( _T ( "ToolbarX" ), g_maintoolbar_x );
2415     Write( _T ( "ToolbarY" ), g_maintoolbar_y );
2416     //Write( _T ( "ToolbarOrient" ), g_maintoolbar_orient );
2417 
2418     Write( _T ( "iENCToolbarX" ), g_iENCToolbarPosX );
2419     Write( _T ( "iENCToolbarY" ), g_iENCToolbarPosY );
2420 
2421     if ( !g_bInlandEcdis ){
2422         Write( _T ( "GlobalToolbarConfig" ), g_toolbarConfig );
2423         Write( _T ( "DistanceFormat" ), g_iDistanceFormat );
2424         Write( _T ( "SpeedFormat" ), g_iSpeedFormat );
2425         Write( _T ( "ShowDepthUnits" ), g_bShowDepthUnits );
2426     }
2427     Write( _T ( "GPSIdent" ), g_GPS_Ident );
2428     Write( _T ( "UseGarminHostUpload" ), g_bGarminHostUpload );
2429 
2430     Write( _T ( "MobileTouch" ), g_btouch );
2431     Write( _T ( "ResponsiveGraphics" ), g_bresponsive );
2432     Write( _T ( "EnableRolloverBlock" ), g_bRollover );
2433 
2434     Write( _T ( "AutoHideToolbar" ), g_bAutoHideToolbar );
2435     Write( _T ( "AutoHideToolbarSecs" ), g_nAutoHideToolbar );
2436 
2437     Write( _T ( "DisplaySizeMM" ), g_config_display_size_mm );
2438     Write( _T ( "DisplaySizeManual" ), g_config_display_size_manual );
2439 
2440     Write( _T ( "SelectionRadiusMM" ), g_selection_radius_mm );
2441     Write( _T ( "SelectionRadiusTouchMM" ), g_selection_radius_touch_mm );
2442 
2443     wxString st0;
2444     st0.Printf( _T ( "%g" ), g_PlanSpeed );
2445     Write( _T ( "PlanSpeed" ), st0 );
2446 
2447     if(g_bLayersLoaded){
2448         wxString vis, invis, visnames, invisnames;
2449         LayerList::iterator it;
2450         int index = 0;
2451         for( it = ( *pLayerList ).begin(); it != ( *pLayerList ).end(); ++it, ++index ) {
2452             Layer *lay = (Layer *) ( *it );
2453             if( lay->IsVisibleOnChart() ) vis += ( lay->m_LayerName ) + _T(";");
2454             else
2455                 invis += ( lay->m_LayerName ) + _T(";");
2456 
2457             if( lay->HasVisibleNames() == wxCHK_CHECKED ) {
2458                 visnames += ( lay->m_LayerName) + _T(";");
2459             } else if( lay->HasVisibleNames() == wxCHK_UNCHECKED ) {
2460                 invisnames += ( lay->m_LayerName) + _T(";");
2461             }
2462         }
2463         Write( _T ( "VisibleLayers" ), vis );
2464         Write( _T ( "InvisibleLayers" ), invis );
2465         Write( _T ( "VisNameInLayers" ), visnames);
2466         Write( _T ( "InvisNameInLayers" ), invisnames);
2467     }
2468     Write( _T ( "Locale" ), g_locale );
2469     Write( _T ( "LocaleOverride" ), g_localeOverride );
2470 
2471     Write( _T ( "KeepNavobjBackups" ), g_navobjbackups );
2472     Write( _T ( "LegacyInputCOMPortFilterBehaviour" ), g_b_legacy_input_filter_behaviour );
2473     Write( _T( "AdvanceRouteWaypointOnArrivalOnly" ), g_bAdvanceRouteWaypointOnArrivalOnly);
2474 
2475     // LIVE ETA OPTION
2476     Write( _T( "LiveETA" ), g_bShowLiveETA);
2477     Write( _T( "DefaultBoatSpeed" ), g_defaultBoatSpeed);
2478 
2479 //    S57 Object Filter Settings
2480 
2481     SetPath( _T ( "/Settings/ObjectFilter" ) );
2482 
2483     if( ps52plib ) {
2484         for( unsigned int iPtr = 0; iPtr < ps52plib->pOBJLArray->GetCount(); iPtr++ ) {
2485             OBJLElement *pOLE = (OBJLElement *) ( ps52plib->pOBJLArray->Item( iPtr ) );
2486 
2487             wxString st1( _T ( "viz" ) );
2488             char name[7];
2489             strncpy( name, pOLE->OBJLName, 6 );
2490             name[6] = 0;
2491             st1.Append( wxString( name, wxConvUTF8 ) );
2492             Write( st1, pOLE->nViz );
2493         }
2494     }
2495 
2496 //    Global State
2497 
2498     SetPath( _T ( "/Settings/GlobalState" ) );
2499 
2500     wxString st1;
2501 
2502 //     if( cc1 ) {
2503 //         ViewPort vp = cc1->GetVP();
2504 //
2505 //         if( vp.IsValid() ) {
2506 //             st1.Printf( _T ( "%10.4f,%10.4f" ), vp.clat, vp.clon );
2507 //             Write( _T ( "VPLatLon" ), st1 );
2508 //             st1.Printf( _T ( "%g" ), vp.view_scale_ppm );
2509 //             Write( _T ( "VPScale" ), st1 );
2510 //             st1.Printf( _T ( "%i" ), ((int)(vp.rotation * 180 / PI)) % 360 );
2511 //             Write( _T ( "VPRotation" ), st1 );
2512 //         }
2513 //     }
2514 
2515     st1.Printf( _T ( "%10.4f, %10.4f" ), gLat, gLon );
2516     Write( _T ( "OwnShipLatLon" ), st1 );
2517 
2518     //    Various Options
2519     SetPath( _T ( "/Settings/GlobalState" ) );
2520     if ( !g_bInlandEcdis ) Write( _T ( "nColorScheme" ), (int) gFrame->GetColorScheme() );
2521 
2522     Write( _T ( "FrameWinX" ), g_nframewin_x );
2523     Write( _T ( "FrameWinY" ), g_nframewin_y );
2524     Write( _T ( "FrameWinPosX" ), g_nframewin_posx );
2525     Write( _T ( "FrameWinPosY" ), g_nframewin_posy );
2526     Write( _T ( "FrameMax" ), g_bframemax );
2527 
2528     Write( _T ( "ClientPosX" ), g_lastClientRectx );
2529     Write( _T ( "ClientPosY" ), g_lastClientRecty );
2530     Write( _T ( "ClientSzX" ), g_lastClientRectw );
2531     Write( _T ( "ClientSzY" ), g_lastClientRecth );
2532 
2533     Write( _T ( "S52_DEPTH_UNIT_SHOW" ), g_nDepthUnitDisplay );
2534 
2535     Write( _T( "RoutePropSizeX" ), g_route_prop_sx );
2536     Write( _T( "RoutePropSizeY" ), g_route_prop_sy );
2537     Write( _T( "RoutePropPosX" ), g_route_prop_x );
2538     Write( _T( "RoutePropPosY" ), g_route_prop_y );
2539 
2540     //    AIS
2541     SetPath( _T ( "/Settings/AIS" ) );
2542 
2543     Write( _T ( "bNoCPAMax" ), g_bCPAMax );
2544     Write( _T ( "NoCPAMaxNMi" ), g_CPAMax_NM );
2545     Write( _T ( "bCPAWarn" ), g_bCPAWarn );
2546     Write( _T ( "CPAWarnNMi" ), g_CPAWarn_NM );
2547     Write( _T ( "bTCPAMax" ), g_bTCPA_Max );
2548     Write( _T ( "TCPAMaxMinutes" ), g_TCPA_Max );
2549     Write( _T ( "bMarkLostTargets" ), g_bMarkLost );
2550     Write( _T ( "MarkLost_Minutes" ), g_MarkLost_Mins );
2551     Write( _T ( "bRemoveLostTargets" ), g_bRemoveLost );
2552     Write( _T ( "RemoveLost_Minutes" ), g_RemoveLost_Mins );
2553     Write( _T ( "bShowCOGArrows" ), g_bShowCOG );
2554     Write( _T ( "CogArrowMinutes" ), g_ShowCOG_Mins );
2555     Write( _T ( "bShowTargetTracks" ), g_bAISShowTracks );
2556     Write( _T ( "TargetTracksMinutes" ), g_AISShowTracks_Mins );
2557 
2558     Write( _T ( "bHideMooredTargets" ), g_bHideMoored );
2559     Write( _T ( "MooredTargetMaxSpeedKnots" ), g_ShowMoored_Kts );
2560 
2561     Write( _T ( "bAISAlertDialog" ), g_bAIS_CPA_Alert );
2562     Write( _T ( "bAISAlertAudio" ), g_bAIS_CPA_Alert_Audio );
2563     Write( _T ( "AISAlertAudioFile" ), g_sAIS_Alert_Sound_File );
2564     Write( _T ( "bAISAlertSuppressMoored" ), g_bAIS_CPA_Alert_Suppress_Moored );
2565     Write( _T ( "bShowAreaNotices" ), g_bShowAreaNotices );
2566     Write( _T ( "bDrawAISSize" ), g_bDrawAISSize );
2567     Write( _T ( "bDrawAISRealtime" ), g_bDrawAISRealtime );
2568     Write( _T ( "AISRealtimeMinSpeedKnots" ), g_AIS_RealtPred_Kts );
2569     Write( _T ( "bShowAISName" ), g_bShowAISName );
2570     Write( _T ( "ShowAISTargetNameScale" ), g_Show_Target_Name_Scale );
2571     Write( _T ( "bWplIsAprsPositionReport" ), g_bWplIsAprsPosition );
2572     Write( _T ( "AISCOGPredictorWidth" ), g_ais_cog_predictor_width );
2573     Write( _T ( "bShowScaledTargets" ), g_bAllowShowScaled );
2574     Write( _T ( "AISScaledNumber" ), g_ShowScaled_Num );
2575     Write( _T ( "AISScaledNumberWeightSOG" ), g_ScaledNumWeightSOG );
2576     Write( _T ( "AISScaledNumberWeightCPA" ), g_ScaledNumWeightCPA );
2577     Write( _T ( "AISScaledNumberWeightTCPA" ), g_ScaledNumWeightTCPA );
2578     Write( _T ( "AISScaledNumberWeightRange" ), g_ScaledNumWeightRange );
2579     Write( _T ( "AISScaledNumberWeightSizeOfTarget" ), g_ScaledNumWeightSizeOfT );
2580     Write( _T ( "AISScaledSizeMinimal" ), g_ScaledSizeMinimal );
2581     Write( _T ( "AISShowScaled"), g_bShowScaled);
2582 
2583     Write( _T ( "AlertDialogSizeX" ), g_ais_alert_dialog_sx );
2584     Write( _T ( "AlertDialogSizeY" ), g_ais_alert_dialog_sy );
2585     Write( _T ( "AlertDialogPosX" ), g_ais_alert_dialog_x );
2586     Write( _T ( "AlertDialogPosY" ), g_ais_alert_dialog_y );
2587     Write( _T ( "QueryDialogPosX" ), g_ais_query_dialog_x );
2588     Write( _T ( "QueryDialogPosY" ), g_ais_query_dialog_y );
2589     Write( _T ( "AISTargetListPerspective" ), g_AisTargetList_perspective );
2590     Write( _T ( "AISTargetListRange" ), g_AisTargetList_range );
2591     Write( _T ( "AISTargetListSortColumn" ), g_AisTargetList_sortColumn );
2592     Write( _T ( "bAISTargetListSortReverse" ), g_bAisTargetList_sortReverse );
2593     Write( _T ( "AISTargetListColumnSpec" ), g_AisTargetList_column_spec );
2594     Write( _T ("AISTargetListColumnOrder"), g_AisTargetList_column_order);
2595 
2596     Write( _T ( "S57QueryDialogSizeX" ), g_S57_dialog_sx );
2597     Write( _T ( "S57QueryDialogSizeY" ), g_S57_dialog_sy );
2598     Write( _T ( "S57QueryExtraDialogSizeX" ), g_S57_extradialog_sx );
2599     Write( _T ( "S57QueryExtraDialogSizeY" ), g_S57_extradialog_sy );
2600 
2601     Write( _T ( "bAISRolloverShowClass" ), g_bAISRolloverShowClass );
2602     Write( _T ( "bAISRolloverShowCOG" ), g_bAISRolloverShowCOG );
2603     Write( _T ( "bAISRolloverShowCPA" ), g_bAISRolloverShowCPA );
2604 
2605     Write( _T ( "bAISAlertAckTimeout" ), g_bAIS_ACK_Timeout );
2606     Write( _T ( "AlertAckTimeoutMinutes" ), g_AckTimeout_Mins );
2607 
2608     SetPath( _T ( "/Settings/GlobalState" ) );
2609     if( ps52plib ) {
2610         Write( _T ( "bShowS57Text" ), ps52plib->GetShowS57Text() );
2611         Write( _T ( "bShowS57ImportantTextOnly" ), ps52plib->GetShowS57ImportantTextOnly() );
2612         if ( !g_bInlandEcdis ) Write( _T ( "nDisplayCategory" ), (long) ps52plib->GetDisplayCategory() );
2613         Write( _T ( "nSymbolStyle" ), (int) ps52plib->m_nSymbolStyle );
2614         Write( _T ( "nBoundaryStyle" ), (int) ps52plib->m_nBoundaryStyle );
2615 
2616         Write( _T ( "bShowSoundg" ), ps52plib->m_bShowSoundg );
2617         Write( _T ( "bShowMeta" ), ps52plib->m_bShowMeta );
2618         Write( _T ( "bUseSCAMIN" ), ps52plib->m_bUseSCAMIN );
2619         Write( _T ( "bShowAtonText" ), ps52plib->m_bShowAtonText );
2620         Write( _T ( "bShowLightDescription" ), ps52plib->m_bShowLdisText );
2621         Write( _T ( "bExtendLightSectors" ), ps52plib->m_bExtendLightSectors );
2622         Write( _T ( "bDeClutterText" ), ps52plib->m_bDeClutterText );
2623         Write( _T ( "bShowNationalText" ), ps52plib->m_bShowNationalTexts );
2624 
2625         Write( _T ( "S52_MAR_SAFETY_CONTOUR" ), S52_getMarinerParam( S52_MAR_SAFETY_CONTOUR ) );
2626         Write( _T ( "S52_MAR_SHALLOW_CONTOUR" ), S52_getMarinerParam( S52_MAR_SHALLOW_CONTOUR ) );
2627         Write( _T ( "S52_MAR_DEEP_CONTOUR" ), S52_getMarinerParam( S52_MAR_DEEP_CONTOUR ) );
2628         Write( _T ( "S52_MAR_TWO_SHADES" ), S52_getMarinerParam( S52_MAR_TWO_SHADES ) );
2629         Write( _T ( "S52_DEPTH_UNIT_SHOW" ), ps52plib->m_nDepthUnitDisplay );
2630         Write( _T ( "ENCSoundingScaleFactor" ), g_ENCSoundingScaleFactor );
2631     }
2632     SetPath( _T ( "/Directories" ) );
2633     Write( _T ( "S57DataLocation" ), _T("") );
2634 //    Write( _T ( "SENCFileLocation" ), _T("") );
2635 
2636     SetPath( _T ( "/Directories" ) );
2637     Write( _T ( "InitChartDir" ), *pInit_Chart_Dir );
2638     Write( _T ( "GPXIODir" ), g_gpx_path );
2639     Write( _T ( "TCDataDir" ), g_TCData_Dir );
2640     Write( _T ( "BasemapDir" ), g_Platform->NormalizePath(gWorldMapLocation) );
2641     Write( _T ( "pluginInstallDir" ), g_Platform->NormalizePath(g_winPluginDir) );
2642 
2643     SetPath( _T ( "/Settings/NMEADataSource" ) );
2644     wxString connectionconfigs;
2645     for (size_t i = 0; i < g_pConnectionParams->Count(); i++)
2646     {
2647         if (i > 0)
2648             connectionconfigs.Append(_T("|"));
2649         connectionconfigs.Append(g_pConnectionParams->Item(i)->Serialize());
2650     }
2651     Write ( _T ( "DataConnections" ), connectionconfigs );
2652 
2653     //    Fonts
2654 
2655     //  Store the persistent Auxiliary Font descriptor Keys
2656     SetPath( _T ( "/Settings/AuxFontKeys" ) );
2657 
2658     wxArrayString keyArray = FontMgr::Get().GetAuxKeyArray();
2659     for(unsigned int i=0 ; i <  keyArray.GetCount() ; i++){
2660         wxString key;
2661         key.Printf(_T("Key%i"), i);
2662         wxString keyval = keyArray[i];
2663         Write( key, keyval );
2664     }
2665 
2666     wxString font_path;
2667 #ifdef __WXX11__
2668     font_path = ( _T ( "/Settings/X11Fonts" ) );
2669 #endif
2670 
2671 #ifdef __WXGTK__
2672     font_path = ( _T ( "/Settings/GTKFonts" ) );
2673 #endif
2674 
2675 #ifdef __WXMSW__
2676     font_path = ( _T ( "/Settings/MSWFonts" ) );
2677 #endif
2678 
2679 #ifdef __WXMAC__
2680     font_path = ( _T ( "/Settings/MacFonts" ) );
2681 #endif
2682 
2683 #ifdef __WXQT__
2684     font_path = ( _T ( "/Settings/QTFonts" ) );
2685 #endif
2686 
2687     DeleteGroup(font_path);
2688 
2689     SetPath( font_path );
2690 
2691     int nFonts = FontMgr::Get().GetNumFonts();
2692 
2693     for( int i = 0; i < nFonts; i++ ) {
2694         wxString cfstring(FontMgr::Get().GetConfigString(i));
2695         wxString valstring = FontMgr::Get().GetFullConfigDesc( i );
2696         Write( cfstring, valstring );
2697     }
2698 
2699     //  Tide/Current Data Sources
2700     DeleteGroup( _T ( "/TideCurrentDataSources" ) );
2701     SetPath( _T ( "/TideCurrentDataSources" ) );
2702     unsigned int iDirMax = TideCurrentDataSet.Count();
2703     for( unsigned int id = 0 ; id < iDirMax ; id++ ) {
2704         wxString key;
2705         key.Printf(_T("tcds%d"), id);
2706         Write( key, TideCurrentDataSet[id] );
2707     }
2708 
2709     SetPath( _T ( "/Settings/Others" ) );
2710 
2711     // Radar rings
2712     Write( _T ( "ShowRadarRings" ), (bool)(g_iNavAidRadarRingsNumberVisible > 0) );  //3.0.0 config support
2713     Write( _T ( "RadarRingsNumberVisible" ), g_iNavAidRadarRingsNumberVisible );
2714     Write( _T ( "RadarRingsStep" ), g_fNavAidRadarRingsStep );
2715     Write( _T ( "RadarRingsStepUnits" ), g_pNavAidRadarRingsStepUnits );
2716     Write( _T ( "RadarRingsColour" ), g_colourOwnshipRangeRingsColour.GetAsString( wxC2S_HTML_SYNTAX ) );
2717     Write( _T( "WaypointUseScaMin" ), g_bUseWptScaMin );
2718     Write( _T( "WaypointScaMinValue" ), g_iWpt_ScaMin );
2719     Write( _T( "WaypointUseScaMinOverrule" ), g_bOverruleScaMin );
2720     Write( _T("WaypointsShowName"), g_bShowWptName );
2721 
2722     // Waypoint Radar rings
2723     Write( _T ( "WaypointRangeRingsNumber" ), g_iWaypointRangeRingsNumber );
2724     Write( _T ( "WaypointRangeRingsStep" ), g_fWaypointRangeRingsStep );
2725     Write( _T ( "WaypointRangeRingsStepUnits" ), g_iWaypointRangeRingsStepUnits );
2726     Write( _T ( "WaypointRangeRingsColour" ), g_colourWaypointRangeRingsColour.GetAsString( wxC2S_HTML_SYNTAX ) );
2727 
2728     Write( _T ( "ConfirmObjectDeletion" ), g_bConfirmObjectDelete );
2729 
2730     // Waypoint dragging with mouse; toh, 2009.02.24
2731     Write( _T ( "WaypointPreventDragging" ), g_bWayPointPreventDragging );
2732 
2733     Write( _T ( "EnableZoomToCursor" ), g_bEnableZoomToCursor );
2734 
2735     Write( _T ( "TrackIntervalSeconds" ), g_TrackIntervalSeconds );
2736     Write( _T ( "TrackDeltaDistance" ), g_TrackDeltaDistance );
2737     Write( _T ( "TrackPrecision" ), g_nTrackPrecision );
2738 
2739     Write( _T ( "RouteLineWidth" ), g_route_line_width );
2740     Write( _T ( "TrackLineWidth" ), g_track_line_width );
2741     Write( _T ( "TrackLineColour" ), g_colourTrackLineColour.GetAsString( wxC2S_HTML_SYNTAX ) );
2742     Write( _T ( "DefaultWPIcon" ), g_default_wp_icon );
2743     Write( _T ( "DefaultRPIcon" ), g_default_routepoint_icon );
2744 
2745     DeleteGroup(_T ( "/MMSIProperties" ));
2746     SetPath( _T ( "/MMSIProperties" ) );
2747     for(unsigned int i=0 ; i < g_MMSI_Props_Array.GetCount() ; i++){
2748         wxString p;
2749         p.Printf(_T("Props%d"), i);
2750         Write( p, g_MMSI_Props_Array[i]->Serialize() );
2751     }
2752 
2753     SaveCanvasConfigs();
2754 
2755     Flush();
2756 }
2757 
UpdateNavObj(bool bRecreate)2758 void MyConfig::UpdateNavObj( bool bRecreate )
2759 {
2760 
2761 //   Create the NavObjectCollection, and save to specified file
2762     NavObjectCollection1 *pNavObjectSet = new NavObjectCollection1();
2763 
2764     pNavObjectSet->CreateAllGPXObjects();
2765     pNavObjectSet->SaveFile( m_sNavObjSetFile );
2766 
2767     delete pNavObjectSet;
2768 
2769     if( ::wxFileExists( m_sNavObjSetChangesFile ) ){
2770         wxLogNull logNo;                // avoid silly log error message.
2771         wxRemoveFile( m_sNavObjSetChangesFile );
2772     }
2773 
2774     if(bRecreate){
2775         delete m_pNavObjectChangesSet;
2776         m_pNavObjectChangesSet = new NavObjectChanges(m_sNavObjSetChangesFile);
2777     }
2778 
2779 }
2780 
exportFileName(wxWindow * parent,const wxString suggestedName)2781 static wxFileName exportFileName(wxWindow* parent, const wxString suggestedName )
2782 {
2783     wxFileName ret;
2784     wxString path;
2785     wxString validName{suggestedName};
2786     // replace common date characters invalid in filename
2787     // MS-DOS file systems have many more
2788     validName.Replace(_T("/"), _T("-"));
2789     validName.Replace(_T(":"), _T("_"));
2790     int response = g_Platform->DoFileSelectorDialog( parent, &path,
2791                                                      _( "Export GPX file" ),
2792                                                      g_gpx_path,
2793                                                      validName,
2794                                                      wxT ( "*.gpx" )
2795     );
2796 
2797     if( response == wxID_OK ) {
2798         wxFileName fn(path);
2799         g_gpx_path = fn.GetPath();
2800         fn.SetExt(_T("gpx"));
2801 
2802 #ifndef __WXMAC__
2803         if( wxFileExists( fn.GetFullPath() ) ) {
2804             int answer = OCPNMessageBox( NULL, _("Overwrite existing file?"), _T("Confirm"),
2805                     wxICON_QUESTION | wxYES_NO | wxCANCEL );
2806             if( answer != wxID_YES )
2807                 return ret;
2808         }
2809 #endif
2810         ret = fn;
2811     }
2812     return ret;
2813 }
2814 
IsChangesFileDirty()2815 bool MyConfig::IsChangesFileDirty()
2816 {
2817     if(m_pNavObjectChangesSet){
2818         return m_pNavObjectChangesSet->m_bdirty;
2819     }
2820     else{
2821         return true;
2822     }
2823 }
2824 
2825 
ExportGPXRoutes(wxWindow * parent,RouteList * pRoutes,const wxString suggestedName)2826 bool ExportGPXRoutes( wxWindow* parent, RouteList *pRoutes, const wxString suggestedName )
2827 {
2828     wxFileName fn = exportFileName(parent, suggestedName);
2829     if (fn.IsOk()) {
2830         NavObjectCollection1 *pgpx = new NavObjectCollection1;
2831         pgpx->AddGPXRoutesList( pRoutes );
2832 
2833 #ifdef __OCPN__ANDROID__
2834         wxString fns = androidGetCacheDir() + wxFileName::GetPathSeparator() + fn.GetFullName();
2835         pgpx->SaveFile(fns);
2836         AndroidSecureCopyFile(fns, fn.GetFullPath());
2837 #else
2838         pgpx->SaveFile(fn.GetFullPath());
2839 
2840 #endif
2841 
2842         delete pgpx;
2843 
2844         return true;
2845     }
2846     return false;
2847 }
2848 
ExportGPXTracks(wxWindow * parent,TrackList * pTracks,const wxString suggestedName)2849 bool ExportGPXTracks( wxWindow* parent, TrackList *pTracks, const wxString suggestedName )
2850 {
2851     wxFileName fn = exportFileName(parent, suggestedName);
2852     if (fn.IsOk()) {
2853         NavObjectCollection1 *pgpx = new NavObjectCollection1;
2854         pgpx->AddGPXTracksList( pTracks );
2855 #ifdef __OCPN__ANDROID__
2856         wxString fns = androidGetCacheDir() + wxFileName::GetPathSeparator() + fn.GetFullName();
2857         pgpx->SaveFile(fns);
2858         AndroidSecureCopyFile(fns, fn.GetFullPath());
2859 #else
2860         pgpx->SaveFile(fn.GetFullPath());
2861 #endif
2862         delete pgpx;
2863 
2864         return true;
2865     }
2866     return false;
2867 }
2868 
ExportGPXWaypoints(wxWindow * parent,RoutePointList * pRoutePoints,const wxString suggestedName)2869 bool ExportGPXWaypoints( wxWindow* parent, RoutePointList *pRoutePoints, const wxString suggestedName )
2870 {
2871     wxFileName fn = exportFileName(parent, suggestedName);
2872     if (fn.IsOk()) {
2873         NavObjectCollection1 *pgpx = new NavObjectCollection1;
2874         pgpx->AddGPXPointsList( pRoutePoints );
2875 
2876 #ifdef __OCPN__ANDROID__
2877         wxString fns = androidGetCacheDir() + wxFileName::GetPathSeparator() + fn.GetFullName();
2878         pgpx->SaveFile(fns);
2879         AndroidSecureCopyFile(fns, fn.GetFullPath());
2880 #else
2881         pgpx->SaveFile(fn.GetFullPath());
2882 #endif
2883 
2884         delete pgpx;
2885 
2886         return true;
2887     }
2888     return false;
2889 }
2890 
ExportGPX(wxWindow * parent,bool bviz_only,bool blayer)2891 void ExportGPX( wxWindow* parent, bool bviz_only, bool blayer )
2892 {
2893     wxFileName fn = exportFileName(parent, _T("userobjects.gpx"));
2894     if (fn.IsOk()) {
2895         ::wxBeginBusyCursor();
2896 
2897         NavObjectCollection1 *pgpx = new NavObjectCollection1;
2898 
2899         wxGenericProgressDialog *pprog = nullptr;
2900         int count = pWayPointMan->GetWaypointList()->GetCount();
2901         int progStep = count / 32;
2902         if( count > 200) {
2903             pprog = new wxGenericProgressDialog( _("Export GPX file"), _T("0/0"), count, NULL,
2904                                           wxPD_APP_MODAL | wxPD_SMOOTH |
2905                                           wxPD_ELAPSED_TIME | wxPD_ESTIMATED_TIME | wxPD_REMAINING_TIME );
2906             pprog->SetSize( 400, wxDefaultCoord );
2907             pprog->Centre();
2908         }
2909 
2910         //WPTs
2911         int ic = 1;
2912 
2913         wxRoutePointListNode *node = pWayPointMan->GetWaypointList()->GetFirst();
2914         RoutePoint *pr;
2915         while( node ) {
2916             if( pprog && !(ic % progStep) ) {
2917                 wxString msg;
2918                 msg.Printf(_T("%d/%d"), ic, count);
2919                 pprog->Update( ic, msg );
2920             }
2921             ic++;
2922 
2923             pr = node->GetData();
2924 
2925             bool b_add = true;
2926 
2927             if( bviz_only && !pr->m_bIsVisible )
2928                 b_add = false;
2929 
2930             if( pr->m_bIsInLayer && !blayer )
2931                 b_add = false;
2932             if( b_add) {
2933                 if( pr->m_bKeepXRoute || !WptIsInRouteList( pr ) )
2934                     pgpx->AddGPXWaypoint( pr);
2935             }
2936 
2937             node = node->GetNext();
2938         }
2939         //RTEs and TRKs
2940         wxRouteListNode *node1 = pRouteList->GetFirst();
2941         while( node1 ) {
2942             Route *pRoute = node1->GetData();
2943 
2944             bool b_add = true;
2945 
2946             if( bviz_only && !pRoute->IsVisible() )
2947                 b_add = false;
2948 
2949             if(  pRoute->m_bIsInLayer && !blayer )
2950                 b_add = false;
2951 
2952             if( b_add )
2953                 pgpx->AddGPXRoute( pRoute );
2954 
2955             node1 = node1->GetNext();
2956         }
2957 
2958         wxTrackListNode *node2 = pTrackList->GetFirst();
2959         while( node2 ) {
2960             Track *pTrack = node2->GetData();
2961 
2962             bool b_add = true;
2963 
2964             if( bviz_only && !pTrack->IsVisible() )
2965                 b_add = false;
2966 
2967             if(  pTrack->m_bIsInLayer && !blayer )
2968                 b_add = false;
2969 
2970             if( b_add )
2971                     pgpx->AddGPXTrack( pTrack );
2972             node2 = node2->GetNext();
2973         }
2974 
2975 
2976         // Android 5+ requires special handling to support native app file writes to SDCard
2977         // We need to use a two step copy process using a guaranteed accessible location for the first step.
2978 #ifdef __OCPN__ANDROID__
2979         wxString fns = androidGetCacheDir() + wxFileName::GetPathSeparator() + fn.GetFullName();
2980         pgpx->SaveFile(fns);
2981         AndroidSecureCopyFile(fns, fn.GetFullPath());
2982 #else
2983         pgpx->SaveFile( fn.GetFullPath() );
2984 #endif
2985 
2986         delete pgpx;
2987         ::wxEndBusyCursor();
2988 
2989         delete pprog;
2990 
2991     }
2992 }
2993 
UI_ImportGPX(wxWindow * parent,bool islayer,wxString dirpath,bool isdirectory,bool isPersistent)2994 void UI_ImportGPX( wxWindow* parent, bool islayer, wxString dirpath, bool isdirectory, bool isPersistent )
2995 {
2996     int response = wxID_CANCEL;
2997     wxArrayString file_array;
2998     Layer *l = NULL;
2999 
3000     if( !islayer || dirpath.IsSameAs( _T("") ) ) {
3001 
3002         //  Platform DoFileSelectorDialog method does not properly handle multiple selections
3003         //  So use native method if not Android, which means Android gets single selection only.
3004 #ifndef __OCPN__ANDROID__
3005         wxFileDialog *popenDialog = new wxFileDialog( NULL, _( "Import GPX file" ), g_gpx_path, wxT ( "" ),
3006                 wxT ( "GPX files (*.gpx)|*.gpx|All files (*.*)|*.*" ),
3007                 wxFD_OPEN | wxFD_MULTIPLE );
3008 
3009         if(g_bresponsive && parent)
3010             popenDialog = g_Platform->AdjustFileDialogFont(parent, popenDialog);
3011 
3012         popenDialog->Centre();
3013 
3014         #ifdef __WXOSX__
3015         if(parent)
3016             parent->HideWithEffect(wxSHOW_EFFECT_BLEND );
3017         #endif
3018 
3019         response = popenDialog->ShowModal();
3020 
3021         #ifdef __WXOSX__
3022         if(parent)
3023             parent->ShowWithEffect(wxSHOW_EFFECT_BLEND );
3024         #endif
3025 
3026         if( response == wxID_OK ) {
3027             popenDialog->GetPaths( file_array );
3028 
3029             //    Record the currently selected directory for later use
3030             if( file_array.GetCount() ) {
3031                 wxFileName fn( file_array[0] );
3032                 g_gpx_path = fn.GetPath();
3033             }
3034         }
3035         delete popenDialog;
3036 #else
3037         wxString path;
3038         response = g_Platform->DoFileSelectorDialog( NULL, &path,
3039                                                          _( "Import GPX file" ),
3040                                                          g_gpx_path,
3041                                                          _T(""),
3042                                                          wxT ( "*.gpx" )
3043                                                          );
3044 
3045         file_array.Add(path);
3046         wxFileName fn( path );
3047         g_gpx_path = fn.GetPath();
3048 
3049 #endif
3050 
3051     } else {
3052         if( isdirectory ) {
3053             if( wxDir::GetAllFiles( dirpath, &file_array, wxT("*.gpx") ) )
3054                 response = wxID_OK;
3055         } else {
3056             file_array.Add( dirpath );
3057             response = wxID_OK;
3058         }
3059     }
3060 
3061     if( response == wxID_OK ) {
3062 
3063         if( islayer ) {
3064             l = new Layer();
3065             l->m_LayerID = ++g_LayerIdx;
3066             l->m_LayerFileName = file_array[0];
3067             if( file_array.GetCount() <= 1 ) wxFileName::SplitPath( file_array[0], NULL, NULL,
3068                     &( l->m_LayerName ), NULL, NULL );
3069             else {
3070                 if( dirpath.IsSameAs( _T("") ) ) wxFileName::SplitPath( g_gpx_path, NULL, NULL,
3071                         &( l->m_LayerName ), NULL, NULL );
3072                 else
3073                     wxFileName::SplitPath( dirpath, NULL, NULL, &( l->m_LayerName ), NULL, NULL );
3074             }
3075 
3076             bool bLayerViz = g_bShowLayers;
3077             if( g_VisibleLayers.Contains( l->m_LayerName ) )
3078                 bLayerViz = true;
3079             if( g_InvisibleLayers.Contains( l->m_LayerName ) )
3080                 bLayerViz = false;
3081             l->m_bIsVisibleOnChart = bLayerViz;
3082 
3083             // Default for new layers is "Names visible"
3084             l->m_bHasVisibleNames = wxCHK_CHECKED;
3085 
3086             wxString laymsg;
3087             laymsg.Printf( wxT("New layer %d: %s"), l->m_LayerID, l->m_LayerName.c_str() );
3088             wxLogMessage( laymsg );
3089 
3090             pLayerList->Insert( l );
3091         }
3092 
3093         for( unsigned int i = 0; i < file_array.GetCount(); i++ ) {
3094             wxString path = file_array[i];
3095 
3096             if( ::wxFileExists( path ) ) {
3097 
3098                 NavObjectCollection1 *pSet = new NavObjectCollection1;
3099                 pSet->load_file(path.fn_str());
3100 
3101                 if(islayer){
3102                     l->m_NoOfItems = pSet->LoadAllGPXObjectsAsLayer(l->m_LayerID, l->m_bIsVisibleOnChart, l->m_bHasVisibleNames);
3103                     l->m_LayerType = isPersistent ? _("Persistent") : _("Temporary") ;
3104 
3105                     if(isPersistent)
3106                     {
3107                         // If this is a persistent layer also copy the file to config file dir /layers
3108                         wxString destf, f, name, ext;
3109                         f = l->m_LayerFileName;
3110                         wxFileName::SplitPath(f, NULL , NULL, &name, &ext);
3111                         destf = g_Platform->GetPrivateDataDir();
3112                         appendOSDirSlash(&destf);
3113                         destf.Append(_T("layers"));
3114                         appendOSDirSlash(&destf);
3115                         if (!wxDirExists(destf))
3116                         {
3117                             if( !wxMkdir(destf, wxS_DIR_DEFAULT) )
3118                                 wxLogMessage( _T("Error creating layer directory") );
3119                         }
3120 
3121                         destf << name << _T(".") << ext;
3122                         wxString msg;
3123                         if( wxCopyFile(f, destf, true) )
3124                             msg.Printf(_T("File: %s.%s also added to persistent layers"), name, ext);
3125                         else
3126                             msg.Printf(_T("Failed adding %s.%s to persistent layers"), name, ext);
3127                         wxLogMessage(msg);
3128                     }
3129                 }
3130                 else {
3131                     int wpt_dups;
3132                     pSet->LoadAllGPXObjects( !pSet->IsOpenCPN(), wpt_dups ); // Import with full visibility of names and objects
3133                     if(wpt_dups > 0) {
3134                         OCPNMessageBox(parent, wxString::Format(_T("%d ")+_("duplicate waypoints detected during import and ignored."), wpt_dups), _("OpenCPN Info"), wxICON_INFORMATION|wxOK, 10);
3135                     }
3136                 }
3137                 delete pSet;
3138             }
3139         }
3140     }
3141 }
3142 
3143 //-------------------------------------------------------------------------
3144 //           Static Routine Switch to Inland Ecdis Mode
3145 //-------------------------------------------------------------------------
SwitchInlandEcdisMode(bool Switch)3146 void SwitchInlandEcdisMode( bool Switch )
3147 {
3148     if ( Switch ){
3149         wxLogMessage( _T("Switch InlandEcdis mode On") );
3150         LoadS57();
3151         //Overule some sewttings to comply with InlandEcdis
3152         //g_toolbarConfig = _T ( ".....XXXX.X...XX.XXXXXXXXXXXX" );
3153         g_iDistanceFormat = 2; //0 = "Nautical miles"), 1 = "Statute miles", 2 = "Kilometers", 3 = "Meters"
3154         g_iSpeedFormat =2; //0 = "kts"), 1 = "mph", 2 = "km/h", 3 = "m/s"
3155         if ( ps52plib ) ps52plib->SetDisplayCategory( STANDARD );
3156         g_bDrawAISSize = false;
3157         if (gFrame) gFrame->RequestNewToolbars(true);
3158     }
3159     else{
3160         wxLogMessage( _T("Switch InlandEcdis mode Off") );
3161         //reread the settings overruled by inlandEcdis
3162         if (pConfig){
3163             pConfig->SetPath( _T ( "/Settings" ) );
3164             pConfig->Read( _T ( "GlobalToolbarConfig" ), &g_toolbarConfig );
3165             pConfig->Read( _T ( "DistanceFormat" ), &g_iDistanceFormat );
3166             pConfig->Read( _T ( "SpeedFormat" ), &g_iSpeedFormat );
3167             pConfig->Read( _T ( "ShowDepthUnits" ), &g_bShowDepthUnits, 1 );
3168             int read_int;
3169             pConfig->Read( _T ( "nDisplayCategory" ), &read_int, (enum _DisCat) STANDARD );
3170             if ( ps52plib ) ps52plib->SetDisplayCategory((enum _DisCat) read_int );
3171             pConfig->SetPath( _T ( "/Settings/AIS" ) );
3172             pConfig->Read( _T ( "bDrawAISSize" ), &g_bDrawAISSize );
3173             pConfig->Read( _T ( "bDrawAISRealtime" ), &g_bDrawAISRealtime );
3174         }
3175         if (gFrame) gFrame->RequestNewToolbars(true);
3176     }
3177 }
3178 
3179 //-------------------------------------------------------------------------
3180 //
3181 //          Static GPX Support Routines
3182 //
3183 //-------------------------------------------------------------------------
WaypointExists(const wxString & name,double lat,double lon)3184 RoutePoint *WaypointExists( const wxString& name, double lat, double lon )
3185 {
3186     RoutePoint *pret = NULL;
3187 //    if( g_bIsNewLayer ) return NULL;
3188     wxRoutePointListNode *node = pWayPointMan->GetWaypointList()->GetFirst();
3189     while( node ) {
3190         RoutePoint *pr = node->GetData();
3191 
3192 //        if( pr->m_bIsInLayer ) return NULL;
3193 
3194         if( name == pr->GetName() ) {
3195             if( fabs( lat - pr->m_lat ) < 1.e-6 && fabs( lon - pr->m_lon ) < 1.e-6 ) {
3196                 pret = pr;
3197                 break;
3198             }
3199         }
3200         node = node->GetNext();
3201     }
3202 
3203     return pret;
3204 }
3205 
WaypointExists(const wxString & guid)3206 RoutePoint *WaypointExists( const wxString& guid )
3207 {
3208     wxRoutePointListNode *node = pWayPointMan->GetWaypointList()->GetFirst();
3209     while( node ) {
3210         RoutePoint *pr = node->GetData();
3211 
3212 //        if( pr->m_bIsInLayer ) return NULL;
3213 
3214         if( guid == pr->m_GUID ) {
3215             return pr;
3216         }
3217         node = node->GetNext();
3218     }
3219 
3220     return NULL;
3221 }
3222 
WptIsInRouteList(RoutePoint * pr)3223 bool WptIsInRouteList( RoutePoint *pr )
3224 {
3225     bool IsInList = false;
3226 
3227     wxRouteListNode *node1 = pRouteList->GetFirst();
3228     while( node1 ) {
3229         Route *pRoute = node1->GetData();
3230         RoutePointList *pRoutePointList = pRoute->pRoutePointList;
3231 
3232         wxRoutePointListNode *node2 = pRoutePointList->GetFirst();
3233         RoutePoint *prp;
3234 
3235         while( node2 ) {
3236             prp = node2->GetData();
3237 
3238             if( pr->IsSame( prp ) ) {
3239                 IsInList = true;
3240                 break;
3241             }
3242 
3243             node2 = node2->GetNext();
3244         }
3245         node1 = node1->GetNext();
3246     }
3247     return IsInList;
3248 }
3249 
RouteExists(const wxString & guid)3250 Route *RouteExists( const wxString& guid )
3251 {
3252     wxRouteListNode *route_node = pRouteList->GetFirst();
3253 
3254     while( route_node ) {
3255         Route *proute = route_node->GetData();
3256 
3257         if( guid == proute->m_GUID ) return proute;
3258 
3259         route_node = route_node->GetNext();
3260     }
3261     return NULL;
3262 }
3263 
RouteExists(Route * pTentRoute)3264 Route *RouteExists( Route * pTentRoute )
3265 {
3266     wxRouteListNode *route_node = pRouteList->GetFirst();
3267     while( route_node ) {
3268         Route *proute = route_node->GetData();
3269 
3270         if( proute->IsEqualTo( pTentRoute ) )
3271             return proute;
3272 
3273         route_node = route_node->GetNext();       // next route
3274     }
3275     return NULL;
3276 }
3277 
TrackExists(const wxString & guid)3278 Track *TrackExists( const wxString& guid )
3279 {
3280     wxTrackListNode *track_node = pTrackList->GetFirst();
3281 
3282     while( track_node ) {
3283         Track *ptrack = track_node->GetData();
3284 
3285         if( guid == ptrack->m_GUID ) return ptrack;
3286 
3287         track_node = track_node->GetNext();
3288     }
3289     return NULL;
3290 }
3291 
3292 
3293 
3294 // This function formats the input date/time into a valid GPX ISO 8601
3295 // time string specified in the UTC time zone.
3296 
FormatGPXDateTime(wxDateTime dt)3297 wxString FormatGPXDateTime( wxDateTime dt )
3298 {
3299 //      return dt.Format(wxT("%Y-%m-%dT%TZ"), wxDateTime::GMT0);
3300     return dt.Format( wxT("%Y-%m-%dT%H:%M:%SZ") );
3301 }
3302 
3303 
3304 // This function parses a string containing a GPX time representation
3305 // and returns a wxDateTime containing the UTC corresponding to the
3306 // input. The function return value is a pointer past the last valid
3307 // character parsed (if successful) or NULL (if the string is invalid).
3308 //
3309 // Valid GPX time strings are in ISO 8601 format as follows:
3310 //
3311 //   [-]<YYYY>-<MM>-<DD>T<hh>:<mm>:<ss>Z|(+|-<hh>:<mm>)
3312 //
3313 // For example, 2010-10-30T14:34:56Z and 2010-10-30T14:34:56-04:00
3314 // are the same time. The first is UTC and the second is EDT.
3315 
ParseGPXDateTime(wxDateTime & dt,const wxChar * datetime)3316 const wxChar *ParseGPXDateTime( wxDateTime &dt, const wxChar *datetime )
3317 {
3318     long sign, hrs_west, mins_west;
3319     const wxChar *end;
3320 
3321     // Skip any leading whitespace
3322     while( isspace( *datetime ) )
3323         datetime++;
3324 
3325     // Skip (and ignore) leading hyphen
3326     if( *datetime == wxT('-') ) datetime++;
3327 
3328     // Parse and validate ISO 8601 date/time string
3329     if( ( end = dt.ParseFormat( datetime, wxT("%Y-%m-%dT%T") ) ) != NULL ) {
3330 
3331         // Invalid date/time
3332         if( *end == 0 ) return NULL;
3333 
3334         // ParseFormat outputs in UTC if the controlling
3335         // wxDateTime class instance has not been initialized.
3336 
3337         // Date/time followed by UTC time zone flag, so we are done
3338         else
3339             if( *end == wxT('Z') ) {
3340                 end++;
3341                 return end;
3342             }
3343 
3344             // Date/time followed by given number of hrs/mins west of UTC
3345             else
3346                 if( *end == wxT('+') || *end == wxT('-') ) {
3347 
3348                     // Save direction from UTC
3349                     if( *end == wxT('+') ) sign = 1;
3350                     else
3351                         sign = -1;
3352                     end++;
3353 
3354                     // Parse hrs west of UTC
3355                     if( isdigit( *end ) && isdigit( *( end + 1 ) ) && *( end + 2 ) == wxT(':') ) {
3356 
3357                         // Extract and validate hrs west of UTC
3358                         wxString( end ).ToLong( &hrs_west );
3359                         if( hrs_west > 12 ) return NULL;
3360                         end += 3;
3361 
3362                         // Parse mins west of UTC
3363                         if( isdigit( *end ) && isdigit( *( end + 1 ) ) ) {
3364 
3365                             // Extract and validate mins west of UTC
3366                             wxChar mins[3];
3367                             mins[0] = *end;
3368                             mins[1] = *( end + 1 );
3369                             mins[2] = 0;
3370                             wxString( mins ).ToLong( &mins_west );
3371                             if( mins_west > 59 ) return NULL;
3372 
3373                             // Apply correction
3374                             dt -= sign * wxTimeSpan( hrs_west, mins_west, 0, 0 );
3375                             return end + 2;
3376                         } else
3377                             // Missing mins digits
3378                             return NULL;
3379                     } else
3380                         // Missing hrs digits or colon
3381                         return NULL;
3382                 } else
3383                     // Unknown field after date/time (not UTC, not hrs/mins
3384                     //  west of UTC)
3385                     return NULL;
3386     } else
3387         // Invalid ISO 8601 date/time
3388         return NULL;
3389 }
3390 
3391 
3392 //---------------------------------------------------------------------------------
3393 //          Private Font Manager and Helpers
3394 //---------------------------------------------------------------------------------
3395 #include <wx/fontdlg.h>
3396 #include <wx/fontenum.h>
3397 #include "wx/encinfo.h"
3398 
3399 #ifdef __WXX11__
3400 #include "/usr/X11R6/include/X11/Xlib.h"
3401 
3402 //-----------------------------------------------------------------------------
3403 // helper class - MyFontPreviewer
3404 //-----------------------------------------------------------------------------
3405 
3406 class MyFontPreviewer : public wxWindow
3407 {
3408 public:
MyFontPreviewer(wxWindow * parent,const wxSize & sz=wxDefaultSize)3409     MyFontPreviewer ( wxWindow *parent, const wxSize& sz = wxDefaultSize ) : wxWindow ( parent, wxID_ANY, wxDefaultPosition, sz )
3410     {
3411     }
3412 
3413 private:
3414     void OnPaint ( wxPaintEvent& event );
3415     DECLARE_EVENT_TABLE()
3416 };
3417 
BEGIN_EVENT_TABLE(MyFontPreviewer,wxWindow)3418 BEGIN_EVENT_TABLE ( MyFontPreviewer, wxWindow )
3419 EVT_PAINT ( MyFontPreviewer::OnPaint )
3420 END_EVENT_TABLE()
3421 
3422 void MyFontPreviewer::OnPaint ( wxPaintEvent& WXUNUSED ( event ) )
3423 {
3424     wxPaintDC dc ( this );
3425 
3426     wxSize size = GetSize();
3427     wxFont font = GetFont();
3428 
3429     dc.SetPen ( *wxBLACK_PEN );
3430     dc.SetBrush ( *wxWHITE_BRUSH );
3431     dc.DrawRectangle ( 0, 0, size.x, size.y );
3432 
3433     if ( font.Ok() )
3434     {
3435         dc.SetFont ( font );
3436         // Calculate vertical centre
3437         long w, h;
3438         dc.GetTextExtent ( wxT ( "X" ), &w, &h );
3439         dc.SetTextForeground ( GetForegroundColour() );
3440         dc.SetClippingRegion ( 2, 2, size.x-4, size.y-4 );
3441         dc.DrawText ( GetName(),
3442                 10, size.y/2 - h/2 );
3443         dc.DestroyClippingRegion();
3444     }
3445 }
3446 
3447 //-----------------------------------------------------------------------------
3448 // X11FontPicker
3449 //-----------------------------------------------------------------------------
3450 
3451 IMPLEMENT_DYNAMIC_CLASS ( X11FontPicker, wxDialog )
3452 
3453 BEGIN_EVENT_TABLE ( X11FontPicker, wxDialog )
3454 EVT_CHECKBOX ( wxID_FONT_UNDERLINE, X11FontPicker::OnChangeFont )
3455 EVT_CHOICE ( wxID_FONT_STYLE, X11FontPicker::OnChangeFont )
3456 EVT_CHOICE ( wxID_FONT_WEIGHT, X11FontPicker::OnChangeFont )
3457 EVT_CHOICE ( wxID_FONT_FAMILY, X11FontPicker::OnChangeFace )
3458 EVT_CHOICE ( wxID_FONT_COLOUR, X11FontPicker::OnChangeFont )
3459 EVT_CHOICE ( wxID_FONT_SIZE, X11FontPicker::OnChangeFont )
3460 
3461 EVT_CLOSE ( X11FontPicker::OnCloseWindow )
3462 END_EVENT_TABLE()
3463 
3464 #define SCALEABLE_SIZES 11
3465 static wxString scaleable_pointsize[SCALEABLE_SIZES] =
3466 {
3467     wxT ( "6" ),
3468     wxT ( "8" ),
3469     wxT ( "10" ),
3470     wxT ( "12" ),
3471     wxT ( "14" ),
3472     wxT ( "16" ),
3473     wxT ( "18" ),
3474     wxT ( "20" ),
3475     wxT ( "24" ),
3476     wxT ( "30" ),
3477     wxT ( "36" )
3478 };
3479 
3480 #define NUM_COLS 49
3481 static wxString wxColourDialogNames[NUM_COLS]= {wxT ( "ORANGE" ),
3482     wxT ( "GOLDENROD" ),
3483     wxT ( "WHEAT" ),
3484     wxT ( "SPRING GREEN" ),
3485     wxT ( "SKY BLUE" ),
3486     wxT ( "SLATE BLUE" ),
3487     wxT ( "MEDIUM VIOLET RED" ),
3488     wxT ( "PURPLE" ),
3489 
3490     wxT ( "RED" ),
3491     wxT ( "YELLOW" ),
3492     wxT ( "MEDIUM SPRING GREEN" ),
3493     wxT ( "PALE GREEN" ),
3494     wxT ( "CYAN" ),
3495     wxT ( "LIGHT STEEL BLUE" ),
3496     wxT ( "ORCHID" ),
3497     wxT ( "LIGHT MAGENTA" ),
3498 
3499     wxT ( "BROWN" ),
3500     wxT ( "YELLOW" ),
3501     wxT ( "GREEN" ),
3502     wxT ( "CADET BLUE" ),
3503     wxT ( "MEDIUM BLUE" ),
3504     wxT ( "MAGENTA" ),
3505     wxT ( "MAROON" ),
3506     wxT ( "ORANGE RED" ),
3507 
3508     wxT ( "FIREBRICK" ),
3509     wxT ( "CORAL" ),
3510     wxT ( "FOREST GREEN" ),
3511     wxT ( "AQUARAMINE" ),
3512     wxT ( "BLUE" ),
3513     wxT ( "NAVY" ),
3514     wxT ( "THISTLE" ),
3515     wxT ( "MEDIUM VIOLET RED" ),
3516 
3517     wxT ( "INDIAN RED" ),
3518     wxT ( "GOLD" ),
3519     wxT ( "MEDIUM SEA GREEN" ),
3520     wxT ( "MEDIUM BLUE" ),
3521     wxT ( "MIDNIGHT BLUE" ),
3522     wxT ( "GREY" ),
3523     wxT ( "PURPLE" ),
3524     wxT ( "KHAKI" ),
3525 
3526     wxT ( "BLACK" ),
3527     wxT ( "MEDIUM FOREST GREEN" ),
3528     wxT ( "KHAKI" ),
3529     wxT ( "DARK GREY" ),
3530     wxT ( "SEA GREEN" ),
3531     wxT ( "LIGHT GREY" ),
3532     wxT ( "MEDIUM SLATE BLUE" ),
3533     wxT ( "WHITE" )
3534     wxT ( "SIENNA" )
3535 };
3536 
3537 /*
3538  * Generic X11FontPicker
3539  */
3540 
Init()3541 void X11FontPicker::Init()
3542 {
3543     m_useEvents = false;
3544     m_previewer = NULL;
3545     Create ( m_parent );
3546 }
3547 
~X11FontPicker()3548 X11FontPicker::~X11FontPicker()
3549 {
3550 }
3551 
OnCloseWindow(wxCloseEvent & WXUNUSED (event))3552 void X11FontPicker::OnCloseWindow ( wxCloseEvent& WXUNUSED ( event ) )
3553 {
3554     EndModal ( wxID_CANCEL );
3555 }
3556 
DoCreate(wxWindow * parent)3557 bool X11FontPicker::DoCreate ( wxWindow *parent )
3558 {
3559     if ( !wxDialog::Create ( parent , wxID_ANY , _T ( "Choose Font" ) , wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE,
3560                     _T ( "fontdialog" ) ) )
3561     {
3562         wxFAIL_MSG ( wxT ( "wxFontDialog creation failed" ) );
3563         return false;
3564     }
3565 
3566     InitializeAllAvailableFonts();
3567     InitializeFont();
3568     CreateWidgets();
3569 
3570 // sets initial font in preview area
3571     wxCommandEvent dummy;
3572     OnChangeFont ( dummy );
3573 
3574     return true;
3575 }
3576 
ShowModal()3577 int X11FontPicker::ShowModal()
3578 {
3579     int ret = wxDialog::ShowModal();
3580 
3581     if ( ret != wxID_CANCEL )
3582     {
3583         dialogFont = *pPreviewFont;
3584         m_fontData.m_chosenFont = dialogFont;
3585     }
3586 
3587     return ret;
3588 }
3589 
InitializeAllAvailableFonts()3590 void X11FontPicker::InitializeAllAvailableFonts()
3591 {
3592 
3593     // get the Array of all fonts facenames
3594     wxString pattern;
3595     pattern.Printf ( wxT ( "-*-*-*-*-*-*-*-*-*-*-*-*-iso8859-1" ) );
3596 
3597     int nFonts;
3598     char ** list = XListFonts ( ( Display * ) wxGetDisplay(), pattern.mb_str(), 32767, &nFonts );
3599 
3600     pFaceNameArray = new wxArrayString;
3601     unsigned int jname;
3602     for ( int i=0; i < nFonts; i++ )
3603     {
3604         wxStringTokenizer st ( wxString ( list[i] ), _T ( "-" ) );
3605         st.GetNextToken();
3606         st.GetNextToken();
3607         wxString facename = st.GetNextToken();
3608         for ( jname=0; jname<pFaceNameArray->GetCount(); jname++ )
3609         {
3610             if ( facename == pFaceNameArray->Item ( jname ) )
3611             break;
3612         }
3613         if ( jname >= pFaceNameArray->GetCount() )
3614         {
3615             pFaceNameArray->Add ( facename );
3616         }
3617 
3618     }
3619 
3620 }
3621 
3622 // This should be application-settable
ShowToolTips()3623 static bool ShowToolTips() {return false;}
3624 
CreateWidgets()3625 void X11FontPicker::CreateWidgets()
3626 {
3627     // layout
3628 
3629     bool is_pda = ( wxSystemSettings::GetScreenType() <= wxSYS_SCREEN_PDA );
3630     int noCols, noRows;
3631     if ( is_pda )
3632     {
3633         noCols = 2; noRows = 3;
3634     }
3635     else
3636     {
3637         noCols = 3; noRows = 2;
3638     }
3639 
3640     wxBoxSizer* itemBoxSizer2 = new wxBoxSizer ( wxVERTICAL );
3641     this->SetSizer ( itemBoxSizer2 );
3642     this->SetAutoLayout ( TRUE );
3643 
3644     wxBoxSizer* itemBoxSizer3 = new wxBoxSizer ( wxVERTICAL );
3645     itemBoxSizer2->Add ( itemBoxSizer3, 1, wxEXPAND|wxALL, 5 );
3646 
3647     wxFlexGridSizer* itemGridSizer4 = new wxFlexGridSizer ( noRows, noCols, 0, 0 );
3648     itemBoxSizer3->Add ( itemGridSizer4, 0, wxEXPAND, 5 );
3649 
3650     wxBoxSizer* itemBoxSizer5 = new wxBoxSizer ( wxVERTICAL );
3651     itemGridSizer4->Add ( itemBoxSizer5, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 );
3652     wxStaticText* itemStaticText6 = new wxStaticText ( this, wxID_STATIC, _ ( "&Font family:" ),
3653             wxDefaultPosition, wxDefaultSize, 0 );
3654     itemBoxSizer5->Add ( itemStaticText6, 0, wxALIGN_LEFT|wxLEFT|wxRIGHT|wxTOP, 5 );
3655 
3656     wxChoice* itemChoice7 = new wxChoice ( this, wxID_FONT_FAMILY, wxDefaultPosition,
3657             wxDefaultSize, *pFaceNameArray, 0 );
3658     itemChoice7->SetHelpText ( _ ( "The font family." ) );
3659     if ( ShowToolTips() )
3660     itemChoice7->SetToolTip ( _ ( "The font family." ) );
3661     itemBoxSizer5->Add ( itemChoice7, 0, wxALIGN_LEFT|wxALL, 5 );
3662 
3663     wxBoxSizer* itemBoxSizer8 = new wxBoxSizer ( wxVERTICAL );
3664     itemGridSizer4->Add ( itemBoxSizer8, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 );
3665     wxStaticText* itemStaticText9 = new wxStaticText ( this, wxID_STATIC, _ ( "&Style:" ), wxDefaultPosition, wxDefaultSize, 0 );
3666     itemBoxSizer8->Add ( itemStaticText9, 0, wxALIGN_LEFT|wxLEFT|wxRIGHT|wxTOP, 5 );
3667 
3668     wxChoice* itemChoice10 = new wxChoice ( this, wxID_FONT_STYLE, wxDefaultPosition, wxDefaultSize );
3669     itemChoice10->SetHelpText ( _ ( "The font style." ) );
3670     if ( ShowToolTips() )
3671     itemChoice10->SetToolTip ( _ ( "The font style." ) );
3672     itemBoxSizer8->Add ( itemChoice10, 0, wxALIGN_LEFT|wxALL, 5 );
3673 
3674     wxBoxSizer* itemBoxSizer11 = new wxBoxSizer ( wxVERTICAL );
3675     itemGridSizer4->Add ( itemBoxSizer11, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 );
3676     wxStaticText* itemStaticText12 = new wxStaticText ( this, wxID_STATIC, _ ( "&Weight:" ), wxDefaultPosition, wxDefaultSize, 0 );
3677     itemBoxSizer11->Add ( itemStaticText12, 0, wxALIGN_LEFT|wxLEFT|wxRIGHT|wxTOP, 5 );
3678 
3679     wxChoice* itemChoice13 = new wxChoice ( this, wxID_FONT_WEIGHT, wxDefaultPosition, wxDefaultSize );
3680     itemChoice13->SetHelpText ( _ ( "The font weight." ) );
3681     if ( ShowToolTips() )
3682     itemChoice13->SetToolTip ( _ ( "The font weight." ) );
3683     itemBoxSizer11->Add ( itemChoice13, 0, wxALIGN_LEFT|wxALL, 5 );
3684 
3685     wxBoxSizer* itemBoxSizer14 = new wxBoxSizer ( wxVERTICAL );
3686     itemGridSizer4->Add ( itemBoxSizer14, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 );
3687     if ( m_fontData.GetEnableEffects() )
3688     {
3689         wxStaticText* itemStaticText15 = new wxStaticText ( this, wxID_STATIC, _ ( "C&olour:" ),
3690                 wxDefaultPosition, wxDefaultSize, 0 );
3691         itemBoxSizer14->Add ( itemStaticText15, 0, wxALIGN_LEFT|wxLEFT|wxRIGHT|wxTOP, 5 );
3692 
3693         wxSize colourSize = wxDefaultSize;
3694         if ( is_pda )
3695         colourSize.x = 100;
3696 
3697         wxChoice* itemChoice16 = new wxChoice ( this, wxID_FONT_COLOUR, wxDefaultPosition,
3698                 colourSize, NUM_COLS, wxColourDialogNames, 0 );
3699         itemChoice16->SetHelpText ( _ ( "The font colour." ) );
3700         if ( ShowToolTips() )
3701         itemChoice16->SetToolTip ( _ ( "The font colour." ) );
3702         itemBoxSizer14->Add ( itemChoice16, 0, wxALIGN_LEFT|wxALL, 5 );
3703     }
3704 
3705     wxBoxSizer* itemBoxSizer17 = new wxBoxSizer ( wxVERTICAL );
3706     itemGridSizer4->Add ( itemBoxSizer17, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 );
3707     wxStaticText* itemStaticText18 = new wxStaticText ( this, wxID_STATIC, _ ( "&Point size:" ),
3708             wxDefaultPosition, wxDefaultSize, 0 );
3709     itemBoxSizer17->Add ( itemStaticText18, 0, wxALIGN_LEFT|wxLEFT|wxRIGHT|wxTOP, 5 );
3710 
3711     wxChoice *pc = new wxChoice ( this, wxID_FONT_SIZE, wxDefaultPosition, wxDefaultSize );
3712     pc->SetHelpText ( _ ( "The font point size." ) );
3713     if ( ShowToolTips() )
3714     pc->SetToolTip ( _ ( "The font point size." ) );
3715     itemBoxSizer17->Add ( pc, 0, wxALIGN_LEFT|wxALL, 5 );
3716 
3717     if ( m_fontData.GetEnableEffects() )
3718     {
3719         wxBoxSizer* itemBoxSizer20 = new wxBoxSizer ( wxVERTICAL );
3720         itemGridSizer4->Add ( itemBoxSizer20, 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL, 5 );
3721         wxCheckBox* itemCheckBox21 = new wxCheckBox ( this, wxID_FONT_UNDERLINE, _ ( "&Underline" ),
3722                 wxDefaultPosition, wxDefaultSize, 0 );
3723         itemCheckBox21->SetValue ( FALSE );
3724         itemCheckBox21->SetHelpText ( _ ( "Whether the font is underlined." ) );
3725         if ( ShowToolTips() )
3726         itemCheckBox21->SetToolTip ( _ ( "Whether the font is underlined." ) );
3727         itemBoxSizer20->Add ( itemCheckBox21, 0, wxALIGN_LEFT|wxALL, 5 );
3728     }
3729 
3730     if ( !is_pda )
3731     itemBoxSizer3->Add ( 5, 5, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5 );
3732 
3733     wxStaticText* itemStaticText23 = new wxStaticText ( this, wxID_STATIC, _ ( "Preview:" ), wxDefaultPosition, wxDefaultSize, 0 );
3734     itemBoxSizer3->Add ( itemStaticText23, 0, wxALIGN_LEFT|wxLEFT|wxRIGHT|wxTOP, 5 );
3735 
3736     MyFontPreviewer* itemWindow24 = new MyFontPreviewer ( this, wxSize ( 400, 80 ) );
3737     m_previewer = itemWindow24;
3738     itemWindow24->SetHelpText ( _ ( "Shows the font preview." ) );
3739     if ( ShowToolTips() )
3740     itemWindow24->SetToolTip ( _ ( "Shows the font preview." ) );
3741     itemBoxSizer3->Add ( itemWindow24, 0, wxEXPAND, 5 );
3742 
3743     wxBoxSizer* itemBoxSizer25 = new wxBoxSizer ( wxHORIZONTAL );
3744     itemBoxSizer3->Add ( itemBoxSizer25, 0, wxEXPAND, 5 );
3745     itemBoxSizer25->Add ( 5, 5, 1, wxEXPAND|wxALL, 5 );
3746 
3747     wxButton* itemButton28 = new wxButton ( this, wxID_CANCEL, _( "Cancel" ), wxDefaultPosition, wxDefaultSize, 0 );
3748 
3749     if ( ShowToolTips() )
3750     itemButton28->SetToolTip ( _ ( "Click to cancel the font selection." ) );
3751     itemBoxSizer25->Add ( itemButton28, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
3752 
3753     wxButton* itemButton27 = new wxButton ( this, wxID_OK, _ ( "&OK" ), wxDefaultPosition, wxDefaultSize, 0 );
3754     itemButton27->SetDefault();
3755     itemButton27->SetHelpText ( _ ( "Click to confirm the font selection." ) );
3756     if ( ShowToolTips() )
3757     itemButton27->SetToolTip ( _ ( "Click to confirm the font selection." ) );
3758     itemBoxSizer25->Add ( itemButton27, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
3759 
3760     familyChoice = ( wxChoice* ) FindWindow ( wxID_FONT_FAMILY );
3761     styleChoice = ( wxChoice* ) FindWindow ( wxID_FONT_STYLE );
3762     weightChoice = ( wxChoice* ) FindWindow ( wxID_FONT_WEIGHT );
3763     colourChoice = ( wxChoice* ) FindWindow ( wxID_FONT_COLOUR );
3764     pointSizeChoice = ( wxChoice* ) FindWindow ( wxID_FONT_SIZE );
3765     underLineCheckBox = ( wxCheckBox* ) FindWindow ( wxID_FONT_UNDERLINE );
3766 
3767     //    Get readable font items
3768     wxString gotfontnative = dialogFont.GetNativeFontInfoDesc();
3769     wxStringTokenizer st ( gotfontnative, _T ( "-" ) );
3770     st.GetNextToken();
3771     st.GetNextToken();
3772     wxString facename = st.GetNextToken();
3773     wxString weight = st.GetNextToken();
3774     st.GetNextToken();
3775     st.GetNextToken();
3776     st.GetNextToken();
3777     st.GetNextToken();
3778     wxString pointsize = st.GetNextToken();
3779 
3780     int ptsz = atoi ( pointsize.mb_str() );
3781     pointsize.Printf ( _T ( "%d" ), ptsz / 10 );
3782 
3783     SetChoiceOptionsFromFacename ( facename );
3784 
3785     familyChoice->SetStringSelection ( facename );
3786     weightChoice->SetStringSelection ( weight );
3787     pointSizeChoice->SetStringSelection ( pointsize );
3788 
3789     m_previewer->SetFont ( dialogFont );
3790     m_previewer->SetName ( _T( "ABCDEFGabcdefg12345" ) );
3791 
3792 //    m_previewer->Refresh();
3793 
3794 //    familyChoice->SetStringSelection( wxFontFamilyIntToString(dialogFont.GetFamily()) );
3795 //    styleChoice->SetStringSelection(wxFontStyleIntToString(dialogFont.GetStyle()));
3796 //    weightChoice->SetStringSelection(wxFontWeightIntToString(dialogFont.GetWeight()));
3797 
3798     /*
3799      if (colourChoice)
3800      {
3801      wxString name(wxTheColourDatabase->FindName(m_fontData.GetColour()));
3802      if (name.length())
3803      colourChoice->SetStringSelection(name);
3804      else
3805      colourChoice->SetStringSelection(wxT("BLACK"));
3806      }
3807 
3808      if (underLineCheckBox)
3809      {
3810      underLineCheckBox->SetValue(dialogFont.GetUnderlined());
3811      }
3812 
3813      //    pointSizeChoice->SetSelection(dialogFont.GetPointSize()-1);
3814      pointSizeChoice->SetSelection(0);
3815 
3816      #if !defined(__SMARTPHONE__) && !defined(__POCKETPC__)
3817      GetSizer()->SetItemMinSize(m_previewer, is_pda ? 100 : 430, is_pda ? 40 : 100);
3818      GetSizer()->SetSizeHints(this);
3819      GetSizer()->Fit(this);
3820 
3821      Centre(wxBOTH);
3822      #endif
3823      */
3824 
3825     // Don't block events any more
3826     m_useEvents = true;
3827 
3828 }
3829 
OnChangeFace(wxCommandEvent & WXUNUSED (event))3830 void X11FontPicker::OnChangeFace ( wxCommandEvent& WXUNUSED ( event ) )
3831 {
3832     if ( !m_useEvents ) return;
3833 
3834     //    Capture the current selections
3835     wxString facename = familyChoice->GetStringSelection();
3836     wxString pointsize = pointSizeChoice->GetStringSelection();
3837     wxString weight = weightChoice->GetStringSelection();
3838 
3839     SetChoiceOptionsFromFacename ( facename );
3840 
3841     //    Reset the choices
3842     familyChoice->SetStringSelection ( facename );
3843     weightChoice->SetStringSelection ( weight );
3844     pointSizeChoice->SetStringSelection ( pointsize );
3845 
3846     //    And make the font change
3847     DoFontChange();
3848 
3849 }
3850 
SetChoiceOptionsFromFacename(const wxString & facename)3851 void X11FontPicker::SetChoiceOptionsFromFacename (const wxString &facename)
3852 {
3853     //    Get a list of matching fonts
3854     char face[101];
3855     strncpy ( face, facename.mb_str(), 100 );
3856     face[100] = '\0';
3857 
3858     char pattern[100];
3859     sprintf ( pattern, "-*-%s-*-*-*-*-*-*-*-*-*-*-iso8859-1", face );
3860 //    wxString pattern;
3861 //    pattern.Printf(wxT("-*-%s-*-*-*-*-*-*-*-*-*-*-iso8859-1"), facename.mb_str());
3862 
3863     int nFonts;
3864     char ** list = XListFonts ( ( Display * ) wxGetDisplay(), pattern, 32767, &nFonts );
3865 
3866     //    First, look thru all the point sizes looking for "0" to indicate scaleable (e.g. TrueType) font
3867     bool scaleable = false;
3868     for ( int i=0; i < nFonts; i++ )
3869     {
3870         wxStringTokenizer st ( wxString ( list[i] ), _T ( "-" ) );
3871         st.GetNextToken();
3872         st.GetNextToken();
3873         st.GetNextToken();
3874         st.GetNextToken();
3875         st.GetNextToken();
3876         st.GetNextToken();
3877         st.GetNextToken();
3878         wxString pointsize = st.GetNextToken();
3879 
3880         if ( pointsize.IsSameAs ( _T ( "0" ) ) )
3881         {
3882             scaleable = true;
3883             break;
3884         }
3885     }
3886 
3887     // make different pointsize selections for scaleable fonts
3888     wxArrayString PointSizeArray;
3889 
3890     if ( scaleable )
3891     {
3892         for ( int j=0; j < SCALEABLE_SIZES; j++ )
3893         PointSizeArray.Add ( scaleable_pointsize[j] );
3894     }
3895 
3896     else
3897     {
3898         //Get the Point Sizes Array
3899         unsigned int jname;
3900         for ( int i=0; i < nFonts; i++ )
3901         {
3902 //                  printf("%s\n", list[i]);
3903             wxStringTokenizer st ( wxString ( list[i] ), _T ( "-" ) );
3904             st.GetNextToken();
3905             st.GetNextToken();
3906             st.GetNextToken();
3907             st.GetNextToken();
3908             st.GetNextToken();
3909             st.GetNextToken();
3910             st.GetNextToken();
3911             wxString pointsize = st.GetNextToken();
3912             //           printf("%s\n",facename.mb_str());
3913             for ( jname=0; jname<PointSizeArray.GetCount(); jname++ )
3914             {
3915                 if ( pointsize == PointSizeArray[jname] )
3916                 break;
3917             }
3918             if ( jname >= PointSizeArray.GetCount() )
3919             {
3920                 PointSizeArray.Add ( pointsize );
3921 //                        printf("Added %s\n", pointsize.mb_str());
3922             }
3923         }
3924     }
3925     pointSizeChoice->Clear();
3926     pointSizeChoice->Append ( PointSizeArray );
3927     pointSizeChoice->SetSelection ( 0 );
3928 
3929     //Get the Weight Array
3930     wxArrayString WeightArray;
3931     for ( int i=0; i < nFonts; i++ )
3932     {
3933 //            printf("%s\n", list[i]);
3934         wxStringTokenizer st ( wxString ( list[i] ), _T ( "-" ) );
3935         st.GetNextToken();
3936         st.GetNextToken();
3937         st.GetNextToken();
3938         wxString weight = st.GetNextToken();
3939         //           printf("%s\n",facename.mb_str());
3940         unsigned int jname;
3941         for ( jname=0; jname<WeightArray.GetCount(); jname++ )
3942         {
3943             if ( weight == WeightArray[jname] )
3944             break;
3945         }
3946         if ( jname >= WeightArray.GetCount() )
3947         {
3948             WeightArray.Add ( weight );
3949 //                  printf("Added weight %s\n", weight.mb_str());
3950         }
3951     }
3952 
3953     weightChoice->Clear();
3954     weightChoice->Append ( WeightArray );
3955     weightChoice->SetSelection ( 0 );
3956 
3957 }
3958 
InitializeFont()3959 void X11FontPicker::InitializeFont()
3960 {
3961     int fontFamily = wxSWISS;
3962     int fontWeight = wxNORMAL;
3963     int fontStyle = wxNORMAL;
3964     int fontSize = 12;
3965     bool fontUnderline = false;
3966 
3967     wxString fontnative;
3968     if ( m_fontData.m_initialFont.Ok() )
3969     {
3970         fontnative = m_fontData.m_initialFont.GetNativeFontInfoDesc();
3971         fontFamily = m_fontData.m_initialFont.GetFamily();
3972         fontWeight = m_fontData.m_initialFont.GetWeight();
3973         fontStyle = m_fontData.m_initialFont.GetStyle();
3974         fontSize = m_fontData.m_initialFont.GetPointSize();
3975         fontUnderline = m_fontData.m_initialFont.GetUnderlined();
3976     }
3977 
3978 //      printf("Init Fetching    %s\n", fontnative.mb_str());
3979 
3980     wxFont tFont = wxFont ( fontSize, fontFamily, fontStyle,
3981             fontWeight, fontUnderline );
3982 
3983     wxFont *pdialogFont = tFont.New ( fontnative );
3984 
3985     //    Confirm
3986     /*
3987      wxNativeFontInfo *i = (wxNativeFontInfo *)pdialogFont->GetNativeFontInfo();
3988 
3989      XFontStruct *xfont = (XFontStruct*) pdialogFont->GetFontStruct( 1.0, (Display *)wxGetDisplay() );
3990      unsigned long ret;
3991      XGetFontProperty(xfont, 18, &ret);
3992      char* x = XGetAtomName((Display *)wxGetDisplay(), ret);
3993      printf(" Init Got %s\n", x);
3994      */
3995 
3996     dialogFont = *pdialogFont;
3997 
3998 }
3999 
OnChangeFont(wxCommandEvent & WXUNUSED (event))4000 void X11FontPicker::OnChangeFont ( wxCommandEvent& WXUNUSED ( event ) )
4001 {
4002     if ( !m_useEvents ) return;
4003 
4004     DoFontChange();
4005 }
4006 
DoFontChange(void)4007 void X11FontPicker::DoFontChange ( void )
4008 {
4009     wxString facename = familyChoice->GetStringSelection();
4010     wxString pointsize = pointSizeChoice->GetStringSelection();
4011     wxString weight = weightChoice->GetStringSelection();
4012 
4013     char font_x[200];
4014     sprintf ( font_x,"-*-%s-%s-r-normal-*-*-%s0-*-*-*-*-iso8859-1", facename.mb_str(), weight.mb_str(), pointsize.mb_str() );
4015     wxString font_xlfd ( font_x, wxConvUTF8 );
4016 
4017 //                  printf("Fetching    %s\n", font_xlfd.mb_str());
4018 
4019     XFontStruct *test = XLoadQueryFont ( ( Display * ) wxGetDisplay(),font_xlfd.mb_str() );
4020 
4021     //    Confirm
4022     /*
4023      unsigned long ret0;
4024      if(test)
4025      {
4026      XGetFontProperty(test, 18, &ret0);
4027      char* x = XGetAtomName((Display *)wxGetDisplay(), ret0);
4028      printf("FGot %s\n", x);
4029      }
4030      */
4031     if ( test )
4032     {
4033         font_xlfd.Prepend ( "0;" );
4034         wxFont *ptf = new wxFont;
4035         pPreviewFont = ptf->New ( font_xlfd );
4036 
4037         /*
4038          wxNativeFontInfo *i = (wxNativeFontInfo *)pPreviewFont->GetNativeFontInfo();
4039 
4040          XFontStruct *xfont = (XFontStruct*) pPreviewFont->GetFontStruct( 1.0, (Display *)wxGetDisplay() );
4041          unsigned long ret;
4042          XGetFontProperty(xfont, 18, &ret);
4043          char* x = XGetAtomName((Display *)wxGetDisplay(), ret);
4044          printf("Got %s\n", x);
4045          */
4046         m_previewer->SetName ( _T( "ABCDEFGabcdefg12345" ) );
4047         m_previewer->SetFont ( *pPreviewFont );
4048         m_previewer->Refresh();
4049     }
4050 
4051     else
4052     {
4053         wxString err ( _T ( "No Font:" ) );
4054         err.Append ( font_xlfd );
4055         m_previewer->SetName ( err );
4056         m_previewer->SetFont ( *pPreviewFont );
4057         m_previewer->Refresh();
4058     }
4059 
4060     /*
4061      int fontFamily = wxFontFamilyStringToInt(WXSTRINGCAST familyChoice->GetStringSelection());
4062      int fontWeight = wxFontWeightStringToInt(WXSTRINGCAST weightChoice->GetStringSelection());
4063      int fontStyle = wxFontStyleStringToInt(WXSTRINGCAST styleChoice->GetStringSelection());
4064      int fontSize = wxAtoi(pointSizeChoice->GetStringSelection());
4065      // Start with previous underline setting, we want to retain it even if we can't edit it
4066      // dialogFont is always initialized because of the call to InitializeFont
4067      int fontUnderline = dialogFont.GetUnderlined();
4068 
4069      if (underLineCheckBox)
4070      {
4071      fontUnderline = underLineCheckBox->GetValue();
4072      }
4073 
4074      dialogFont = wxFont(fontSize, fontFamily, fontStyle, fontWeight, (fontUnderline != 0));
4075      m_previewer->SetFont(dialogFont);
4076 
4077      if ( colourChoice )
4078      {
4079      if ( !colourChoice->GetStringSelection().empty() )
4080      {
4081      wxColour col = wxTheColourDatabase->Find(colourChoice->GetStringSelection());
4082      if (col.Ok())
4083      {
4084      m_fontData.m_fontColour = col;
4085      }
4086      }
4087      }
4088      // Update color here so that we can also use the color originally passed in
4089      // (EnableEffects may be false)
4090      if (m_fontData.m_fontColour.Ok())
4091      m_previewer->SetForegroundColour(m_fontData.m_fontColour);
4092 
4093      m_previewer->Refresh();
4094      */
4095 }
4096 
4097 #endif            //__WXX11__
4098 
4099 //---------------------------------------------------------------------------------
4100 //          Vector Stuff for Hit Test Algorithm
4101 //---------------------------------------------------------------------------------
vGetLengthOfNormal(pVector2D a,pVector2D b,pVector2D n)4102 double vGetLengthOfNormal( pVector2D a, pVector2D b, pVector2D n )
4103 {
4104     vector2D c, vNormal;
4105     vNormal.x = 0;
4106     vNormal.y = 0;
4107     //
4108     //Obtain projection vector.
4109     //
4110     //c = ((a * b)/(|b|^2))*b
4111     //
4112     c.x = b->x * ( vDotProduct( a, b ) / vDotProduct( b, b ) );
4113     c.y = b->y * ( vDotProduct( a, b ) / vDotProduct( b, b ) );
4114 //
4115     //Obtain perpendicular projection : e = a - c
4116     //
4117     vSubtractVectors( a, &c, &vNormal );
4118     //
4119     //Fill PROJECTION structure with appropriate values.
4120     //
4121     *n = vNormal;
4122 
4123     return ( vVectorMagnitude( &vNormal ) );
4124 }
4125 
vDotProduct(pVector2D v0,pVector2D v1)4126 double vDotProduct( pVector2D v0, pVector2D v1 )
4127 {
4128     double dotprod;
4129 
4130     dotprod = ( v0 == NULL || v1 == NULL ) ? 0.0 : ( v0->x * v1->x ) + ( v0->y * v1->y );
4131 
4132     return ( dotprod );
4133 }
4134 
vAddVectors(pVector2D v0,pVector2D v1,pVector2D v)4135 pVector2D vAddVectors( pVector2D v0, pVector2D v1, pVector2D v )
4136 {
4137     if( v0 == NULL || v1 == NULL ) v = (pVector2D) NULL;
4138     else {
4139         v->x = v0->x + v1->x;
4140         v->y = v0->y + v1->y;
4141     }
4142     return ( v );
4143 }
4144 
vSubtractVectors(pVector2D v0,pVector2D v1,pVector2D v)4145 pVector2D vSubtractVectors( pVector2D v0, pVector2D v1, pVector2D v )
4146 {
4147     if( v0 == NULL || v1 == NULL ) v = (pVector2D) NULL;
4148     else {
4149         v->x = v0->x - v1->x;
4150         v->y = v0->y - v1->y;
4151     }
4152     return ( v );
4153 }
4154 
vVectorSquared(pVector2D v0)4155 double vVectorSquared( pVector2D v0 )
4156 {
4157     double dS;
4158 
4159     if( v0 == NULL ) dS = 0.0;
4160     else
4161         dS = ( ( v0->x * v0->x ) + ( v0->y * v0->y ) );
4162     return ( dS );
4163 }
4164 
vVectorMagnitude(pVector2D v0)4165 double vVectorMagnitude( pVector2D v0 )
4166 {
4167     double dMagnitude;
4168 
4169     if( v0 == NULL ) dMagnitude = 0.0;
4170     else
4171         dMagnitude = sqrt( vVectorSquared( v0 ) );
4172     return ( dMagnitude );
4173 }
4174 
4175 /**************************************************************************/
4176 /*          LogMessageOnce                                                */
4177 /**************************************************************************/
4178 
LogMessageOnce(const wxString & msg)4179 bool LogMessageOnce(const wxString &msg)
4180 {
4181     //    Search the array for a match
4182 
4183     for( unsigned int i = 0; i < pMessageOnceArray->GetCount(); i++ ) {
4184         if( msg.IsSameAs( pMessageOnceArray->Item( i ) ) ) return false;
4185     }
4186 
4187     // Not found, so add to the array
4188     pMessageOnceArray->Add( msg );
4189 
4190     //    And print it
4191     wxLogMessage( msg );
4192     return true;
4193 }
4194 
4195 /**************************************************************************/
4196 /*          Some assorted utilities                                       */
4197 /**************************************************************************/
4198 
4199 /**************************************************************************/
4200 /*          Converts the distance to the units selected by user           */
4201 /**************************************************************************/
toUsrDistance(double nm_distance,int unit)4202 double toUsrDistance( double nm_distance, int unit  )
4203 {
4204     double ret = NAN;
4205     if ( unit == -1 )
4206         unit = g_iDistanceFormat;
4207     switch( unit ){
4208         case DISTANCE_NMI: //Nautical miles
4209             ret = nm_distance;
4210             break;
4211         case DISTANCE_MI: //Statute miles
4212             ret = nm_distance * 1.15078;
4213             break;
4214         case DISTANCE_KM:
4215             ret = nm_distance * 1.852;
4216             break;
4217         case DISTANCE_M:
4218             ret = nm_distance * 1852;
4219             break;
4220         case DISTANCE_FT:
4221             ret = nm_distance * 6076.12;
4222             break;
4223         case DISTANCE_FA:
4224             ret = nm_distance * 1012.68591;
4225             break;
4226         case DISTANCE_IN:
4227             ret = nm_distance * 72913.4;
4228             break;
4229         case DISTANCE_CM:
4230             ret = nm_distance * 185200;
4231             break;
4232     }
4233     return ret;
4234 }
4235 
4236 /**************************************************************************/
4237 /*          Converts the distance from the units selected by user to NMi  */
4238 /**************************************************************************/
fromUsrDistance(double usr_distance,int unit)4239 double fromUsrDistance( double usr_distance, int unit )
4240 {
4241     double ret = NAN;
4242     if ( unit == -1 )
4243         unit = g_iDistanceFormat;
4244     switch( unit ){
4245         case DISTANCE_NMI: //Nautical miles
4246             ret = usr_distance;
4247             break;
4248         case DISTANCE_MI: //Statute miles
4249             ret = usr_distance / 1.15078;
4250             break;
4251         case DISTANCE_KM:
4252             ret = usr_distance / 1.852;
4253             break;
4254         case DISTANCE_M:
4255             ret = usr_distance / 1852;
4256             break;
4257         case DISTANCE_FT:
4258             ret = usr_distance / 6076.12;
4259             break;
4260     }
4261     return ret;
4262 }
4263 
4264 /**************************************************************************/
4265 /*          Returns the abbreviation of user selected distance unit       */
4266 /**************************************************************************/
getUsrDistanceUnit(int unit)4267 wxString getUsrDistanceUnit( int unit )
4268 {
4269     wxString ret;
4270     if ( unit == -1 )
4271         unit = g_iDistanceFormat;
4272     switch( unit ){
4273         case DISTANCE_NMI: //Nautical miles
4274             ret = _("NMi");
4275             break;
4276         case DISTANCE_MI: //Statute miles
4277             ret = _("mi");
4278             break;
4279         case DISTANCE_KM:
4280             ret = _("km");
4281             break;
4282         case DISTANCE_M:
4283             ret = _("m");
4284             break;
4285         case DISTANCE_FT:
4286             ret = _("ft");
4287             break;
4288         case DISTANCE_FA:
4289             ret = _("fa");
4290             break;
4291         case DISTANCE_IN:
4292             ret = _("in");
4293             break;
4294         case DISTANCE_CM:
4295             ret = _("cm");
4296             break;
4297     }
4298     return ret;
4299 }
4300 
4301 /**************************************************************************/
4302 /*          Converts the speed to the units selected by user              */
4303 /**************************************************************************/
toUsrSpeed(double kts_speed,int unit)4304 double toUsrSpeed( double kts_speed, int unit )
4305 {
4306     double ret = NAN;
4307     if ( unit == -1 )
4308         unit = g_iSpeedFormat;
4309     switch( unit )
4310     {
4311         case SPEED_KTS: //kts
4312             ret = kts_speed;
4313             break;
4314         case SPEED_MPH: //mph
4315             ret = kts_speed * 1.15078;
4316             break;
4317         case SPEED_KMH: //km/h
4318             ret = kts_speed * 1.852;
4319             break;
4320         case SPEED_MS: //m/s
4321             ret = kts_speed * 0.514444444;
4322             break;
4323     }
4324     return ret;
4325 }
4326 
4327 /**************************************************************************/
4328 /*          Converts the speed from the units selected by user to knots   */
4329 /**************************************************************************/
fromUsrSpeed(double usr_speed,int unit)4330 double fromUsrSpeed( double usr_speed, int unit )
4331 {
4332     double ret = NAN;
4333     if ( unit == -1 )
4334         unit = g_iSpeedFormat;
4335     switch( unit )
4336     {
4337         case SPEED_KTS: //kts
4338             ret = usr_speed;
4339             break;
4340         case SPEED_MPH: //mph
4341             ret = usr_speed / 1.15078;
4342             break;
4343         case SPEED_KMH: //km/h
4344             ret = usr_speed / 1.852;
4345             break;
4346         case SPEED_MS: //m/s
4347             ret = usr_speed / 0.514444444;
4348             break;
4349     }
4350     return ret;
4351 }
4352 
4353 /**************************************************************************/
4354 /*          Returns the abbreviation of user selected speed unit          */
4355 /**************************************************************************/
getUsrSpeedUnit(int unit)4356 wxString getUsrSpeedUnit( int unit )
4357 {
4358     wxString ret;
4359     if ( unit == -1 )
4360         unit = g_iSpeedFormat;
4361     switch( unit ){
4362         case SPEED_KTS: //kts
4363             ret = _("kts");
4364             break;
4365         case SPEED_MPH: //mph
4366             ret = _("mph");
4367             break;
4368         case SPEED_KMH:
4369             ret = _("km/h");
4370             break;
4371         case SPEED_MS:
4372             ret = _("m/s");
4373             break;
4374     }
4375     return ret;
4376 }
4377 
formatTimeDelta(wxTimeSpan span)4378 wxString formatTimeDelta(wxTimeSpan span)
4379 {
4380     wxString timeStr;
4381     int days = span.GetDays();
4382     span -= wxTimeSpan::Days(days);
4383     int hours = span.GetHours();
4384     span -= wxTimeSpan::Hours(hours);
4385     double minutes = (double)span.GetSeconds().ToLong()/60.0;
4386     span -= wxTimeSpan::Minutes(span.GetMinutes());
4387     int seconds = (double)span.GetSeconds().ToLong();
4388 
4389     timeStr = (days ? wxString::Format(_("%dd "), days) : _T("")) +
4390     (hours || days ? wxString::Format(_("%2dH %2dM"), hours, (int)round(minutes)) :
4391      wxString::Format(_("%2dM %2dS"), (int)floor(minutes), seconds));
4392 
4393     return timeStr;
4394 }
4395 
formatTimeDelta(wxDateTime startTime,wxDateTime endTime)4396 wxString formatTimeDelta(wxDateTime startTime, wxDateTime endTime)
4397 {
4398     wxString timeStr;
4399     if(startTime.IsValid() && endTime.IsValid())
4400     {
4401         wxTimeSpan span = endTime - startTime;
4402         return formatTimeDelta(span);
4403     } else {
4404         return _("N/A");
4405     }
4406 }
4407 
formatTimeDelta(wxLongLong secs)4408 wxString formatTimeDelta(wxLongLong secs)
4409 {
4410     wxString timeStr;
4411 
4412     wxTimeSpan span(0, 0, secs);
4413     return formatTimeDelta(span);
4414 }
4415 
FormatDistanceAdaptive(double distance)4416 wxString FormatDistanceAdaptive( double distance ) {
4417     wxString result;
4418     int unit = g_iDistanceFormat;
4419     double usrDistance = toUsrDistance( distance, unit );
4420     if( usrDistance < 0.1 &&  ( unit == DISTANCE_KM || unit == DISTANCE_MI || unit == DISTANCE_NMI ) ) {
4421         unit = ( unit == DISTANCE_MI ) ? DISTANCE_FT : DISTANCE_M;
4422         usrDistance = toUsrDistance( distance, unit );
4423     }
4424     wxString format;
4425     if( usrDistance < 5.0 ) {
4426         format = _T("%1.2f ");
4427     } else if( usrDistance < 100.0 ) {
4428         format = _T("%2.1f ");
4429     } else if( usrDistance < 1000.0 ) {
4430         format = _T("%3.0f ");
4431     } else {
4432         format = _T("%4.0f ");
4433     }
4434     result << wxString::Format(format, usrDistance ) << getUsrDistanceUnit( unit );
4435     return result;
4436 }
4437 
4438 /**************************************************************************/
4439 /*          Formats the coordinates to string                             */
4440 /**************************************************************************/
toSDMM(int NEflag,double a,bool hi_precision)4441 wxString toSDMM( int NEflag, double a, bool hi_precision )
4442 {
4443     wxString s;
4444     double mpy;
4445     short neg = 0;
4446     int d;
4447     long m;
4448     double ang = a;
4449     char c = 'N';
4450 
4451     if( a < 0.0 ) {
4452         a = -a;
4453         neg = 1;
4454     }
4455     d = (int) a;
4456     if( neg ) d = -d;
4457     if( NEflag ) {
4458         if( NEflag == 1 ) {
4459             c = 'N';
4460 
4461             if( neg ) {
4462                 d = -d;
4463                 c = 'S';
4464             }
4465         } else
4466             if( NEflag == 2 ) {
4467                 c = 'E';
4468 
4469                 if( neg ) {
4470                     d = -d;
4471                     c = 'W';
4472                 }
4473             }
4474     }
4475 
4476     switch( g_iSDMMFormat ){
4477         case 0:
4478             mpy = 600.0;
4479             if( hi_precision ) mpy = mpy * 1000;
4480 
4481             m = (long) wxRound( ( a - (double) d ) * mpy );
4482 
4483             if( !NEflag || NEflag < 1 || NEflag > 2 ) //Does it EVER happen?
4484                     {
4485                 if( hi_precision ) s.Printf( _T ( "%d\u00B0 %02ld.%04ld'" ), d, m / 10000, m % 10000 );
4486                 else
4487                     s.Printf( _T ( "%d\u00B0 %02ld.%01ld'" ), d, m / 10, m % 10 );
4488             } else {
4489                 if( hi_precision )
4490                     if (NEflag == 1)
4491                         s.Printf( _T ( "%02d\u00B0 %02ld.%04ld' %c" ), d, m / 10000, ( m % 10000 ), c );
4492                     else
4493                         s.Printf( _T ( "%03d\u00B0 %02ld.%04ld' %c" ), d, m / 10000, ( m % 10000 ), c );
4494                 else
4495                     if (NEflag == 1)
4496                         s.Printf( _T ( "%02d\u00B0 %02ld.%01ld' %c" ), d, m / 10, ( m % 10 ), c );
4497                     else
4498                         s.Printf( _T ( "%03d\u00B0 %02ld.%01ld' %c" ), d, m / 10, ( m % 10 ), c );
4499             }
4500             break;
4501         case 1:
4502             if( hi_precision ) s.Printf( _T ( "%03.6f" ), ang ); //cca 11 cm - the GPX precision is higher, but as we use hi_precision almost everywhere it would be a little too much....
4503             else
4504                 s.Printf( _T ( "%03.4f" ), ang ); //cca 11m
4505             break;
4506         case 2:
4507             m = (long) ( ( a - (double) d ) * 60 );
4508             mpy = 10.0;
4509             if( hi_precision ) mpy = mpy * 100;
4510             long sec = (long) ( ( a - (double) d - ( ( (double) m ) / 60 ) ) * 3600 * mpy );
4511 
4512             if( !NEflag || NEflag < 1 || NEflag > 2 ) //Does it EVER happen?
4513                     {
4514                 if( hi_precision ) s.Printf( _T ( "%d\u00B0 %ld'%ld.%ld\"" ), d, m, sec / 1000,
4515                         sec % 1000 );
4516                 else
4517                     s.Printf( _T ( "%d\u00B0 %ld'%ld.%ld\"" ), d, m, sec / 10, sec % 10 );
4518             } else {
4519                 if( hi_precision )
4520                     if (NEflag == 1)
4521                         s.Printf( _T ( "%02d\u00B0 %02ld' %02ld.%03ld\" %c" ), d, m, sec / 1000, sec % 1000, c );
4522                     else
4523                         s.Printf( _T ( "%03d\u00B0 %02ld' %02ld.%03ld\" %c" ), d, m, sec / 1000, sec % 1000, c );
4524                 else
4525                     if (NEflag == 1)
4526                         s.Printf( _T ( "%02d\u00B0 %02ld' %02ld.%ld\" %c" ), d, m, sec / 10, sec % 10, c );
4527                     else
4528                         s.Printf( _T ( "%03d\u00B0 %02ld' %02ld.%ld\" %c" ), d, m, sec / 10, sec % 10, c );
4529             }
4530             break;
4531     }
4532     return s;
4533 }
4534 
4535 /****************************************************************************/
4536 // Modified from the code posted by Andy Ross at
4537 //     http://www.mail-archive.com/flightgear-devel@flightgear.org/msg06702.html
4538 // Basically, it looks for a list of decimal numbers embedded in the
4539 // string and uses the first three as degree, minutes and seconds.  The
4540 // presence of a "S" or "W character indicates that the result is in a
4541 // hemisphere where the final answer must be negated.  Non-number
4542 // characters are treated as whitespace separating numbers.
4543 //
4544 // So there are lots of bogus strings you can feed it to get a bogus
4545 // answer, but that's not surprising.  It does, however, correctly parse
4546 // all the well-formed strings I can thing of to feed it.  I've tried all
4547 // the following:
4548 //
4549 // 37°54.204' N
4550 // N37 54 12
4551 // 37°54'12"
4552 // 37.9034
4553 // 122°18.621' W
4554 // 122w 18 37
4555 // -122.31035
4556 /****************************************************************************/
fromDMM(wxString sdms)4557 double fromDMM( wxString sdms )
4558 {
4559     wchar_t buf[64];
4560     char narrowbuf[64];
4561     int i, len, top = 0;
4562     double stk[32], sign = 1;
4563 
4564     //First round of string modifications to accomodate some known strange formats
4565     wxString replhelper;
4566     replhelper = wxString::FromUTF8( "´·" ); //UKHO PDFs
4567     sdms.Replace( replhelper, _T(".") );
4568     replhelper = wxString::FromUTF8( "\"·" ); //Don't know if used, but to make sure
4569     sdms.Replace( replhelper, _T(".") );
4570     replhelper = wxString::FromUTF8( "·" );
4571     sdms.Replace( replhelper, _T(".") );
4572 
4573     replhelper = wxString::FromUTF8( "s. š." ); //Another example: cs.wikipedia.org (someone was too active translating...)
4574     sdms.Replace( replhelper, _T("N") );
4575     replhelper = wxString::FromUTF8( "j. š." );
4576     sdms.Replace( replhelper, _T("S") );
4577     sdms.Replace( _T("v. d."), _T("E") );
4578     sdms.Replace( _T("z. d."), _T("W") );
4579 
4580     //If the string contains hemisphere specified by a letter, then '-' is for sure a separator...
4581     sdms.UpperCase();
4582     if( sdms.Contains( _T("N") ) || sdms.Contains( _T("S") ) || sdms.Contains( _T("E") )
4583             || sdms.Contains( _T("W") ) ) sdms.Replace( _T("-"), _T(" ") );
4584 
4585     wcsncpy( buf, sdms.wc_str( wxConvUTF8 ), 63 );
4586     buf[63] = 0;
4587     len = wxMin( wcslen( buf ), sizeof(narrowbuf)-1);;
4588 
4589     for( i = 0; i < len; i++ ) {
4590         wchar_t c = buf[i];
4591         if( ( c >= '0' && c <= '9' ) || c == '-' || c == '.' || c == '+' ) {
4592             narrowbuf[i] = c;
4593             continue; /* Digit characters are cool as is */
4594         }
4595         if( c == ',' ) {
4596             narrowbuf[i] = '.'; /* convert to decimal dot */
4597             continue;
4598         }
4599         if( ( c | 32 ) == 'w' || ( c | 32 ) == 's' ) sign = -1; /* These mean "negate" (note case insensitivity) */
4600         narrowbuf[i] = 0; /* Replace everything else with nuls */
4601     }
4602 
4603     /* Build a stack of doubles */
4604     stk[0] = stk[1] = stk[2] = 0;
4605     for( i = 0; i < len; i++ ) {
4606         while( i < len && narrowbuf[i] == 0 )
4607             i++;
4608         if( i != len ) {
4609             stk[top++] = atof( narrowbuf + i );
4610             i += strlen( narrowbuf + i );
4611         }
4612     }
4613 
4614     return sign * ( stk[0] + ( stk[1] + stk[2] / 60 ) / 60 );
4615 }
4616 
formatAngle(double angle)4617 wxString formatAngle(double angle)
4618 {
4619     wxString out;
4620     if( g_bShowMag && g_bShowTrue ) {
4621         out.Printf(wxT("%03.0f \u00B0T (%.0f \u00B0M)"), angle, gFrame->GetMag(angle));
4622     } else if( g_bShowTrue ) {
4623         out.Printf(wxT("%03.0f \u00B0T"), angle);
4624     } else {
4625         out.Printf(wxT("%03.0f \u00B0M"), gFrame->GetMag(angle));
4626     }
4627     return out;
4628 }
4629 
4630 /* render a rectangle at a given color and transparency */
AlphaBlending(ocpnDC & dc,int x,int y,int size_x,int size_y,float radius,wxColour color,unsigned char transparency)4631 void AlphaBlending( ocpnDC &dc, int x, int y, int size_x, int size_y, float radius, wxColour color,
4632         unsigned char transparency )
4633 {
4634     wxDC *pdc = dc.GetDC();
4635     if( pdc ) {
4636         //    Get wxImage of area of interest
4637         wxBitmap obm( size_x, size_y );
4638         wxMemoryDC mdc1;
4639         mdc1.SelectObject( obm );
4640         mdc1.Blit( 0, 0, size_x, size_y, pdc, x, y );
4641         mdc1.SelectObject( wxNullBitmap );
4642         wxImage oim = obm.ConvertToImage();
4643 
4644         //    Create destination image
4645         wxBitmap olbm( size_x, size_y );
4646         wxMemoryDC oldc( olbm );
4647         if(!oldc.IsOk())
4648             return;
4649 
4650         oldc.SetBackground( *wxBLACK_BRUSH );
4651         oldc.SetBrush( *wxWHITE_BRUSH );
4652         oldc.Clear();
4653 
4654         if( radius > 0.0 )
4655             oldc.DrawRoundedRectangle( 0, 0, size_x, size_y, radius );
4656 
4657         wxImage dest = olbm.ConvertToImage();
4658         unsigned char *dest_data = (unsigned char *) malloc(
4659                 size_x * size_y * 3 * sizeof(unsigned char) );
4660         unsigned char *bg = oim.GetData();
4661         unsigned char *box = dest.GetData();
4662         unsigned char *d = dest_data;
4663 
4664         //  Sometimes, on Windows, the destination image is corrupt...
4665         if(NULL == box)
4666         {
4667             free(d);
4668             return;
4669         }
4670         float alpha = 1.0 - (float)transparency / 255.0;
4671         int sb = size_x * size_y;
4672         for( int i = 0; i < sb; i++ ) {
4673             float a = alpha;
4674             if( *box == 0 && radius > 0.0 ) a = 1.0;
4675             int r = ( ( *bg++ ) * a ) + (1.0-a) * color.Red();
4676             *d++ = r; box++;
4677             int g = ( ( *bg++ ) * a ) + (1.0-a) * color.Green();
4678             *d++ = g; box++;
4679             int b = ( ( *bg++ ) * a ) + (1.0-a) * color.Blue();
4680             *d++ = b; box++;
4681         }
4682 
4683         dest.SetData( dest_data );
4684 
4685         //    Convert destination to bitmap and draw it
4686         wxBitmap dbm( dest );
4687         dc.DrawBitmap( dbm, x, y, false );
4688 
4689         // on MSW, the dc Bounding box is not updated on DrawBitmap() method.
4690         // Do it explicitely here for all platforms.
4691         dc.CalcBoundingBox( x, y );
4692         dc.CalcBoundingBox( x + size_x, y + size_y );
4693     } else {
4694 #ifdef ocpnUSE_GL
4695 #ifdef USE_ANDROID_GLES2
4696         glEnable( GL_BLEND );
4697 
4698         float radMod = wxMax(radius, 2.0);
4699         wxColour c(color.Red(), color.Green(), color.Blue(), transparency);
4700         dc.SetBrush(wxBrush(c));
4701         dc.SetPen(wxPen(c, 1));
4702         dc.DrawRoundedRectangle( x, y, size_x, size_y, radMod );
4703 
4704         glDisable( GL_BLEND );
4705 
4706 
4707 #else
4708         /* opengl version */
4709         glEnable( GL_BLEND );
4710 
4711         if(radius > 1.0f){
4712             wxColour c(color.Red(), color.Green(), color.Blue(), transparency);
4713             dc.SetBrush(wxBrush(c));
4714             dc.DrawRoundedRectangle( x, y, size_x, size_y, radius );
4715         }
4716         else {
4717             glColor4ub( color.Red(), color.Green(), color.Blue(), transparency );
4718             glBegin( GL_QUADS );
4719             glVertex2i( x, y );
4720             glVertex2i( x + size_x, y );
4721             glVertex2i( x + size_x, y + size_y );
4722             glVertex2i( x, y + size_y );
4723             glEnd();
4724         }
4725         glDisable( GL_BLEND );
4726 #endif
4727 #endif
4728     }
4729 }
4730 
4731 // RFC4122 version 4 compliant random UUIDs generator.
GetUUID(void)4732 wxString GpxDocument::GetUUID(void)
4733 {
4734     wxString str;
4735     struct {
4736         int time_low;
4737         int time_mid;
4738         int time_hi_and_version;
4739         int clock_seq_hi_and_rsv;
4740         int clock_seq_low;
4741         int node_hi;
4742         int node_low;
4743     } uuid;
4744 
4745     uuid.time_low = GetRandomNumber(0, 2147483647);//FIXME: the max should be set to something like MAXINT32, but it doesn't compile un gcc...
4746     uuid.time_mid = GetRandomNumber(0, 65535);
4747     uuid.time_hi_and_version = GetRandomNumber(0, 65535);
4748     uuid.clock_seq_hi_and_rsv = GetRandomNumber(0, 255);
4749     uuid.clock_seq_low = GetRandomNumber(0, 255);
4750     uuid.node_hi = GetRandomNumber(0, 65535);
4751     uuid.node_low = GetRandomNumber(0, 2147483647);
4752 
4753     /* Set the two most significant bits (bits 6 and 7) of the
4754      * clock_seq_hi_and_rsv to zero and one, respectively. */
4755     uuid.clock_seq_hi_and_rsv = (uuid.clock_seq_hi_and_rsv & 0x3F) | 0x80;
4756 
4757     /* Set the four most significant bits (bits 12 through 15) of the
4758      * time_hi_and_version field to 4 */
4759     uuid.time_hi_and_version = (uuid.time_hi_and_version & 0x0fff) | 0x4000;
4760 
4761     str.Printf(_T("%08x-%04x-%04x-%02x%02x-%04x%08x"),
4762                uuid.time_low,
4763                uuid.time_mid,
4764                uuid.time_hi_and_version,
4765                uuid.clock_seq_hi_and_rsv,
4766                uuid.clock_seq_low,
4767                uuid.node_hi,
4768                uuid.node_low);
4769 
4770     return str;
4771 }
4772 
GetRandomNumber(int range_min,int range_max)4773 int GpxDocument::GetRandomNumber(int range_min, int range_max)
4774 {
4775     long u = (long)wxRound(((double)rand() / ((double)(RAND_MAX) + 1) * (range_max - range_min)) + range_min);
4776     return (int)u;
4777 }
4778 
SeedRandom()4779 void GpxDocument::SeedRandom()
4780 {
4781     /* Fill with random. Miliseconds hopefully good enough for our usage, reading /dev/random would be much better on linux and system guid function on Windows as well */
4782     wxDateTime x = wxDateTime::UNow();
4783     long seed = x.GetMillisecond();
4784     seed *= x.GetTicks();
4785     srand(seed);
4786 }
4787 
DimeControl(wxWindow * ctrl)4788 void DimeControl( wxWindow* ctrl )
4789 {
4790 #ifdef __WXOSX__
4791     // On macOS 10.14+, we use the native colours in both light mode and dark mode, and do not need to do anything else.
4792     // Dark mode is toggled at the application level in `SetAndApplyColorScheme`, and is also respected if it is enabled system-wide.
4793     if (wxPlatformInfo::Get().CheckOSVersion(10, 14)) {
4794         return;
4795     }
4796 #endif
4797 #ifdef __WXQT__
4798     return; // this is seriously broken on wxqt
4799 #endif
4800 
4801     if( NULL == ctrl ) return;
4802 
4803     wxColour col, window_back_color, gridline, uitext, udkrd, ctrl_back_color, text_color;
4804     col = GetGlobalColor( _T("DILG0") );       // Dialog Background white
4805     window_back_color = GetGlobalColor( _T("DILG1") );      // Dialog Background
4806     ctrl_back_color = GetGlobalColor( _T("DILG1") );      // Control Background
4807     text_color = GetGlobalColor( _T("DILG3") );      // Text
4808     uitext = GetGlobalColor( _T("UITX1") );    // Menu Text, derived from UINFF
4809     udkrd = GetGlobalColor( _T("UDKRD") );
4810     gridline = GetGlobalColor( _T("GREY2") );
4811 
4812     DimeControl( ctrl, col, window_back_color, ctrl_back_color, text_color, uitext, udkrd, gridline );
4813 }
4814 
DimeControl(wxWindow * ctrl,wxColour col,wxColour window_back_color,wxColour ctrl_back_color,wxColour text_color,wxColour uitext,wxColour udkrd,wxColour gridline)4815 void DimeControl( wxWindow* ctrl, wxColour col, wxColour window_back_color, wxColour ctrl_back_color,
4816                   wxColour text_color, wxColour uitext, wxColour udkrd, wxColour gridline )
4817 {
4818 #ifdef __WXOSX__
4819     // On macOS 10.14+, we use the native colours in both light mode and dark mode, and do not need to do anything else.
4820     // Dark mode is toggled at the application level in `SetAndApplyColorScheme`, and is also respected if it is enabled system-wide.
4821     if (wxPlatformInfo::Get().CheckOSVersion(10, 14)) {
4822         return;
4823     }
4824 #endif
4825 
4826     ColorScheme cs = global_color_scheme;
4827 
4828     // Are we in dusk or night mode? (Used below in several places.)
4829     bool darkMode = ( cs == GLOBAL_COLOR_SCHEME_DUSK || cs == GLOBAL_COLOR_SCHEME_NIGHT );
4830 
4831     static int depth = 0; // recursion count
4832     if ( depth == 0 ) {   // only for the window root, not for every child
4833         // If the color scheme is DAY or RGB, use the default platform native colour for backgrounds
4834         if ( !darkMode ) {
4835             window_back_color = wxNullColour;
4836             col = wxSystemSettings::GetColour(wxSYS_COLOUR_LISTBOX);
4837             uitext = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT);
4838         }
4839 
4840         ctrl->SetBackgroundColour( window_back_color );
4841 
4842 #if defined(__WXOSX__) && defined(OCPN_USE_DARKMODE)
4843         // On macOS 10.12, enable dark mode at the window level if appropriate.
4844         // This will enable dark window decorations but will not darken the rest of the UI.
4845         if ( wxPlatformInfo::Get().CheckOSVersion(10, 12) ) {
4846             setWindowLevelDarkMode(ctrl->MacGetTopLevelWindowRef(), darkMode);
4847         }
4848         // Force consistent coloured UI text; dark in light mode and light in dark mode.
4849         uitext = darkMode ? wxColor(228,228,228) : wxColor(0,0,0);
4850 #endif
4851     }
4852 
4853     wxWindowList kids = ctrl->GetChildren();
4854     for( unsigned int i = 0; i < kids.GetCount(); i++ ) {
4855         wxWindowListNode *node = kids.Item(i);
4856         wxWindow *win = node->GetData();
4857 
4858         if (
4859             win->IsKindOf(CLASSINFO(wxListBox))
4860             || win->IsKindOf(CLASSINFO(wxListCtrl))
4861             || win->IsKindOf(CLASSINFO(wxTextCtrl))
4862 #ifndef __OCPN__ANDROID__
4863             || win->IsKindOf(CLASSINFO(wxTimePickerCtrl))
4864 #endif
4865         ) {
4866             win->SetBackgroundColour(col);
4867         }
4868         else if (
4869             win->IsKindOf(CLASSINFO(wxStaticText))
4870             || win->IsKindOf(CLASSINFO(wxCheckBox))
4871             || win->IsKindOf(CLASSINFO(wxRadioButton))
4872         ) {
4873             win->SetForegroundColour(uitext);
4874         }
4875 
4876 #ifndef __WXOSX__
4877         // On macOS most controls can't be styled, and trying to do so only creates weird coloured boxes around them.
4878         // Fortunately, however, many of them inherit a colour or tint from the background of their parent.
4879 
4880         else if (
4881             win->IsKindOf(CLASSINFO(wxBitmapComboBox))
4882             || win->IsKindOf(CLASSINFO(wxChoice))
4883             || win->IsKindOf(CLASSINFO(wxComboBox))
4884             || win->IsKindOf(CLASSINFO(wxTreeCtrl))
4885         ) {
4886             win->SetBackgroundColour(col);
4887         }
4888 
4889         else if (
4890             win->IsKindOf(CLASSINFO(wxScrolledWindow))
4891             || win->IsKindOf(CLASSINFO(wxGenericDirCtrl))
4892             || win->IsKindOf(CLASSINFO(wxListbook))
4893             || win->IsKindOf(CLASSINFO(wxButton))
4894             || win->IsKindOf(CLASSINFO(wxToggleButton))
4895         ) {
4896             win->SetBackgroundColour( window_back_color );
4897         }
4898 
4899         else if ( win->IsKindOf(CLASSINFO(wxNotebook)) ) {
4900             ((wxNotebook*) win)->SetBackgroundColour(window_back_color);
4901             ((wxNotebook*) win)->SetForegroundColour(text_color);
4902         }
4903 #endif
4904 
4905         else if( win->IsKindOf( CLASSINFO(wxHtmlWindow) ) ) {
4906             if( cs != GLOBAL_COLOR_SCHEME_DAY && cs != GLOBAL_COLOR_SCHEME_RGB )
4907                 ( (wxPanel*) win )->SetBackgroundColour( ctrl_back_color );
4908             else
4909                 ( (wxPanel*) win )->SetBackgroundColour( wxNullColour );
4910         }
4911 
4912         else if( win->IsKindOf( CLASSINFO(wxGrid) ) ) {
4913             ( (wxGrid*) win )->SetDefaultCellBackgroundColour( window_back_color );
4914             ( (wxGrid*) win )->SetDefaultCellTextColour( uitext );
4915             ( (wxGrid*) win )->SetLabelBackgroundColour( col );
4916             ( (wxGrid*) win )->SetLabelTextColour( uitext );
4917 #if !wxCHECK_VERSION(3,0,0)
4918             ( (wxGrid*) win )->SetDividerPen( wxPen( col ) );
4919 #endif
4920             ( (wxGrid*) win )->SetGridLineColour( gridline );
4921         }
4922 
4923         if( win->GetChildren().GetCount() > 0 ) {
4924             depth++;
4925             wxWindow * w = win;
4926             DimeControl( w, col, window_back_color, ctrl_back_color, text_color, uitext, udkrd, gridline );
4927             depth--;
4928         }
4929     }
4930 }
4931 
4932 
4933