OpenCPN Partial API docs
Loading...
Searching...
No Matches
navutil.cpp
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#include <stdlib.h>
34#include <time.h>
35#include <locale>
36#include <list>
37
38#ifndef WX_PRECOMP
39#include <wx/wx.h>
40#endif // precompiled headers
41
42#include <wx/bmpcbox.h>
43#include <wx/dir.h>
44#include <wx/filename.h>
45#include <wx/graphics.h>
46#include <wx/image.h>
47#include <wx/listbook.h>
48#include <wx/listimpl.cpp>
49#include <wx/progdlg.h>
50#include <wx/sstream.h>
51#include <wx/tglbtn.h>
52#include <wx/timectrl.h>
53#include <wx/tokenzr.h>
54
55#include "model/ais_decoder.h"
57#include "model/cmdline.h"
58#include "model/config_vars.h"
59#include "model/conn_params.h"
60#include "model/cutil.h"
61#include "model/geodesic.h"
62#include "model/georef.h"
63#include "model/idents.h"
64#include "model/multiplexer.h"
65#include "model/nav_object_database.h"
66#include "model/navutil_base.h"
67#include "model/own_ship.h"
68#include "model/plugin_comm.h"
69#include "model/route.h"
70#include "model/routeman.h"
71#include "model/select.h"
72#include "model/track.h"
73
74#include "ais.h"
75#include "CanvasConfig.h"
76#include "chartbase.h"
77#include "chartdb.h"
78#include "chcanv.h"
79#include "cm93.h"
80#include "config.h"
81#include "ConfigMgr.h"
82#include "displays.h"
83#include "dychart.h"
84#include "FontMgr.h"
85#include "Layer.h"
86#include "navutil.h"
87#include "nmea0183.h"
88#include "observable_globvar.h"
89#include "ocpndc.h"
90#include "ocpn_frame.h"
91#include "ocpn_plugin.h"
92#include "OCPNPlatform.h"
93#include "OCPN_Sound.h"
94#include "s52plib.h"
95#include "s52utils.h"
96#include "snd_config.h"
97#include "styles.h"
98
99#ifdef ocpnUSE_GL
100#include "glChartCanvas.h"
101#endif
102
103#ifdef __ANDROID__
104#include "androidUTIL.h"
105#endif
106
107// Statics
108
109extern OCPNPlatform *g_Platform;
110extern MyFrame *gFrame;
111
112extern double g_ChartNotRenderScaleFactor;
113extern int g_restore_stackindex;
114extern int g_restore_dbindex;
115extern RouteList *pRouteList;
116extern std::vector<Track *> g_TrackList;
117extern LayerList *pLayerList;
118extern MyConfig *pConfig;
119extern double vLat, vLon;
120extern double kLat, kLon;
121extern ColorScheme global_color_scheme;
122extern int g_nbrightness;
123extern bool g_bShowStatusBar;
124extern bool g_bUIexpert;
125extern bool g_bFullscreen;
126
127extern wxString g_SENCPrefix;
128extern wxString g_UserPresLibData;
129
130extern wxString *pInit_Chart_Dir;
131extern wxString gWorldMapLocation;
132extern wxString gWorldShapefileLocation;
133
134extern bool s_bSetSystemTime;
135extern bool g_bDisplayGrid; // Flag indicating if grid is to be displayed
136extern bool g_bPlayShipsBells;
137extern int g_iSoundDeviceIndex;
138extern bool g_bFullscreenToolbar;
139extern bool g_bShowLayers;
140extern bool g_bTransparentToolbar;
141extern bool g_bPermanentMOBIcon;
142
143extern bool g_bShowDepthUnits;
144extern bool g_bAutoAnchorMark;
145extern bool g_bskew_comp;
146extern bool g_bopengl;
147extern bool g_bSoftwareGL;
148extern bool g_bsmoothpanzoom;
149extern bool g_fog_overzoom;
150extern double g_overzoom_emphasis_base;
151extern bool g_oz_vector_scale;
152extern double g_plus_minus_zoom_factor;
153extern bool g_bShowOutlines;
154extern bool g_bShowActiveRouteHighway;
155extern bool g_bShowRouteTotal;
156extern int g_nAWDefault;
157extern int g_nAWMax;
158extern bool g_btenhertz;
159extern bool g_declutter_anchorage;
160
161extern int g_nframewin_x;
162extern int g_nframewin_y;
163extern int g_nframewin_posx;
164extern int g_nframewin_posy;
165extern bool g_bframemax;
166
167extern wxString g_VisibleLayers;
168extern wxString g_InvisibleLayers;
169extern wxString g_VisiNameinLayers;
170extern wxString g_InVisiNameinLayers;
171
172extern wxArrayString *pMessageOnceArray;
173
174// LIVE ETA OPTION
175extern bool g_bShowLiveETA;
176extern double g_defaultBoatSpeed;
177extern double g_defaultBoatSpeedUserUnit;
178
179extern bool g_bUseOnlyConfirmedAISName;
180extern int g_ScaledNumWeightSOG;
181
182extern int g_S57_dialog_sx, g_S57_dialog_sy;
183int g_S57_extradialog_sx, g_S57_extradialog_sy;
184
185extern int g_iNavAidRadarRingsNumberVisible;
186extern bool g_bNavAidRadarRingsShown;
187extern float g_fNavAidRadarRingsStep;
188extern int g_pNavAidRadarRingsStepUnits;
189extern bool g_bWayPointPreventDragging;
190extern bool g_bConfirmObjectDelete;
191extern wxColour g_colourOwnshipRangeRingsColour;
192
193extern bool g_bEnableZoomToCursor;
194extern wxString g_toolbarConfig;
195extern double g_TrackIntervalSeconds;
196
197extern int g_nCacheLimit;
198extern int g_memCacheLimit;
199
200extern bool g_bGDAL_Debug;
201extern bool g_bDebugCM93;
202extern bool g_bDebugS57;
203
204extern double g_ownship_predictor_minutes;
205extern int g_cog_predictor_style;
206extern wxString g_cog_predictor_color;
207extern int g_cog_predictor_endmarker;
208extern int g_cog_predictor_width;
209extern int g_ownship_HDTpredictor_style;
210extern wxString g_ownship_HDTpredictor_color;
211extern int g_ownship_HDTpredictor_endmarker;
212extern int g_ownship_HDTpredictor_width;
213extern double g_ownship_HDTpredictor_miles;
214
215extern bool g_own_ship_sog_cog_calc;
216extern int g_own_ship_sog_cog_calc_damp_sec;
217
218extern bool g_bShowMenuBar;
219extern bool g_bShowCompassWin;
220
221extern s52plib *ps52plib;
222
223extern int g_cm93_zoom_factor;
224extern bool g_b_legacy_input_filter_behaviour;
225extern bool g_bShowDetailSlider;
226extern int g_detailslider_dialog_x, g_detailslider_dialog_y;
227
228extern bool g_bUseGreenShip;
229
230extern int g_OwnShipmmsi;
231extern int g_OwnShipIconType;
232extern double g_n_ownship_length_meters;
233extern double g_n_ownship_beam_meters;
234extern double g_n_gps_antenna_offset_y;
235extern double g_n_gps_antenna_offset_x;
236extern int g_n_ownship_min_mm;
237extern int g_maxzoomin;
238
239extern bool g_bShowShipToActive;
240extern int g_shipToActiveStyle;
241extern int g_shipToActiveColor;
242
243extern bool g_bPreserveScaleOnX;
244extern bool g_bsimplifiedScalebar;
245
246extern bool g_bUseGLL;
247
248extern wxString g_locale;
249extern wxString g_localeOverride;
250
251extern bool g_bCourseUp;
252extern bool g_bLookAhead;
253extern int g_COGAvgSec;
254extern bool g_bShowChartBar;
255
256extern int g_MemFootMB;
257
258extern wxString g_AW1GUID;
259extern wxString g_AW2GUID;
260extern int g_BSBImgDebug;
261
262extern int n_NavMessageShown;
263extern wxString g_config_version_string;
264
265extern wxString g_CmdSoundString;
266
267extern bool g_bDebugGPSD;
268
269int g_navobjbackups;
270
271extern bool g_bQuiltEnable;
272extern bool g_bFullScreenQuilt;
273extern bool g_bQuiltStart;
274
275extern int g_SkewCompUpdatePeriod;
276
277extern int g_maintoolbar_x;
278extern int g_maintoolbar_y;
279extern long g_maintoolbar_orient;
280
281extern int g_lastClientRectx;
282extern int g_lastClientRecty;
283extern int g_lastClientRectw;
284extern int g_lastClientRecth;
285
286extern bool g_bHighliteTracks;
287extern int g_cog_predictor_width;
288extern int g_ais_cog_predictor_width;
289
290extern wxColour g_colourTrackLineColour;
291extern wxString g_default_wp_icon;
292
293extern ChartGroupArray *g_pGroupArray;
294
295extern bool g_bDebugOGL;
296extern int g_tcwin_scale;
297extern wxString g_uploadConnection;
298
299extern ocpnStyle::StyleManager *g_StyleManager;
300extern std::vector<std::string> TideCurrentDataSet;
301extern wxString g_TCData_Dir;
302
303extern bool g_bresponsive;
304
305extern bool g_bGLexpert;
306
307extern int g_SENC_LOD_pixels;
308extern ArrayOfMmsiProperties g_MMSI_Props_Array;
309
310extern int g_chart_zoom_modifier_raster;
311extern int g_chart_zoom_modifier_vector;
312
313extern bool g_bShowTrackPointTime;
314
315extern bool g_bAdvanceRouteWaypointOnArrivalOnly;
316extern double g_display_size_mm;
317extern std::vector<size_t> g_config_display_size_mm;
318extern bool g_config_display_size_manual;
319
320extern bool g_benable_rotate;
321extern bool g_bEmailCrashReport;
322
323extern int g_default_font_size;
324extern wxString g_default_font_facename;
325
326extern bool g_bAutoHideToolbar;
327extern int g_nAutoHideToolbar;
328extern int g_GUIScaleFactor;
329extern int g_ChartScaleFactor;
330extern float g_MarkScaleFactorExp;
331
332extern int g_ShipScaleFactor;
333extern float g_ShipScaleFactorExp;
334extern int g_ENCSoundingScaleFactor;
335extern int g_ENCTextScaleFactor;
336
337extern int g_iENCToolbarPosX;
338extern int g_iENCToolbarPosY;
339extern bool g_bRollover;
340
341extern bool g_bSpaceDropMark;
342
343extern bool g_bShowTide;
344extern bool g_bShowCurrent;
345
346extern wxString g_uiStyle;
347extern bool g_btrackContinuous;
348extern bool g_useMUI;
349
350int g_nCPUCount;
351
352extern unsigned int g_canvasConfig;
353extern wxString g_lastAppliedTemplateGUID;
354
355extern int g_route_prop_x, g_route_prop_y;
356extern int g_route_prop_sx, g_route_prop_sy;
357extern int g_AndroidVersionCode;
358
359extern wxString g_ObjQFileExt;
360
361wxString g_gpx_path;
362bool g_bLayersLoaded;
363bool g_bShowMuiZoomButtons = true;
364
365double g_mouse_zoom_sensitivity;
366int g_mouse_zoom_sensitivity_ui;
367
368#ifdef ocpnUSE_GL
369extern ocpnGLOptions g_GLOptions;
370#endif
371
372#if !defined(NAN)
373static const long long lNaN = 0xfff8000000000000;
374#define NAN (*(double *)&lNaN)
375#endif
376
377// Layer helper function
378
379wxString GetLayerName(int id) {
380 wxString name(_T("unknown layer"));
381 if (id <= 0) return (name);
382 LayerList::iterator it;
383 int index = 0;
384 for (it = (*pLayerList).begin(); it != (*pLayerList).end(); ++it, ++index) {
385 Layer *lay = (Layer *)(*it);
386 if (lay->m_LayerID == id) return (lay->m_LayerName);
387 }
388 return (name);
389}
390
391// Helper conditional file name dir slash
392void appendOSDirSlash(wxString *pString);
393
394//-----------------------------------------------------------------------------
395// MyConfig Implementation
396//-----------------------------------------------------------------------------
397//
398
399MyConfig::MyConfig(const wxString &LocalFileName)
400 : wxFileConfig(_T (""), _T (""), LocalFileName, _T (""),
401 wxCONFIG_USE_LOCAL_FILE) {}
402
403MyConfig::~MyConfig() {}
404
405int MyConfig::LoadMyConfig() {
406 int display_width, display_height;
407 display_width = g_monitor_info[g_current_monitor].width;
408 display_height = g_monitor_info[g_current_monitor].height;
409
410 // Set up any defaults not set elsewhere
411 g_useMUI = true;
412 g_TalkerIdText = _T("EC");
413 g_maxWPNameLength = 6;
414 g_NMEAAPBPrecision = 3;
415
416#ifdef ocpnUSE_GL
417 g_GLOptions.m_bUseAcceleratedPanning = true;
418 g_GLOptions.m_GLPolygonSmoothing = true;
419 g_GLOptions.m_GLLineSmoothing = true;
420 g_GLOptions.m_iTextureDimension = 512;
421 g_GLOptions.m_iTextureMemorySize = 128;
422 if (!g_bGLexpert) {
423 g_GLOptions.m_iTextureMemorySize =
424 wxMax(128, g_GLOptions.m_iTextureMemorySize);
425 g_GLOptions.m_bTextureCompressionCaching =
426 g_GLOptions.m_bTextureCompression;
427 }
428#endif
429
430 g_maintoolbar_orient = wxTB_HORIZONTAL;
431 g_iENCToolbarPosX = -1;
432 g_iENCToolbarPosY = -1;
433 g_restore_dbindex = -1;
434 g_ChartNotRenderScaleFactor = 1.5;
435 g_detailslider_dialog_x = 200L;
436 g_detailslider_dialog_y = 200L;
437 g_SENC_LOD_pixels = 2;
438 g_SkewCompUpdatePeriod = 10;
439
440 g_bShowStatusBar = 1;
441 g_bShowCompassWin = 1;
442 g_iSoundDeviceIndex = -1;
443 g_bFullscreenToolbar = 1;
444 g_bTransparentToolbar = 0;
445 g_bShowLayers = 1;
446 g_bShowDepthUnits = 1;
447 g_bShowActiveRouteHighway = 1;
448 g_bShowChartBar = 1;
449 g_defaultBoatSpeed = 6.0;
450 g_ownship_predictor_minutes = 5;
451 g_cog_predictor_style = 105;
452 g_cog_predictor_color = _T("rgb(255,0,0)" );
453 g_cog_predictor_endmarker = 1;
454 g_ownship_HDTpredictor_style = 105;
455 g_ownship_HDTpredictor_color = _T("rgb(255,0,0)" );
456 g_ownship_HDTpredictor_endmarker = 1;
457 g_ownship_HDTpredictor_width = 0;
458 g_cog_predictor_width = 3;
459 g_ownship_HDTpredictor_miles = 1;
460 g_n_ownship_min_mm = 2;
461 g_own_ship_sog_cog_calc_damp_sec = 1;
462 g_bFullScreenQuilt = 1;
463 g_track_rotate_time_type = TIME_TYPE_COMPUTER;
464 g_bHighliteTracks = 1;
465 g_bPreserveScaleOnX = 1;
466 g_navobjbackups = 5;
467 g_benableAISNameCache = true;
468 g_n_arrival_circle_radius = 0.05;
469 g_plus_minus_zoom_factor = 2.0;
470 g_mouse_zoom_sensitivity = 1.5;
471 g_datetime_format = "UTC";
472
473 g_AISShowTracks_Mins = 20;
474 g_AISShowTracks_Limit = 300.0;
475 g_ShowScaled_Num = 10;
476 g_ScaledNumWeightSOG = 50;
477 g_ScaledNumWeightCPA = 60;
478 g_ScaledNumWeightTCPA = 25;
479 g_ScaledSizeMinimal = 50;
480 g_ScaledNumWeightRange = 75;
481 g_ScaledNumWeightSizeOfT = 25;
482 g_Show_Target_Name_Scale = 250000;
483 g_bWplUsePosition = 0;
484 g_WplAction = 0;
485 g_ais_cog_predictor_width = 3;
486 g_ais_alert_dialog_sx = 200;
487 g_ais_alert_dialog_sy = 200;
488 g_ais_alert_dialog_x = 200;
489 g_ais_alert_dialog_y = 200;
490 g_ais_query_dialog_x = 200;
491 g_ais_query_dialog_y = 200;
492 g_AisTargetList_range = 40;
493 g_AisTargetList_sortColumn = 2; // Column #2 is MMSI
494 g_S57_dialog_sx = 400;
495 g_S57_dialog_sy = 400;
496 g_S57_extradialog_sx = 400;
497 g_S57_extradialog_sy = 400;
498
499 // Reasonable starting point
500 vLat = START_LAT; // display viewpoint
501 vLon = START_LON;
502 gLat = START_LAT; // GPS position, as default
503 gLon = START_LON;
504 g_maxzoomin = 800;
505
506 g_iNavAidRadarRingsNumberVisible = 0;
507 g_bNavAidRadarRingsShown = false;
508 g_fNavAidRadarRingsStep = 1.0;
509 g_pNavAidRadarRingsStepUnits = 0;
510 g_colourOwnshipRangeRingsColour = *wxRED;
511 g_iWaypointRangeRingsNumber = 0;
512 g_fWaypointRangeRingsStep = 1.0;
513 g_iWaypointRangeRingsStepUnits = 0;
514 g_colourWaypointRangeRingsColour = wxColour(*wxRED);
515 g_bConfirmObjectDelete = true;
516
517 g_TrackIntervalSeconds = 60.0;
518 g_TrackDeltaDistance = 0.10;
519 g_route_line_width = 2;
520 g_track_line_width = 2;
521 g_colourTrackLineColour = wxColour(243, 229, 47); // Yellow
522
523 g_tcwin_scale = 100;
524 g_default_wp_icon = _T("triangle");
525 g_default_routepoint_icon = _T("diamond");
526
527 g_nAWDefault = 50;
528 g_nAWMax = 1852;
529 g_ObjQFileExt = _T("txt,rtf,png,html,gif,tif,jpg");
530
531 // Load the raw value, with no defaults, and no processing
532 int ret_Val = LoadMyConfigRaw();
533
534 // Perform any required post processing and validation
535 if (!ret_Val) {
536 g_ChartScaleFactorExp =
537 g_Platform->GetChartScaleFactorExp(g_ChartScaleFactor);
538 g_ShipScaleFactorExp =
539 g_Platform->GetChartScaleFactorExp(g_ShipScaleFactor);
540 g_MarkScaleFactorExp =
541 g_Platform->GetMarkScaleFactorExp(g_ChartScaleFactor);
542
543 g_COGFilterSec = wxMin(g_COGFilterSec, MAX_COGSOG_FILTER_SECONDS);
544 g_COGFilterSec = wxMax(g_COGFilterSec, 1);
545 g_SOGFilterSec = g_COGFilterSec;
546
547 if (!g_bShowTrue && !g_bShowMag) g_bShowTrue = true;
548 g_COGAvgSec =
549 wxMin(g_COGAvgSec, MAX_COG_AVERAGE_SECONDS); // Bound the array size
550
551 if (g_bInlandEcdis) g_bLookAhead = 1;
552
553 if (g_bdisable_opengl) g_bopengl = false;
554
555#ifdef ocpnUSE_GL
556 if (!g_bGLexpert) {
557 g_GLOptions.m_iTextureMemorySize =
558 wxMax(128, g_GLOptions.m_iTextureMemorySize);
559 g_GLOptions.m_bTextureCompressionCaching =
560 g_GLOptions.m_bTextureCompression;
561 }
562#endif
563
564 g_chart_zoom_modifier_raster = wxMin(g_chart_zoom_modifier_raster, 5);
565 g_chart_zoom_modifier_raster = wxMax(g_chart_zoom_modifier_raster, -5);
566 g_chart_zoom_modifier_vector = wxMin(g_chart_zoom_modifier_vector, 5);
567 g_chart_zoom_modifier_vector = wxMax(g_chart_zoom_modifier_vector, -5);
568 g_cm93_zoom_factor = wxMin(g_cm93_zoom_factor, CM93_ZOOM_FACTOR_MAX_RANGE);
569 g_cm93_zoom_factor =
570 wxMax(g_cm93_zoom_factor, (-CM93_ZOOM_FACTOR_MAX_RANGE));
571
572 if ((g_detailslider_dialog_x < 0) ||
573 (g_detailslider_dialog_x > display_width))
574 g_detailslider_dialog_x = 5;
575 if ((g_detailslider_dialog_y < 0) ||
576 (g_detailslider_dialog_y > display_height))
577 g_detailslider_dialog_y = 5;
578
579 g_defaultBoatSpeedUserUnit = toUsrSpeed(g_defaultBoatSpeed, -1);
580 g_n_ownship_min_mm = wxMax(g_n_ownship_min_mm, 2);
581
582 if (g_navobjbackups > 99) g_navobjbackups = 99;
583 if (g_navobjbackups < 0) g_navobjbackups = 0;
584 g_n_arrival_circle_radius = wxClip(g_n_arrival_circle_radius, 0.001, 0.6);
585
586 g_selection_radius_mm = wxMax(g_selection_radius_mm, 0.5);
587 g_selection_radius_touch_mm = wxMax(g_selection_radius_touch_mm, 1.0);
588
589 g_Show_Target_Name_Scale = wxMax(5000, g_Show_Target_Name_Scale);
590
591 if ((g_ais_alert_dialog_x < 0) || (g_ais_alert_dialog_x > display_width))
592 g_ais_alert_dialog_x = 5;
593 if ((g_ais_alert_dialog_y < 0) || (g_ais_alert_dialog_y > display_height))
594 g_ais_alert_dialog_y = 5;
595 if ((g_ais_query_dialog_x < 0) || (g_ais_query_dialog_x > display_width))
596 g_ais_query_dialog_x = 5;
597 if ((g_ais_query_dialog_y < 0) || (g_ais_query_dialog_y > display_height))
598 g_ais_query_dialog_y = 5;
599
600 SwitchInlandEcdisMode(g_bInlandEcdis);
601 if (g_bInlandEcdis)
602 global_color_scheme =
603 GLOBAL_COLOR_SCHEME_DUSK; // startup in duskmode if inlandEcdis
604
605 // Multicanvas Settings
606 LoadCanvasConfigs();
607 }
608
609 return ret_Val;
610}
611
612int MyConfig::LoadMyConfigRaw(bool bAsTemplate) {
613 int read_int;
614 wxString val;
615
616 int display_width, display_height;
617 display_width = g_monitor_info[g_current_monitor].width;
618 display_height = g_monitor_info[g_current_monitor].height;
619
620 // Global options and settings
621 SetPath(_T ( "/Settings" ));
622 Read("ActiveRoute", &g_active_route);
623 Read("PersistActiveRoute", &g_persist_active_route);
624 Read(_T ( "LastAppliedTemplate" ), &g_lastAppliedTemplateGUID);
625 Read(_T ( "CompatOS" ), &g_compatOS);
626 Read(_T ( "CompatOsVersion" ), &g_compatOsVersion);
627
628 // Some undocumented values
629 Read(_T ( "ConfigVersionString" ), &g_config_version_string);
630 Read(_T("CmdSoundString"), &g_CmdSoundString, wxString(OCPN_SOUND_CMD));
631 if (wxIsEmpty(g_CmdSoundString)) g_CmdSoundString = wxString(OCPN_SOUND_CMD);
632 Read(_T ( "NavMessageShown" ), &n_NavMessageShown);
633
634 Read(_T ( "AndroidVersionCode" ), &g_AndroidVersionCode);
635
636 Read(_T ( "UIexpert" ), &g_bUIexpert);
637
638 Read(_T ( "UIStyle" ), &g_uiStyle);
639
640 Read(_T ( "NCacheLimit" ), &g_nCacheLimit);
641
642 Read(_T ( "InlandEcdis" ),
643 &g_bInlandEcdis); // First read if in iENC mode as this will override
644 // some config settings
645
646 Read(_T( "SpaceDropMark" ), &g_bSpaceDropMark);
647
648 int mem_limit = 0;
649 Read(_T ( "MEMCacheLimit" ), &mem_limit);
650 if (mem_limit > 0)
651 g_memCacheLimit = mem_limit * 1024; // convert from MBytes to kBytes
652
653 Read(_T ( "UseModernUI5" ), &g_useMUI);
654
655 Read(_T( "NCPUCount" ), &g_nCPUCount);
656
657 Read(_T ( "DebugGDAL" ), &g_bGDAL_Debug);
658 Read(_T ( "DebugNMEA" ), &g_nNMEADebug);
659 Read(_T ( "AnchorWatchDefault" ), &g_nAWDefault);
660 Read(_T ( "AnchorWatchMax" ), &g_nAWMax);
661 Read(_T ( "GPSDogTimeout" ), &gps_watchdog_timeout_ticks);
662 Read(_T ( "DebugCM93" ), &g_bDebugCM93);
663 Read(_T ( "DebugS57" ),
664 &g_bDebugS57); // Show LUP and Feature info in object query
665 Read(_T ( "DebugBSBImg" ), &g_BSBImgDebug);
666 Read(_T ( "DebugGPSD" ), &g_bDebugGPSD);
667 Read(_T ( "MaxZoomScale" ), &g_maxzoomin);
668 g_maxzoomin = wxMax(g_maxzoomin, 50);
669
670 Read(_T ( "DefaultFontSize"), &g_default_font_size);
671 Read(_T ( "DefaultFontFacename"), &g_default_font_facename);
672
673 Read(_T ( "UseGreenShipIcon" ), &g_bUseGreenShip);
674
675 Read(_T ( "AutoHideToolbar" ), &g_bAutoHideToolbar);
676 Read(_T ( "AutoHideToolbarSecs" ), &g_nAutoHideToolbar);
677
678 Read(_T ( "UseSimplifiedScalebar" ), &g_bsimplifiedScalebar);
679 Read(_T ( "ShowTide" ), &g_bShowTide);
680 Read(_T ( "ShowCurrent" ), &g_bShowCurrent);
681
682 wxString size_mm;
683 Read(_T ( "DisplaySizeMM" ), &size_mm);
684
685 Read(_T ( "SelectionRadiusMM" ), &g_selection_radius_mm);
686 Read(_T ( "SelectionRadiusTouchMM" ), &g_selection_radius_touch_mm);
687
688 if (!bAsTemplate) {
689 g_config_display_size_mm.clear();
690 wxStringTokenizer tokenizer(size_mm, ",");
691 while (tokenizer.HasMoreTokens()) {
692 wxString token = tokenizer.GetNextToken();
693 int size;
694 try {
695 size = std::stoi(token.ToStdString());
696 } catch (std::invalid_argument &e) {
697 size = 0;
698 }
699 if (size > 100 && size < 2000) {
700 g_config_display_size_mm.push_back(size);
701 } else {
702 g_config_display_size_mm.push_back(0);
703 }
704 }
705 Read(_T ( "DisplaySizeManual" ), &g_config_display_size_manual);
706 }
707
708 Read(_T ( "GUIScaleFactor" ), &g_GUIScaleFactor);
709
710 Read(_T ( "ChartObjectScaleFactor" ), &g_ChartScaleFactor);
711 Read(_T ( "ShipScaleFactor" ), &g_ShipScaleFactor);
712 Read(_T ( "ENCSoundingScaleFactor" ), &g_ENCSoundingScaleFactor);
713 Read(_T ( "ENCTextScaleFactor" ), &g_ENCTextScaleFactor);
714 Read(_T ( "ObjQueryAppendFilesExt" ), &g_ObjQFileExt);
715
716 // Plugin catalog handler persistent variables.
717 Read("CatalogCustomURL", &g_catalog_custom_url);
718 Read("CatalogChannel", &g_catalog_channel);
719
720 Read("NetmaskBits", &g_netmask_bits);
721
722 // NMEA connection options.
723 if (!bAsTemplate) {
724 Read(_T ( "FilterNMEA_Avg" ), &g_bfilter_cogsog);
725 Read(_T ( "FilterNMEA_Sec" ), &g_COGFilterSec);
726 Read(_T ( "GPSIdent" ), &g_GPS_Ident);
727 Read(_T ( "UseGarminHostUpload" ), &g_bGarminHostUpload);
728 Read(_T ( "UseNMEA_GLL" ), &g_bUseGLL);
729 Read(_T ( "UseMagAPB" ), &g_bMagneticAPB);
730 Read(_T ( "TrackContinuous" ), &g_btrackContinuous, false);
731 Read(_T ( "FilterTrackDropLargeJump" ), &g_trackFilterMax, 1000);
732 }
733
734 Read(_T ( "ShowTrue" ), &g_bShowTrue);
735 Read(_T ( "ShowMag" ), &g_bShowMag);
736
737 wxString umv;
738 Read(_T ( "UserMagVariation" ), &umv);
739 if (umv.Len()) umv.ToDouble(&g_UserVar);
740
741 Read(_T ( "ScreenBrightness" ), &g_nbrightness);
742
743 Read(_T ( "MemFootprintTargetMB" ), &g_MemFootMB);
744
745 Read(_T ( "WindowsComPortMax" ), &g_nCOMPortCheck);
746
747 Read(_T ( "ChartQuilting" ), &g_bQuiltEnable);
748 Read(_T ( "ChartQuiltingInitial" ), &g_bQuiltStart);
749
750 Read(_T ( "CourseUpMode" ), &g_bCourseUp);
751 Read(_T ( "COGUPAvgSeconds" ), &g_COGAvgSec);
752 Read(_T ( "LookAheadMode" ), &g_bLookAhead);
753 Read(_T ( "SkewToNorthUp" ), &g_bskew_comp);
754 Read(_T ( "TenHzUpdate" ), &g_btenhertz, 0);
755 Read(_T ( "DeclutterAnchorage" ), &g_declutter_anchorage, 0);
756
757 Read(_T( "NMEAAPBPrecision" ), &g_NMEAAPBPrecision);
758
759 Read(_T( "TalkerIdText" ), &g_TalkerIdText);
760 Read(_T( "MaxWaypointNameLength" ), &g_maxWPNameLength);
761 Read(_T( "MbtilesMaxLayers" ), &g_mbtilesMaxLayers);
762
763 Read(_T( "ShowTrackPointTime" ), &g_bShowTrackPointTime, true);
764 /* opengl options */
765#ifdef ocpnUSE_GL
766 if (!bAsTemplate) {
767 Read(_T ( "OpenGLExpert" ), &g_bGLexpert, false);
768 Read(_T ( "UseAcceleratedPanning" ), &g_GLOptions.m_bUseAcceleratedPanning,
769 true);
770 Read(_T ( "GPUTextureCompression" ), &g_GLOptions.m_bTextureCompression);
771 Read(_T ( "GPUTextureCompressionCaching" ),
772 &g_GLOptions.m_bTextureCompressionCaching);
773 Read(_T ( "PolygonSmoothing" ), &g_GLOptions.m_GLPolygonSmoothing);
774 Read(_T ( "LineSmoothing" ), &g_GLOptions.m_GLLineSmoothing);
775 Read(_T ( "GPUTextureDimension" ), &g_GLOptions.m_iTextureDimension);
776 Read(_T ( "GPUTextureMemSize" ), &g_GLOptions.m_iTextureMemorySize);
777 Read(_T ( "DebugOpenGL" ), &g_bDebugOGL);
778 Read(_T ( "OpenGL" ), &g_bopengl);
779 Read(_T ( "SoftwareGL" ), &g_bSoftwareGL);
780 }
781#endif
782
783 Read(_T ( "SmoothPanZoom" ), &g_bsmoothpanzoom);
784
785 Read(_T ( "ToolbarX"), &g_maintoolbar_x);
786 Read(_T ( "ToolbarY" ), &g_maintoolbar_y);
787 Read(_T ( "ToolbarOrient" ), &g_maintoolbar_orient);
788 Read(_T ( "GlobalToolbarConfig" ), &g_toolbarConfig);
789
790 Read(_T ( "iENCToolbarX"), &g_iENCToolbarPosX);
791 Read(_T ( "iENCToolbarY"), &g_iENCToolbarPosY);
792
793 Read(_T ( "AnchorWatch1GUID" ), &g_AW1GUID);
794 Read(_T ( "AnchorWatch2GUID" ), &g_AW2GUID);
795
796 Read(_T ( "InitialStackIndex" ), &g_restore_stackindex);
797 Read(_T ( "InitialdBIndex" ), &g_restore_dbindex);
798
799 Read(_T ( "ChartNotRenderScaleFactor" ), &g_ChartNotRenderScaleFactor);
800
801 Read(_T ( "MobileTouch" ), &g_btouch);
802
803// "Responsive graphics" option deprecated in O58+
804// Read(_T ( "ResponsiveGraphics" ), &g_bresponsive);
805#ifdef __ANDROID__
806 g_bresponsive = true;
807#else
808 g_bresponsive = false;
809#endif
810
811 Read(_T ( "EnableRolloverBlock" ), &g_bRollover);
812
813 Read(_T ( "ZoomDetailFactor" ), &g_chart_zoom_modifier_raster);
814 Read(_T ( "ZoomDetailFactorVector" ), &g_chart_zoom_modifier_vector);
815 Read(_T ( "PlusMinusZoomFactor" ), &g_plus_minus_zoom_factor, 2.0);
816 Read("MouseZoomSensitivity", &g_mouse_zoom_sensitivity, 1.3);
817 g_mouse_zoom_sensitivity_ui =
818 MouseZoom::config_to_ui(g_mouse_zoom_sensitivity);
819 Read(_T ( "CM93DetailFactor" ), &g_cm93_zoom_factor);
820
821 Read(_T ( "CM93DetailZoomPosX" ), &g_detailslider_dialog_x);
822 Read(_T ( "CM93DetailZoomPosY" ), &g_detailslider_dialog_y);
823 Read(_T ( "ShowCM93DetailSlider" ), &g_bShowDetailSlider);
824
825 Read(_T ( "SENC_LOD_Pixels" ), &g_SENC_LOD_pixels);
826
827 Read(_T ( "SkewCompUpdatePeriod" ), &g_SkewCompUpdatePeriod);
828
829 Read(_T ( "SetSystemTime" ), &s_bSetSystemTime);
830 Read(_T ( "ShowStatusBar" ), &g_bShowStatusBar);
831#ifndef __WXOSX__
832 Read(_T ( "ShowMenuBar" ), &g_bShowMenuBar);
833#endif
834 Read(_T ( "Fullscreen" ), &g_bFullscreen);
835 Read(_T ( "ShowCompassWindow" ), &g_bShowCompassWin);
836 Read(_T ( "ShowGrid" ), &g_bDisplayGrid);
837 Read(_T ( "PlayShipsBells" ), &g_bPlayShipsBells);
838 Read(_T ( "SoundDeviceIndex" ), &g_iSoundDeviceIndex);
839 Read(_T ( "FullscreenToolbar" ), &g_bFullscreenToolbar);
840 Read(_T ( "PermanentMOBIcon" ), &g_bPermanentMOBIcon);
841 Read(_T ( "ShowLayers" ), &g_bShowLayers);
842 Read(_T ( "ShowDepthUnits" ), &g_bShowDepthUnits);
843 Read(_T ( "AutoAnchorDrop" ), &g_bAutoAnchorMark);
844 Read(_T ( "ShowChartOutlines" ), &g_bShowOutlines);
845 Read(_T ( "ShowActiveRouteHighway" ), &g_bShowActiveRouteHighway);
846 Read(_T ( "ShowActiveRouteTotal" ), &g_bShowRouteTotal);
847 Read(_T ( "MostRecentGPSUploadConnection" ), &g_uploadConnection);
848 Read(_T ( "ShowChartBar" ), &g_bShowChartBar);
849 Read(_T ( "SDMMFormat" ),
850 &g_iSDMMFormat); // 0 = "Degrees, Decimal minutes"), 1 = "Decimal
851 // degrees", 2 = "Degrees,Minutes, Seconds"
852
853 Read(_T ( "DistanceFormat" ),
854 &g_iDistanceFormat); // 0 = "Nautical miles"), 1 = "Statute miles", 2 =
855 // "Kilometers", 3 = "Meters"
856 Read(_T ( "SpeedFormat" ),
857 &g_iSpeedFormat); // 0 = "kts"), 1 = "mph", 2 = "km/h", 3 = "m/s"
858 Read(_T ( "WindSpeedFormat" ),
859 &g_iWindSpeedFormat); // 0 = "knots"), 1 = "m/s", 2 = "Mph", 3 = "km/h"
860 Read(_T ("TemperatureFormat"), &g_iTempFormat); // 0 = C, 1 = F, 2 = K
861
862 // LIVE ETA OPTION
863 Read(_T ( "LiveETA" ), &g_bShowLiveETA);
864 Read(_T ( "DefaultBoatSpeed" ), &g_defaultBoatSpeed);
865
866 Read(_T ( "OwnshipCOGPredictorMinutes" ), &g_ownship_predictor_minutes);
867 Read(_T ( "OwnshipCOGPredictorStyle" ), &g_cog_predictor_style);
868 Read(_T ( "OwnshipCOGPredictorColor" ), &g_cog_predictor_color);
869 Read(_T ( "OwnshipCOGPredictorEndmarker" ), &g_cog_predictor_endmarker);
870 Read(_T ( "OwnshipCOGPredictorWidth" ), &g_cog_predictor_width);
871 Read(_T ( "OwnshipHDTPredictorStyle" ), &g_ownship_HDTpredictor_style);
872 Read(_T ( "OwnshipHDTPredictorColor" ), &g_ownship_HDTpredictor_color);
873 Read(_T ( "OwnshipHDTPredictorEndmarker" ),
874 &g_ownship_HDTpredictor_endmarker);
875 Read(_T ( "OwnshipHDTPredictorWidth" ), &g_ownship_HDTpredictor_width);
876 Read(_T ( "OwnshipHDTPredictorMiles" ), &g_ownship_HDTpredictor_miles);
877
878 Read(_T ( "OwnShipMMSINumber" ), &g_OwnShipmmsi);
879 Read(_T ( "OwnShipIconType" ), &g_OwnShipIconType);
880 Read(_T ( "OwnShipLength" ), &g_n_ownship_length_meters);
881 Read(_T ( "OwnShipWidth" ), &g_n_ownship_beam_meters);
882 Read(_T ( "OwnShipGPSOffsetX" ), &g_n_gps_antenna_offset_x);
883 Read(_T ( "OwnShipGPSOffsetY" ), &g_n_gps_antenna_offset_y);
884 Read(_T ( "OwnShipMinSize" ), &g_n_ownship_min_mm);
885 Read(_T ( "OwnShipSogCogCalc" ), &g_own_ship_sog_cog_calc);
886 Read(_T ( "OwnShipSogCogCalcDampSec"), &g_own_ship_sog_cog_calc_damp_sec);
887 Read(_T ( "ShowDirectRouteLine"), &g_bShowShipToActive);
888 Read(_T ( "DirectRouteLineStyle"), &g_shipToActiveStyle);
889 Read(_T( "DirectRouteLineColor" ), &g_shipToActiveColor);
890
891 wxString racr;
892 Read(_T ( "RouteArrivalCircleRadius" ), &racr);
893 if (racr.Len()) racr.ToDouble(&g_n_arrival_circle_radius);
894
895 Read(_T ( "FullScreenQuilt" ), &g_bFullScreenQuilt);
896
897 Read(_T ( "StartWithTrackActive" ), &g_bTrackCarryOver);
898 Read(_T ( "AutomaticDailyTracks" ), &g_bTrackDaily);
899 Read(_T ( "TrackRotateAt" ), &g_track_rotate_time);
900 Read(_T ( "TrackRotateTimeType" ), &g_track_rotate_time_type);
901 Read(_T ( "HighlightTracks" ), &g_bHighliteTracks);
902
903 Read(_T ( "DateTimeFormat" ), &g_datetime_format);
904
905 wxString stps;
906 Read(_T ( "PlanSpeed" ), &stps);
907 if (!stps.IsEmpty()) stps.ToDouble(&g_PlanSpeed);
908
909 Read(_T ( "VisibleLayers" ), &g_VisibleLayers);
910 Read(_T ( "InvisibleLayers" ), &g_InvisibleLayers);
911 Read(_T ( "VisNameInLayers" ), &g_VisiNameinLayers);
912 Read(_T ( "InvisNameInLayers" ), &g_InVisiNameinLayers);
913
914 Read(_T ( "PreserveScaleOnX" ), &g_bPreserveScaleOnX);
915
916 Read(_T ( "ShowMUIZoomButtons" ), &g_bShowMuiZoomButtons);
917
918 Read(_T ( "Locale" ), &g_locale);
919 Read(_T ( "LocaleOverride" ), &g_localeOverride);
920
921 // We allow 0-99 backups ov navobj.xml
922 Read(_T ( "KeepNavobjBackups" ), &g_navobjbackups);
923
924 // Boolean to cater for legacy Input COM Port filer behaviour, i.e. show msg
925 // filtered but put msg on bus.
926 Read(_T ( "LegacyInputCOMPortFilterBehaviour" ),
927 &g_b_legacy_input_filter_behaviour);
928
929 // Boolean to cater for sailing when not approaching waypoint
930 Read(_T( "AdvanceRouteWaypointOnArrivalOnly" ),
931 &g_bAdvanceRouteWaypointOnArrivalOnly);
932 Read("EnableRootMenuDebug", &g_enable_root_menu_debug);
933
934 Read(_T ( "EnableRotateKeys" ), &g_benable_rotate);
935 Read(_T ( "EmailCrashReport" ), &g_bEmailCrashReport);
936
937 g_benableAISNameCache = true;
938 Read(_T ( "EnableAISNameCache" ), &g_benableAISNameCache);
939
940 Read(_T ( "EnableUDPNullHeader" ), &g_benableUDPNullHeader);
941
942 SetPath(_T ( "/Settings/GlobalState" ));
943
944 Read(_T ( "FrameWinX" ), &g_nframewin_x);
945 Read(_T ( "FrameWinY" ), &g_nframewin_y);
946 Read(_T ( "FrameWinPosX" ), &g_nframewin_posx);
947 Read(_T ( "FrameWinPosY" ), &g_nframewin_posy);
948 Read(_T ( "FrameMax" ), &g_bframemax);
949
950 Read(_T ( "ClientPosX" ), &g_lastClientRectx);
951 Read(_T ( "ClientPosY" ), &g_lastClientRecty);
952 Read(_T ( "ClientSzX" ), &g_lastClientRectw);
953 Read(_T ( "ClientSzY" ), &g_lastClientRecth);
954
955 Read(_T( "RoutePropSizeX" ), &g_route_prop_sx);
956 Read(_T( "RoutePropSizeY" ), &g_route_prop_sy);
957 Read(_T( "RoutePropPosX" ), &g_route_prop_x);
958 Read(_T( "RoutePropPosY" ), &g_route_prop_y);
959
960 read_int = -1;
961 Read(_T ( "S52_DEPTH_UNIT_SHOW" ), &read_int); // default is metres
962 if (read_int >= 0) {
963 read_int = wxMax(read_int, 0); // qualify value
964 read_int = wxMin(read_int, 2);
965 g_nDepthUnitDisplay = read_int;
966 }
967
968 // Sounds
969 SetPath(_T ( "/Settings/Audio" ));
970
971 // Set reasonable defaults
972 wxString sound_dir = g_Platform->GetSharedDataDir();
973 sound_dir.Append(_T("sounds"));
974 sound_dir.Append(wxFileName::GetPathSeparator());
975
976 g_AIS_sound_file = sound_dir + _T("beep_ssl.wav");
977 g_DSC_sound_file = sound_dir + _T("phonering1.wav");
978 g_SART_sound_file = sound_dir + _T("beep3.wav");
979 g_anchorwatch_sound_file = sound_dir + _T("beep1.wav");
980
981 Read(_T ( "AISAlertSoundFile" ), &g_AIS_sound_file);
982 Read(_T ( "DSCAlertSoundFile" ), &g_DSC_sound_file);
983 Read(_T ( "SARTAlertSoundFile" ), &g_SART_sound_file);
984 Read(_T ( "AnchorAlarmSoundFile" ), &g_anchorwatch_sound_file);
985
986 Read(_T ( "bAIS_GCPA_AlertAudio" ), &g_bAIS_GCPA_Alert_Audio);
987 Read(_T ( "bAIS_SART_AlertAudio" ), &g_bAIS_SART_Alert_Audio);
988 Read(_T ( "bAIS_DSC_AlertAudio" ), &g_bAIS_DSC_Alert_Audio);
989 Read(_T ( "bAnchorAlertAudio" ), &g_bAnchor_Alert_Audio);
990
991 // AIS
992 wxString s;
993 SetPath(_T ( "/Settings/AIS" ));
994
995 g_bUseOnlyConfirmedAISName = false;
996 Read(_T ( "UseOnlyConfirmedAISName" ), &g_bUseOnlyConfirmedAISName);
997
998 Read(_T ( "bNoCPAMax" ), &g_bCPAMax);
999
1000 Read(_T ( "NoCPAMaxNMi" ), &s);
1001 s.ToDouble(&g_CPAMax_NM);
1002
1003 Read(_T ( "bCPAWarn" ), &g_bCPAWarn);
1004
1005 Read(_T ( "CPAWarnNMi" ), &s);
1006 s.ToDouble(&g_CPAWarn_NM);
1007
1008 Read(_T ( "bTCPAMax" ), &g_bTCPA_Max);
1009
1010 Read(_T ( "TCPAMaxMinutes" ), &s);
1011 s.ToDouble(&g_TCPA_Max);
1012
1013 Read(_T ( "bMarkLostTargets" ), &g_bMarkLost);
1014
1015 Read(_T ( "MarkLost_Minutes" ), &s);
1016 s.ToDouble(&g_MarkLost_Mins);
1017
1018 Read(_T ( "bRemoveLostTargets" ), &g_bRemoveLost);
1019
1020 Read(_T ( "RemoveLost_Minutes" ), &s);
1021 s.ToDouble(&g_RemoveLost_Mins);
1022
1023 Read(_T ( "bShowCOGArrows" ), &g_bShowCOG);
1024
1025 Read(_T ("bSyncCogPredictors"), &g_bSyncCogPredictors);
1026
1027 Read(_T ( "CogArrowMinutes" ), &s);
1028 s.ToDouble(&g_ShowCOG_Mins);
1029
1030 Read(_T ( "bShowTargetTracks" ), &g_bAISShowTracks);
1031
1032 if (Read(_T ( "TargetTracksLimit" ), &s)) {
1033 s.ToDouble(&g_AISShowTracks_Limit);
1034 g_AISShowTracks_Limit = wxMax(300.0, g_AISShowTracks_Limit);
1035 }
1036 if (Read(_T ( "TargetTracksMinutes" ), &s)) {
1037 s.ToDouble(&g_AISShowTracks_Mins);
1038 g_AISShowTracks_Mins = wxMax(1.0, g_AISShowTracks_Mins);
1039 g_AISShowTracks_Mins = wxMin(g_AISShowTracks_Limit, g_AISShowTracks_Mins);
1040 }
1041
1042 Read(_T ( "bHideMooredTargets" ), &g_bHideMoored);
1043 if (Read(_T ( "MooredTargetMaxSpeedKnots" ), &s))
1044 s.ToDouble(&g_ShowMoored_Kts);
1045
1046 g_SOGminCOG_kts = 0.2;
1047 if (Read(_T ( "SOGMinimumForCOGDisplay" ), &s)) s.ToDouble(&g_SOGminCOG_kts);
1048
1049 Read(_T ("bShowScaledTargets"), &g_bAllowShowScaled);
1050 Read(_T ( "AISScaledNumber" ), &g_ShowScaled_Num);
1051 Read(_T ( "AISScaledNumberWeightSOG" ), &g_ScaledNumWeightSOG);
1052 Read(_T ( "AISScaledNumberWeightCPA" ), &g_ScaledNumWeightCPA);
1053 Read(_T ( "AISScaledNumberWeightTCPA" ), &g_ScaledNumWeightTCPA);
1054 Read(_T ( "AISScaledNumberWeightRange" ), &g_ScaledNumWeightRange);
1055 Read(_T ( "AISScaledNumberWeightSizeOfTarget" ), &g_ScaledNumWeightSizeOfT);
1056 Read(_T ( "AISScaledSizeMinimal" ), &g_ScaledSizeMinimal);
1057 Read(_T("AISShowScaled"), &g_bShowScaled);
1058
1059 Read(_T ( "bShowAreaNotices" ), &g_bShowAreaNotices);
1060 Read(_T ( "bDrawAISSize" ), &g_bDrawAISSize);
1061 Read(_T ( "bDrawAISRealtime" ), &g_bDrawAISRealtime);
1062 Read(_T ( "bShowAISName" ), &g_bShowAISName);
1063 Read(_T ( "AISRealtimeMinSpeedKnots" ), &g_AIS_RealtPred_Kts, 0.7);
1064 Read(_T ( "bAISAlertDialog" ), &g_bAIS_CPA_Alert);
1065 Read(_T ( "ShowAISTargetNameScale" ), &g_Show_Target_Name_Scale);
1066 Read(_T ( "bWplIsAprsPositionReport" ), &g_bWplUsePosition);
1067 Read(_T ( "WplSelAction"), &g_WplAction);
1068 Read(_T ( "AISCOGPredictorWidth" ), &g_ais_cog_predictor_width);
1069
1070 Read(_T ( "bAISAlertAudio" ), &g_bAIS_CPA_Alert_Audio);
1071 Read(_T ( "AISAlertAudioFile" ), &g_sAIS_Alert_Sound_File);
1072 Read(_T ( "bAISAlertSuppressMoored" ), &g_bAIS_CPA_Alert_Suppress_Moored);
1073
1074 Read(_T ( "bAISAlertAckTimeout" ), &g_bAIS_ACK_Timeout);
1075 if (Read(_T ( "AlertAckTimeoutMinutes" ), &s)) s.ToDouble(&g_AckTimeout_Mins);
1076
1077 Read(_T ( "AlertDialogSizeX" ), &g_ais_alert_dialog_sx);
1078 Read(_T ( "AlertDialogSizeY" ), &g_ais_alert_dialog_sy);
1079 Read(_T ( "AlertDialogPosX" ), &g_ais_alert_dialog_x);
1080 Read(_T ( "AlertDialogPosY" ), &g_ais_alert_dialog_y);
1081 Read(_T ( "QueryDialogPosX" ), &g_ais_query_dialog_x);
1082 Read(_T ( "QueryDialogPosY" ), &g_ais_query_dialog_y);
1083
1084 Read(_T ( "AISTargetListPerspective" ), &g_AisTargetList_perspective);
1085 Read(_T ( "AISTargetListRange" ), &g_AisTargetList_range);
1086 Read(_T ( "AISTargetListSortColumn" ), &g_AisTargetList_sortColumn);
1087 Read(_T ( "bAISTargetListSortReverse" ), &g_bAisTargetList_sortReverse);
1088 Read(_T ( "AISTargetListColumnSpec" ), &g_AisTargetList_column_spec);
1089 Read(_T ("AISTargetListColumnOrder"), &g_AisTargetList_column_order);
1090
1091 Read(_T ( "bAISRolloverShowClass" ), &g_bAISRolloverShowClass);
1092 Read(_T ( "bAISRolloverShowCOG" ), &g_bAISRolloverShowCOG);
1093 Read(_T ( "bAISRolloverShowCPA" ), &g_bAISRolloverShowCPA);
1094
1095 Read(_T ( "S57QueryDialogSizeX" ), &g_S57_dialog_sx);
1096 Read(_T ( "S57QueryDialogSizeY" ), &g_S57_dialog_sy);
1097 Read(_T ( "S57QueryExtraDialogSizeX" ), &g_S57_extradialog_sx);
1098 Read(_T ( "S57QueryExtraDialogSizeY" ), &g_S57_extradialog_sy);
1099
1100 wxString strpres(_T ( "PresentationLibraryData" ));
1101 wxString valpres;
1102 SetPath(_T ( "/Directories" ));
1103 Read(strpres, &valpres); // Get the File name
1104 if (!valpres.IsEmpty()) g_UserPresLibData = valpres;
1105
1106 wxString strs(_T ( "SENCFileLocation" ));
1107 SetPath(_T ( "/Directories" ));
1108 wxString vals;
1109 Read(strs, &vals); // Get the Directory name
1110 if (!vals.IsEmpty()) g_SENCPrefix = vals;
1111
1112 SetPath(_T ( "/Directories" ));
1113 wxString vald;
1114 Read(_T ( "InitChartDir" ), &vald); // Get the Directory name
1115
1116 wxString dirnamed(vald);
1117 if (!dirnamed.IsEmpty()) {
1118 if (pInit_Chart_Dir->IsEmpty()) // on second pass, don't overwrite
1119 {
1120 pInit_Chart_Dir->Clear();
1121 pInit_Chart_Dir->Append(vald);
1122 }
1123 }
1124
1125 Read(_T ( "GPXIODir" ), &g_gpx_path); // Get the Directory name
1126 Read(_T ( "TCDataDir" ), &g_TCData_Dir); // Get the Directory name
1127 Read(_T ( "BasemapDir"), &gWorldMapLocation);
1128 Read(_T ( "BaseShapefileDir"), &gWorldShapefileLocation);
1129 Read(_T ( "pluginInstallDir"), &g_winPluginDir);
1130 wxLogMessage("winPluginDir, read from ini file: %s",
1131 g_winPluginDir.mb_str().data());
1132
1133 SetPath(_T ( "/Settings/GlobalState" ));
1134
1135 if (Read(_T ( "nColorScheme" ), &read_int))
1136 global_color_scheme = (ColorScheme)read_int;
1137
1138 if (!bAsTemplate) {
1139 SetPath(_T ( "/Settings/NMEADataSource" ));
1140
1141 TheConnectionParams().clear();
1142 wxString connectionconfigs;
1143 Read(_T( "DataConnections" ), &connectionconfigs);
1144 if (!connectionconfigs.IsEmpty()) {
1145 wxArrayString confs = wxStringTokenize(connectionconfigs, _T("|"));
1146 for (size_t i = 0; i < confs.Count(); i++) {
1147 ConnectionParams *prm = new ConnectionParams(confs[i]);
1148 if (!prm->Valid) {
1149 wxLogMessage(_T( "Skipped invalid DataStream config"));
1150 delete prm;
1151 continue;
1152 }
1153 TheConnectionParams().push_back(prm);
1154 }
1155 }
1156 }
1157
1158 SetPath(_T ( "/Settings/GlobalState" ));
1159 wxString st;
1160
1161 double st_lat, st_lon;
1162 if (Read(_T ( "VPLatLon" ), &st)) {
1163 sscanf(st.mb_str(wxConvUTF8), "%lf,%lf", &st_lat, &st_lon);
1164
1165 // Sanity check the lat/lon...both have to be reasonable.
1166 if (fabs(st_lon) < 360.) {
1167 while (st_lon < -180.) st_lon += 360.;
1168
1169 while (st_lon > 180.) st_lon -= 360.;
1170
1171 vLon = st_lon;
1172 }
1173
1174 if (fabs(st_lat) < 90.0) vLat = st_lat;
1175
1176 s.Printf(_T ( "Setting Viewpoint Lat/Lon %g, %g" ), vLat, vLon);
1177 wxLogMessage(s);
1178 }
1179
1180 double st_view_scale, st_rotation;
1181 if (Read(wxString(_T ( "VPScale" )), &st)) {
1182 sscanf(st.mb_str(wxConvUTF8), "%lf", &st_view_scale);
1183 // Sanity check the scale
1184 st_view_scale = fmax(st_view_scale, .001 / 32);
1185 st_view_scale = fmin(st_view_scale, 4);
1186 }
1187
1188 if (Read(wxString(_T ( "VPRotation" )), &st)) {
1189 sscanf(st.mb_str(wxConvUTF8), "%lf", &st_rotation);
1190 // Sanity check the rotation
1191 st_rotation = fmin(st_rotation, 360);
1192 st_rotation = fmax(st_rotation, 0);
1193 }
1194
1195 wxString sll;
1196 double lat, lon;
1197 if (Read(_T ( "OwnShipLatLon" ), &sll)) {
1198 sscanf(sll.mb_str(wxConvUTF8), "%lf,%lf", &lat, &lon);
1199
1200 // Sanity check the lat/lon...both have to be reasonable.
1201 if (fabs(lon) < 360.) {
1202 while (lon < -180.) lon += 360.;
1203
1204 while (lon > 180.) lon -= 360.;
1205
1206 gLon = lon;
1207 }
1208
1209 if (fabs(lat) < 90.0) gLat = lat;
1210
1211 s.Printf(_T ( "Setting Ownship Lat/Lon %g, %g" ), gLat, gLon);
1212 wxLogMessage(s);
1213 }
1214
1215 // Fonts
1216
1217 // Load the persistent Auxiliary Font descriptor Keys
1218 SetPath(_T ( "/Settings/AuxFontKeys" ));
1219
1220 wxString strk;
1221 long dummyk;
1222 wxString kval;
1223 bool bContk = GetFirstEntry(strk, dummyk);
1224 bool bNewKey = false;
1225 while (bContk) {
1226 Read(strk, &kval);
1227 bNewKey = FontMgr::Get().AddAuxKey(kval);
1228 if (!bAsTemplate && !bNewKey) {
1229 DeleteEntry(strk);
1230 dummyk--;
1231 }
1232 bContk = GetNextEntry(strk, dummyk);
1233 }
1234
1235#ifdef __WXX11__
1236 SetPath(_T ( "/Settings/X11Fonts" ));
1237#endif
1238
1239#ifdef __WXGTK__
1240 SetPath(_T ( "/Settings/GTKFonts" ));
1241#endif
1242
1243#ifdef __WXMSW__
1244 SetPath(_T ( "/Settings/MSWFonts" ));
1245#endif
1246
1247#ifdef __WXMAC__
1248 SetPath(_T ( "/Settings/MacFonts" ));
1249#endif
1250
1251#ifdef __WXQT__
1252 SetPath(_T ( "/Settings/QTFonts" ));
1253#endif
1254
1255 wxString str;
1256 long dummy;
1257 wxString pval;
1258 wxArrayString deleteList;
1259
1260 bool bCont = GetFirstEntry(str, dummy);
1261 while (bCont) {
1262 pval = Read(str);
1263
1264 if (str.StartsWith(_T("Font"))) {
1265 // Convert pre 3.1 setting. Can't delete old entries from inside the
1266 // GetNextEntry() loop, so we need to save those and delete outside.
1267 deleteList.Add(str);
1268 wxString oldKey = pval.BeforeFirst(_T(':'));
1269 str = FontMgr::GetFontConfigKey(oldKey);
1270 }
1271
1272 if (pval.IsEmpty() || pval.StartsWith(_T(":"))) {
1273 deleteList.Add(str);
1274 } else
1275 FontMgr::Get().LoadFontNative(&str, &pval);
1276
1277 bCont = GetNextEntry(str, dummy);
1278 }
1279
1280 for (unsigned int i = 0; i < deleteList.Count(); i++) {
1281 DeleteEntry(deleteList[i]);
1282 }
1283 deleteList.Clear();
1284
1285 // Tide/Current Data Sources
1286 SetPath(_T ( "/TideCurrentDataSources" ));
1287 if (GetNumberOfEntries()) {
1288 TideCurrentDataSet.clear();
1289 wxString str, val;
1290 long dummy;
1291 bool bCont = GetFirstEntry(str, dummy);
1292 while (bCont) {
1293 Read(str, &val); // Get a file name and add it to the list just in case
1294 // it is not repeated
1295 // We have seen duplication of dataset entries in
1296 // https://github.com/OpenCPN/OpenCPN/issues/3042, this effectively gets
1297 // rid of them.
1298 if (std::find(TideCurrentDataSet.begin(), TideCurrentDataSet.end(),
1299 val.ToStdString()) == TideCurrentDataSet.end()) {
1300 TideCurrentDataSet.push_back(val.ToStdString());
1301 }
1302 bCont = GetNextEntry(str, dummy);
1303 }
1304 }
1305
1306 // Groups
1307 LoadConfigGroups(g_pGroupArray);
1308
1309 // // Multicanvas Settings
1310 // LoadCanvasConfigs();
1311
1312 SetPath(_T ( "/Settings/Others" ));
1313
1314 // Radar rings
1315 Read(_T ( "RadarRingsNumberVisible" ), &val);
1316 if (val.Length() > 0) g_iNavAidRadarRingsNumberVisible = atoi(val.mb_str());
1317 g_bNavAidRadarRingsShown = g_iNavAidRadarRingsNumberVisible > 0;
1318
1319 Read(_T ( "RadarRingsStep" ), &val);
1320 if (val.Length() > 0) g_fNavAidRadarRingsStep = atof(val.mb_str());
1321
1322 Read(_T ( "RadarRingsStepUnits" ), &g_pNavAidRadarRingsStepUnits);
1323
1324 wxString l_wxsOwnshipRangeRingsColour;
1325 Read(_T ( "RadarRingsColour" ), &l_wxsOwnshipRangeRingsColour);
1326 if (l_wxsOwnshipRangeRingsColour.Length())
1327 g_colourOwnshipRangeRingsColour.Set(l_wxsOwnshipRangeRingsColour);
1328
1329 // Waypoint Radar rings
1330 Read(_T ( "WaypointRangeRingsNumber" ), &val);
1331 if (val.Length() > 0) g_iWaypointRangeRingsNumber = atoi(val.mb_str());
1332
1333 Read(_T ( "WaypointRangeRingsStep" ), &val);
1334 if (val.Length() > 0) g_fWaypointRangeRingsStep = atof(val.mb_str());
1335
1336 Read(_T ( "WaypointRangeRingsStepUnits" ), &g_iWaypointRangeRingsStepUnits);
1337
1338 wxString l_wxsWaypointRangeRingsColour;
1339 Read(_T( "WaypointRangeRingsColour" ), &l_wxsWaypointRangeRingsColour);
1340 g_colourWaypointRangeRingsColour.Set(l_wxsWaypointRangeRingsColour);
1341
1342 if (!Read(_T("WaypointUseScaMin"), &g_bUseWptScaMin)) g_bUseWptScaMin = false;
1343 if (!Read(_T("WaypointScaMinValue"), &g_iWpt_ScaMin))
1344 g_iWpt_ScaMin = 2147483646;
1345 if (!Read(_T("WaypointUseScaMinOverrule"), &g_bOverruleScaMin))
1346 g_bOverruleScaMin = false;
1347 if (!Read(_T("WaypointsShowName"), &g_bShowWptName)) g_bShowWptName = true;
1348 if (!Read(_T("UserIconsFirst"), &g_bUserIconsFirst)) g_bUserIconsFirst = true;
1349
1350 // Support Version 3.0 and prior config setting for Radar Rings
1351 bool b300RadarRings = true;
1352 if (Read(_T ( "ShowRadarRings" ), &b300RadarRings)) {
1353 if (!b300RadarRings) g_iNavAidRadarRingsNumberVisible = 0;
1354 }
1355
1356 Read(_T ( "ConfirmObjectDeletion" ), &g_bConfirmObjectDelete);
1357
1358 // Waypoint dragging with mouse
1359 g_bWayPointPreventDragging = false;
1360 Read(_T ( "WaypointPreventDragging" ), &g_bWayPointPreventDragging);
1361
1362 g_bEnableZoomToCursor = false;
1363 Read(_T ( "EnableZoomToCursor" ), &g_bEnableZoomToCursor);
1364
1365 val.Clear();
1366 Read(_T ( "TrackIntervalSeconds" ), &val);
1367 if (val.Length() > 0) {
1368 double tval = atof(val.mb_str());
1369 if (tval >= 2.) g_TrackIntervalSeconds = tval;
1370 }
1371
1372 val.Clear();
1373 Read(_T ( "TrackDeltaDistance" ), &val);
1374 if (val.Length() > 0) {
1375 double tval = atof(val.mb_str());
1376 if (tval >= 0.05) g_TrackDeltaDistance = tval;
1377 }
1378
1379 Read(_T ( "TrackPrecision" ), &g_nTrackPrecision);
1380
1381 Read(_T ( "RouteLineWidth" ), &g_route_line_width);
1382 Read(_T ( "TrackLineWidth" ), &g_track_line_width);
1383
1384 wxString l_wxsTrackLineColour;
1385 if (Read(_T( "TrackLineColour" ), &l_wxsTrackLineColour))
1386 g_colourTrackLineColour.Set(l_wxsTrackLineColour);
1387
1388 Read(_T ( "TideCurrentWindowScale" ), &g_tcwin_scale);
1389 Read(_T ( "DefaultWPIcon" ), &g_default_wp_icon);
1390 Read(_T ( "DefaultRPIcon" ), &g_default_routepoint_icon);
1391
1392 SetPath(_T ( "/MmsiProperties" ));
1393 int iPMax = GetNumberOfEntries();
1394 if (iPMax) {
1395 g_MMSI_Props_Array.Empty();
1396 wxString str, val;
1397 long dummy;
1398 bool bCont = pConfig->GetFirstEntry(str, dummy);
1399 while (bCont) {
1400 pConfig->Read(str, &val); // Get an entry
1401
1402 MmsiProperties *pProps = new MmsiProperties(val);
1403 g_MMSI_Props_Array.Add(pProps);
1404
1405 bCont = pConfig->GetNextEntry(str, dummy);
1406 }
1407 }
1408
1409 return (0);
1410}
1411
1412void MyConfig::LoadS57Config() {
1413 if (!ps52plib) return;
1414
1415 int read_int;
1416 double dval;
1417 SetPath(_T ( "/Settings/GlobalState" ));
1418
1419 Read(_T ( "bShowS57Text" ), &read_int, 1);
1420 ps52plib->SetShowS57Text(!(read_int == 0));
1421
1422 Read(_T ( "bShowS57ImportantTextOnly" ), &read_int, 0);
1423 ps52plib->SetShowS57ImportantTextOnly(!(read_int == 0));
1424
1425 Read(_T ( "bShowLightDescription" ), &read_int, 0);
1426 ps52plib->SetShowLdisText(!(read_int == 0));
1427
1428 Read(_T ( "bExtendLightSectors" ), &read_int, 0);
1429 ps52plib->SetExtendLightSectors(!(read_int == 0));
1430
1431 Read(_T ( "nDisplayCategory" ), &read_int, (enum _DisCat)STANDARD);
1432 ps52plib->SetDisplayCategory((enum _DisCat)read_int);
1433
1434 Read(_T ( "nSymbolStyle" ), &read_int, (enum _LUPname)PAPER_CHART);
1435 ps52plib->m_nSymbolStyle = (LUPname)read_int;
1436
1437 Read(_T ( "nBoundaryStyle" ), &read_int, PLAIN_BOUNDARIES);
1438 ps52plib->m_nBoundaryStyle = (LUPname)read_int;
1439
1440 Read(_T ( "bShowSoundg" ), &read_int, 1);
1441 ps52plib->m_bShowSoundg = !(read_int == 0);
1442
1443 Read(_T ( "bShowMeta" ), &read_int, 0);
1444 ps52plib->m_bShowMeta = !(read_int == 0);
1445
1446 Read(_T ( "bUseSCAMIN" ), &read_int, 1);
1447 ps52plib->m_bUseSCAMIN = !(read_int == 0);
1448
1449 Read(_T ( "bUseSUPER_SCAMIN" ), &read_int, 0);
1450 ps52plib->m_bUseSUPER_SCAMIN = !(read_int == 0);
1451
1452 Read(_T ( "bShowAtonText" ), &read_int, 1);
1453 ps52plib->m_bShowAtonText = !(read_int == 0);
1454
1455 Read(_T ( "bDeClutterText" ), &read_int, 0);
1456 ps52plib->m_bDeClutterText = !(read_int == 0);
1457
1458 Read(_T ( "bShowNationalText" ), &read_int, 0);
1459 ps52plib->m_bShowNationalTexts = !(read_int == 0);
1460
1461 Read(_T ( "ENCSoundingScaleFactor" ), &read_int, 0);
1462 ps52plib->m_nSoundingFactor = read_int;
1463
1464 Read(_T ( "ENCTextScaleFactor" ), &read_int, 0);
1465 ps52plib->m_nTextFactor = read_int;
1466
1467 if (Read(_T ( "S52_MAR_SAFETY_CONTOUR" ), &dval, 3.0)) {
1468 S52_setMarinerParam(S52_MAR_SAFETY_CONTOUR, dval);
1469 S52_setMarinerParam(S52_MAR_SAFETY_DEPTH,
1470 dval); // Set safety_contour and safety_depth the same
1471 }
1472
1473 if (Read(_T ( "S52_MAR_SHALLOW_CONTOUR" ), &dval, 2.0))
1474 S52_setMarinerParam(S52_MAR_SHALLOW_CONTOUR, dval);
1475
1476 if (Read(_T ( "S52_MAR_DEEP_CONTOUR" ), &dval, 6.0))
1477 S52_setMarinerParam(S52_MAR_DEEP_CONTOUR, dval);
1478
1479 if (Read(_T ( "S52_MAR_TWO_SHADES" ), &dval, 0.0))
1480 S52_setMarinerParam(S52_MAR_TWO_SHADES, dval);
1481
1482 ps52plib->UpdateMarinerParams();
1483
1484 SetPath(_T ( "/Settings/GlobalState" ));
1485 Read(_T ( "S52_DEPTH_UNIT_SHOW" ), &read_int, 1); // default is metres
1486 read_int = wxMax(read_int, 0); // qualify value
1487 read_int = wxMin(read_int, 2);
1488 ps52plib->m_nDepthUnitDisplay = read_int;
1489 g_nDepthUnitDisplay = read_int;
1490
1491 // S57 Object Class Visibility
1492
1493 OBJLElement *pOLE;
1494
1495 SetPath(_T ( "/Settings/ObjectFilter" ));
1496
1497 int iOBJMax = GetNumberOfEntries();
1498 if (iOBJMax) {
1499 wxString str;
1500 long val;
1501 long dummy;
1502
1503 wxString sObj;
1504
1505 bool bCont = pConfig->GetFirstEntry(str, dummy);
1506 while (bCont) {
1507 pConfig->Read(str, &val); // Get an Object Viz
1508
1509 bool bNeedNew = true;
1510
1511 if (str.StartsWith(_T ( "viz" ), &sObj)) {
1512 for (unsigned int iPtr = 0; iPtr < ps52plib->pOBJLArray->GetCount();
1513 iPtr++) {
1514 pOLE = (OBJLElement *)(ps52plib->pOBJLArray->Item(iPtr));
1515 if (!strncmp(pOLE->OBJLName, sObj.mb_str(), 6)) {
1516 pOLE->nViz = val;
1517 bNeedNew = false;
1518 break;
1519 }
1520 }
1521
1522 if (bNeedNew) {
1523 pOLE = (OBJLElement *)calloc(sizeof(OBJLElement), 1);
1524 memcpy(pOLE->OBJLName, sObj.mb_str(), OBJL_NAME_LEN);
1525 pOLE->nViz = 1;
1526
1527 ps52plib->pOBJLArray->Add((void *)pOLE);
1528 }
1529 }
1530 bCont = pConfig->GetNextEntry(str, dummy);
1531 }
1532 }
1533}
1534
1535bool MyConfig::LoadLayers(wxString &path) {
1536 wxArrayString file_array;
1537 wxDir dir;
1538 Layer *l;
1539 dir.Open(path);
1540 if (dir.IsOpened()) {
1541 wxString filename;
1542 bool cont = dir.GetFirst(&filename);
1543 while (cont) {
1544 file_array.Clear();
1545 filename.Prepend(wxFileName::GetPathSeparator());
1546 filename.Prepend(path);
1547 wxFileName f(filename);
1548 size_t nfiles = 0;
1549 if (f.GetExt().IsSameAs(wxT("gpx")))
1550 file_array.Add(filename); // single-gpx-file layer
1551 else {
1552 if (wxDir::Exists(filename)) {
1553 wxDir dir(filename);
1554 if (dir.IsOpened()) {
1555 nfiles = dir.GetAllFiles(filename, &file_array,
1556 wxT("*.gpx")); // layers subdirectory set
1557 }
1558 }
1559 }
1560
1561 if (file_array.GetCount()) {
1562 l = new Layer();
1563 l->m_LayerID = ++g_LayerIdx;
1564 l->m_LayerFileName = file_array[0];
1565 if (file_array.GetCount() <= 1)
1566 wxFileName::SplitPath(file_array[0], NULL, NULL, &(l->m_LayerName),
1567 NULL, NULL);
1568 else
1569 wxFileName::SplitPath(filename, NULL, NULL, &(l->m_LayerName), NULL,
1570 NULL);
1571
1572 bool bLayerViz = g_bShowLayers;
1573
1574 if (g_VisibleLayers.Contains(l->m_LayerName)) bLayerViz = true;
1575 if (g_InvisibleLayers.Contains(l->m_LayerName)) bLayerViz = false;
1576
1577 l->m_bHasVisibleNames = wxCHK_UNDETERMINED;
1578 if (g_VisiNameinLayers.Contains(l->m_LayerName))
1579 l->m_bHasVisibleNames = wxCHK_CHECKED;
1580 if (g_InVisiNameinLayers.Contains(l->m_LayerName))
1581 l->m_bHasVisibleNames = wxCHK_UNCHECKED;
1582
1583 l->m_bIsVisibleOnChart = bLayerViz;
1584
1585 wxString laymsg;
1586 laymsg.Printf(wxT("New layer %d: %s"), l->m_LayerID,
1587 l->m_LayerName.c_str());
1588 wxLogMessage(laymsg);
1589
1590 pLayerList->Insert(l);
1591
1592 // Load the entire file array as a single layer
1593
1594 for (unsigned int i = 0; i < file_array.GetCount(); i++) {
1595 wxString file_path = file_array[i];
1596
1597 if (::wxFileExists(file_path)) {
1599 if (pSet->load_file(file_path.fn_str()).status !=
1600 pugi::xml_parse_status::status_ok) {
1601 wxLogMessage("Error loading GPX file " + file_path);
1602 pSet->reset();
1603 }
1604 long nItems = pSet->LoadAllGPXObjectsAsLayer(
1605 l->m_LayerID, bLayerViz, l->m_bHasVisibleNames);
1606 l->m_NoOfItems += nItems;
1607 l->m_LayerType = _("Persistent");
1608
1609 wxString objmsg;
1610 objmsg.Printf(wxT("Loaded GPX file %s with %ld items."),
1611 file_path.c_str(), nItems);
1612 wxLogMessage(objmsg);
1613
1614 delete pSet;
1615 }
1616 }
1617 }
1618
1619 cont = dir.GetNext(&filename);
1620 }
1621 }
1622 g_bLayersLoaded = true;
1623
1624 return true;
1625}
1626
1627bool MyConfig::LoadChartDirArray(ArrayOfCDI &ChartDirArray) {
1628 // Chart Directories
1629 SetPath(_T ( "/ChartDirectories" ));
1630 int iDirMax = GetNumberOfEntries();
1631 if (iDirMax) {
1632 ChartDirArray.Empty();
1633 wxString str, val;
1634 long dummy;
1635 int nAdjustChartDirs = 0;
1636 int iDir = 0;
1637 bool bCont = pConfig->GetFirstEntry(str, dummy);
1638 while (bCont) {
1639 pConfig->Read(str, &val); // Get a Directory name
1640
1641 wxString dirname(val);
1642 if (!dirname.IsEmpty()) {
1643 /* Special case for first time run after Windows install with sample
1644 chart data... We desire that the sample configuration file opencpn.ini
1645 should not contain any installation dependencies, so... Detect and
1646 update the sample [ChartDirectories] entries to point to the Shared
1647 Data directory For instance, if the (sample) opencpn.ini file should
1648 contain shortcut coded entries like:
1649
1650 [ChartDirectories]
1651 ChartDir1=SampleCharts\\MaptechRegion7
1652
1653 then this entry will be updated to be something like:
1654 ChartDir1=c:\Program Files\opencpn\SampleCharts\\MaptechRegion7
1655
1656 */
1657 if (dirname.Find(_T ( "SampleCharts" )) ==
1658 0) // only update entries starting with "SampleCharts"
1659 {
1660 nAdjustChartDirs++;
1661
1662 pConfig->DeleteEntry(str);
1663 wxString new_dir = dirname.Mid(dirname.Find(_T ( "SampleCharts" )));
1664 new_dir.Prepend(g_Platform->GetSharedDataDir());
1665 dirname = new_dir;
1666 }
1667
1668 ChartDirInfo cdi;
1669 cdi.fullpath = dirname.BeforeFirst('^');
1670 cdi.magic_number = dirname.AfterFirst('^');
1671
1672 ChartDirArray.Add(cdi);
1673 iDir++;
1674 }
1675
1676 bCont = pConfig->GetNextEntry(str, dummy);
1677 }
1678
1679 if (nAdjustChartDirs) pConfig->UpdateChartDirs(ChartDirArray);
1680 }
1681
1682 return true;
1683}
1684
1685bool MyConfig::UpdateChartDirs(ArrayOfCDI &dir_array) {
1686 wxString key, dir;
1687 wxString str_buf;
1688
1689 SetPath(_T ( "/ChartDirectories" ));
1690 int iDirMax = GetNumberOfEntries();
1691 if (iDirMax) {
1692 long dummy;
1693
1694 for (int i = 0; i < iDirMax; i++) {
1695 GetFirstEntry(key, dummy);
1696 DeleteEntry(key, false);
1697 }
1698 }
1699
1700 iDirMax = dir_array.GetCount();
1701
1702 for (int iDir = 0; iDir < iDirMax; iDir++) {
1703 ChartDirInfo cdi = dir_array[iDir];
1704
1705 wxString dirn = cdi.fullpath;
1706 dirn.Append(_T("^"));
1707 dirn.Append(cdi.magic_number);
1708
1709 str_buf.Printf(_T ( "ChartDir%d" ), iDir + 1);
1710
1711 Write(str_buf, dirn);
1712 }
1713
1714// Avoid nonsense log errors...
1715#ifdef __ANDROID__
1716 wxLogNull logNo;
1717#endif
1718
1719 Flush();
1720 return true;
1721}
1722
1723void MyConfig::CreateConfigGroups(ChartGroupArray *pGroupArray) {
1724 if (!pGroupArray) return;
1725
1726 SetPath(_T ( "/Groups" ));
1727 Write(_T ( "GroupCount" ), (int)pGroupArray->GetCount());
1728
1729 for (unsigned int i = 0; i < pGroupArray->GetCount(); i++) {
1730 ChartGroup *pGroup = pGroupArray->Item(i);
1731 wxString s;
1732 s.Printf(_T("Group%d"), i + 1);
1733 s.Prepend(_T ( "/Groups/" ));
1734 SetPath(s);
1735
1736 Write(_T ( "GroupName" ), pGroup->m_group_name);
1737 Write(_T ( "GroupItemCount" ), (int)pGroup->m_element_array.size());
1738
1739 for (unsigned int j = 0; j < pGroup->m_element_array.size(); j++) {
1740 wxString sg;
1741 sg.Printf(_T("Group%d/Item%d"), i + 1, j);
1742 sg.Prepend(_T ( "/Groups/" ));
1743 SetPath(sg);
1744 Write(_T ( "IncludeItem" ), pGroup->m_element_array[j].m_element_name);
1745
1746 wxString t;
1747 wxArrayString u = pGroup->m_element_array[j].m_missing_name_array;
1748 if (u.GetCount()) {
1749 for (unsigned int k = 0; k < u.GetCount(); k++) {
1750 t += u[k];
1751 t += _T(";");
1752 }
1753 Write(_T ( "ExcludeItems" ), t);
1754 }
1755 }
1756 }
1757}
1758
1759void MyConfig::DestroyConfigGroups(void) {
1760 DeleteGroup(_T ( "/Groups" )); // zap
1761}
1762
1763void MyConfig::LoadConfigGroups(ChartGroupArray *pGroupArray) {
1764 SetPath(_T ( "/Groups" ));
1765 unsigned int group_count;
1766 Read(_T ( "GroupCount" ), (int *)&group_count, 0);
1767
1768 for (unsigned int i = 0; i < group_count; i++) {
1769 ChartGroup *pGroup = new ChartGroup;
1770 wxString s;
1771 s.Printf(_T("Group%d"), i + 1);
1772 s.Prepend(_T ( "/Groups/" ));
1773 SetPath(s);
1774
1775 wxString t;
1776 Read(_T ( "GroupName" ), &t);
1777 pGroup->m_group_name = t;
1778
1779 unsigned int item_count;
1780 Read(_T ( "GroupItemCount" ), (int *)&item_count);
1781 for (unsigned int j = 0; j < item_count; j++) {
1782 wxString sg;
1783 sg.Printf(_T("Group%d/Item%d"), i + 1, j);
1784 sg.Prepend(_T ( "/Groups/" ));
1785 SetPath(sg);
1786
1787 wxString v;
1788 Read(_T ( "IncludeItem" ), &v);
1789
1790 ChartGroupElement pelement{v};
1791 wxString u;
1792 if (Read(_T ( "ExcludeItems" ), &u)) {
1793 if (!u.IsEmpty()) {
1794 wxStringTokenizer tk(u, _T(";"));
1795 while (tk.HasMoreTokens()) {
1796 wxString token = tk.GetNextToken();
1797 pelement.m_missing_name_array.Add(token);
1798 }
1799 }
1800 }
1801 pGroup->m_element_array.push_back(std::move(pelement));
1802 }
1803 pGroupArray->Add(pGroup);
1804 }
1805}
1806
1807void MyConfig::LoadCanvasConfigs(bool bApplyAsTemplate) {
1808 wxString s;
1809 canvasConfig *pcc;
1810 auto &config_array = ConfigMgr::Get().GetCanvasConfigArray();
1811
1812 SetPath(_T ( "/Canvas" ));
1813
1814 // If the canvas config has never been set/persisted, use the global settings
1815 if (!HasEntry(_T ( "CanvasConfig" ))) {
1816 pcc = new canvasConfig(0);
1817 pcc->LoadFromLegacyConfig(this);
1818 config_array.Add(pcc);
1819
1820 return;
1821 }
1822
1823 Read(_T ( "CanvasConfig" ), (int *)&g_canvasConfig, 0);
1824
1825 // Do not recreate canvasConfigs when applying config dynamically
1826 if (config_array.GetCount() == 0) { // This is initial load from startup
1827 s.Printf(_T("/Canvas/CanvasConfig%d"), 1);
1828 SetPath(s);
1829 canvasConfig *pcca = new canvasConfig(0);
1830 LoadConfigCanvas(pcca, bApplyAsTemplate);
1831 config_array.Add(pcca);
1832
1833 s.Printf(_T("/Canvas/CanvasConfig%d"), 2);
1834 SetPath(s);
1835 pcca = new canvasConfig(1);
1836 LoadConfigCanvas(pcca, bApplyAsTemplate);
1837 config_array.Add(pcca);
1838 } else { // This is a dynamic (i.e. Template) load
1839 canvasConfig *pcca = config_array[0];
1840 s.Printf(_T("/Canvas/CanvasConfig%d"), 1);
1841 SetPath(s);
1842 LoadConfigCanvas(pcca, bApplyAsTemplate);
1843
1844 if (config_array.GetCount() > 1) {
1845 canvasConfig *pcca = config_array[1];
1846 s.Printf(_T("/Canvas/CanvasConfig%d"), 2);
1847 SetPath(s);
1848 LoadConfigCanvas(pcca, bApplyAsTemplate);
1849 } else {
1850 s.Printf(_T("/Canvas/CanvasConfig%d"), 2);
1851 SetPath(s);
1852 pcca = new canvasConfig(1);
1853 LoadConfigCanvas(pcca, bApplyAsTemplate);
1854 config_array.Add(pcca);
1855 }
1856 }
1857}
1858
1859void MyConfig::LoadConfigCanvas(canvasConfig *cConfig, bool bApplyAsTemplate) {
1860 wxString st;
1861 double st_lat, st_lon;
1862
1863 if (!bApplyAsTemplate) {
1864 // Reasonable starting point
1865 cConfig->iLat = START_LAT; // display viewpoint
1866 cConfig->iLon = START_LON;
1867
1868 if (Read(_T ( "canvasVPLatLon" ), &st)) {
1869 sscanf(st.mb_str(wxConvUTF8), "%lf,%lf", &st_lat, &st_lon);
1870
1871 // Sanity check the lat/lon...both have to be reasonable.
1872 if (fabs(st_lon) < 360.) {
1873 while (st_lon < -180.) st_lon += 360.;
1874
1875 while (st_lon > 180.) st_lon -= 360.;
1876
1877 cConfig->iLon = st_lon;
1878 }
1879
1880 if (fabs(st_lat) < 90.0) cConfig->iLat = st_lat;
1881 }
1882
1883 cConfig->iScale = .0003; // decent initial value
1884 cConfig->iRotation = 0;
1885
1886 double st_view_scale;
1887 if (Read(wxString(_T ( "canvasVPScale" )), &st)) {
1888 sscanf(st.mb_str(wxConvUTF8), "%lf", &st_view_scale);
1889 // Sanity check the scale
1890 st_view_scale = fmax(st_view_scale, .001 / 32);
1891 st_view_scale = fmin(st_view_scale, 4);
1892 cConfig->iScale = st_view_scale;
1893 }
1894
1895 double st_rotation;
1896 if (Read(wxString(_T ( "canvasVPRotation" )), &st)) {
1897 sscanf(st.mb_str(wxConvUTF8), "%lf", &st_rotation);
1898 // Sanity check the rotation
1899 st_rotation = fmin(st_rotation, 360);
1900 st_rotation = fmax(st_rotation, 0);
1901 cConfig->iRotation = st_rotation * PI / 180.;
1902 }
1903
1904 Read(_T ( "canvasInitialdBIndex" ), &cConfig->DBindex, 0);
1905 Read(_T ( "canvasbFollow" ), &cConfig->bFollow, 0);
1906
1907 Read(_T ( "canvasCourseUp" ), &cConfig->bCourseUp, 0);
1908 Read(_T ( "canvasHeadUp" ), &cConfig->bHeadUp, 0);
1909 Read(_T ( "canvasLookahead" ), &cConfig->bLookahead, 0);
1910 }
1911
1912 Read(_T ( "ActiveChartGroup" ), &cConfig->GroupID, 0);
1913
1914 // Special check for group selection when applied as template
1915 if (cConfig->GroupID && bApplyAsTemplate) {
1916 if (cConfig->GroupID > (int)g_pGroupArray->GetCount()) cConfig->GroupID = 0;
1917 }
1918
1919 Read(_T ( "canvasShowTides" ), &cConfig->bShowTides, 0);
1920 Read(_T ( "canvasShowCurrents" ), &cConfig->bShowCurrents, 0);
1921
1922 Read(_T ( "canvasQuilt" ), &cConfig->bQuilt, 1);
1923 Read(_T ( "canvasShowGrid" ), &cConfig->bShowGrid, 0);
1924 Read(_T ( "canvasShowOutlines" ), &cConfig->bShowOutlines, 0);
1925 Read(_T ( "canvasShowDepthUnits" ), &cConfig->bShowDepthUnits, 0);
1926
1927 Read(_T ( "canvasShowAIS" ), &cConfig->bShowAIS, 1);
1928 Read(_T ( "canvasAttenAIS" ), &cConfig->bAttenAIS, 0);
1929
1930 // ENC options
1931 Read(_T ( "canvasShowENCText" ), &cConfig->bShowENCText, 1);
1932 Read(_T ( "canvasENCDisplayCategory" ), &cConfig->nENCDisplayCategory,
1933 STANDARD);
1934 Read(_T ( "canvasENCShowDepths" ), &cConfig->bShowENCDepths, 1);
1935 Read(_T ( "canvasENCShowBuoyLabels" ), &cConfig->bShowENCBuoyLabels, 1);
1936 Read(_T ( "canvasENCShowLightDescriptions" ),
1937 &cConfig->bShowENCLightDescriptions, 1);
1938 Read(_T ( "canvasENCShowLights" ), &cConfig->bShowENCLights, 1);
1939 Read(_T ( "canvasENCShowVisibleSectorLights" ),
1940 &cConfig->bShowENCVisibleSectorLights, 0);
1941 Read(_T ( "canvasENCShowAnchorInfo" ), &cConfig->bShowENCAnchorInfo, 0);
1942 Read(_T ( "canvasENCShowDataQuality" ), &cConfig->bShowENCDataQuality, 0);
1943
1944 int sx, sy;
1945 Read(_T ( "canvasSizeX" ), &sx, 0);
1946 Read(_T ( "canvasSizeY" ), &sy, 0);
1947 cConfig->canvasSize = wxSize(sx, sy);
1948}
1949
1950void MyConfig::SaveCanvasConfigs() {
1951 auto &config_array = ConfigMgr::Get().GetCanvasConfigArray();
1952
1953 SetPath(_T ( "/Canvas" ));
1954 Write(_T ( "CanvasConfig" ), (int)g_canvasConfig);
1955
1956 wxString s;
1957 canvasConfig *pcc;
1958
1959 switch (g_canvasConfig) {
1960 case 0:
1961 default:
1962
1963 s.Printf(_T("/Canvas/CanvasConfig%d"), 1);
1964 SetPath(s);
1965
1966 if (config_array.GetCount() > 0) {
1967 pcc = config_array.Item(0);
1968 if (pcc) {
1969 SaveConfigCanvas(pcc);
1970 }
1971 }
1972 break;
1973
1974 case 1:
1975
1976 if (config_array.GetCount() > 1) {
1977 s.Printf(_T("/Canvas/CanvasConfig%d"), 1);
1978 SetPath(s);
1979 pcc = config_array.Item(0);
1980 if (pcc) {
1981 SaveConfigCanvas(pcc);
1982 }
1983
1984 s.Printf(_T("/Canvas/CanvasConfig%d"), 2);
1985 SetPath(s);
1986 pcc = config_array.Item(1);
1987 if (pcc) {
1988 SaveConfigCanvas(pcc);
1989 }
1990 }
1991 break;
1992 }
1993}
1994
1995void MyConfig::SaveConfigCanvas(canvasConfig *cConfig) {
1996 wxString st1;
1997
1998 if (cConfig->canvas) {
1999 ViewPort vp = cConfig->canvas->GetVP();
2000
2001 if (vp.IsValid()) {
2002 st1.Printf(_T ( "%10.4f,%10.4f" ), vp.clat, vp.clon);
2003 Write(_T ( "canvasVPLatLon" ), st1);
2004 st1.Printf(_T ( "%g" ), vp.view_scale_ppm);
2005 Write(_T ( "canvasVPScale" ), st1);
2006 st1.Printf(_T ( "%i" ), ((int)(vp.rotation * 180 / PI)) % 360);
2007 Write(_T ( "canvasVPRotation" ), st1);
2008 }
2009
2010 int restore_dbindex = 0;
2011 ChartStack *pcs = cConfig->canvas->GetpCurrentStack();
2012 if (pcs) restore_dbindex = pcs->GetCurrentEntrydbIndex();
2013 if (cConfig->canvas->GetQuiltMode())
2014 restore_dbindex = cConfig->canvas->GetQuiltReferenceChartIndex();
2015 Write(_T ( "canvasInitialdBIndex" ), restore_dbindex);
2016
2017 Write(_T ( "canvasbFollow" ), cConfig->canvas->m_bFollow);
2018 Write(_T ( "ActiveChartGroup" ), cConfig->canvas->m_groupIndex);
2019
2020 Write(_T ( "canvasQuilt" ), cConfig->canvas->GetQuiltMode());
2021 Write(_T ( "canvasShowGrid" ), cConfig->canvas->GetShowGrid());
2022 Write(_T ( "canvasShowOutlines" ), cConfig->canvas->GetShowOutlines());
2023 Write(_T ( "canvasShowDepthUnits" ), cConfig->canvas->GetShowDepthUnits());
2024
2025 Write(_T ( "canvasShowAIS" ), cConfig->canvas->GetShowAIS());
2026 Write(_T ( "canvasAttenAIS" ), cConfig->canvas->GetAttenAIS());
2027
2028 Write(_T ( "canvasShowTides" ), cConfig->canvas->GetbShowTide());
2029 Write(_T ( "canvasShowCurrents" ), cConfig->canvas->GetbShowCurrent());
2030
2031 // ENC options
2032 Write(_T ( "canvasShowENCText" ), cConfig->canvas->GetShowENCText());
2033 Write(_T ( "canvasENCDisplayCategory" ),
2034 cConfig->canvas->GetENCDisplayCategory());
2035 Write(_T ( "canvasENCShowDepths" ), cConfig->canvas->GetShowENCDepth());
2036 Write(_T ( "canvasENCShowBuoyLabels" ),
2037 cConfig->canvas->GetShowENCBuoyLabels());
2038 Write(_T ( "canvasENCShowLightDescriptions" ),
2039 cConfig->canvas->GetShowENCLightDesc());
2040 Write(_T ( "canvasENCShowLights" ), cConfig->canvas->GetShowENCLights());
2041 Write(_T ( "canvasENCShowVisibleSectorLights" ),
2042 cConfig->canvas->GetShowVisibleSectors());
2043 Write(_T ( "canvasENCShowAnchorInfo" ),
2044 cConfig->canvas->GetShowENCAnchor());
2045 Write(_T ( "canvasENCShowDataQuality" ),
2046 cConfig->canvas->GetShowENCDataQual());
2047 Write(_T ( "canvasCourseUp" ),
2048 cConfig->canvas->GetUpMode() == COURSE_UP_MODE);
2049 Write(_T ( "canvasHeadUp" ), cConfig->canvas->GetUpMode() == HEAD_UP_MODE);
2050 Write(_T ( "canvasLookahead" ), cConfig->canvas->GetLookahead());
2051
2052 int width = cConfig->canvas->GetSize().x;
2053 // if(cConfig->canvas->IsPrimaryCanvas()){
2054 // width = wxMax(width, gFrame->GetClientSize().x / 10);
2055 // }
2056 // else{
2057 // width = wxMin(width, gFrame->GetClientSize().x * 9 / 10);
2058 // }
2059
2060 Write(_T ( "canvasSizeX" ), width);
2061 Write(_T ( "canvasSizeY" ), cConfig->canvas->GetSize().y);
2062 }
2063}
2064
2065void MyConfig::UpdateSettings() {
2066 // Temporarily suppress logging of trivial non-fatal wxLogSysError() messages
2067 // provoked by Android security...
2068#ifdef __ANDROID__
2069 wxLogNull logNo;
2070#endif
2071
2072 // Global options and settings
2073 SetPath(_T ( "/Settings" ));
2074
2075 Write(_T ( "LastAppliedTemplate" ), g_lastAppliedTemplateGUID);
2076 Write(_T ( "CompatOS" ), g_compatOS);
2077 Write(_T ( "CompatOsVersion" ), g_compatOsVersion);
2078 Write(_T ( "ConfigVersionString" ), g_config_version_string);
2079 if (wxIsEmpty(g_CmdSoundString)) g_CmdSoundString = wxString(OCPN_SOUND_CMD);
2080 Write(_T( "CmdSoundString" ), g_CmdSoundString);
2081 Write(_T ( "NavMessageShown" ), n_NavMessageShown);
2082 Write(_T ( "InlandEcdis" ), g_bInlandEcdis);
2083
2084 Write(_T ( "AndroidVersionCode" ), g_AndroidVersionCode);
2085
2086 Write(_T ( "UIexpert" ), g_bUIexpert);
2087 Write(_T( "SpaceDropMark" ), g_bSpaceDropMark);
2088 // Write( _T ( "UIStyle" ), g_StyleManager->GetStyleNextInvocation() );
2089 // //Not desired for O5 MUI
2090
2091 Write(_T ( "ShowStatusBar" ), g_bShowStatusBar);
2092#ifndef __WXOSX__
2093 Write(_T ( "ShowMenuBar" ), g_bShowMenuBar);
2094#endif
2095 Write(_T ( "DefaultFontSize" ), g_default_font_size);
2096 Write(_T ( "DefaultFontFacename" ), g_default_font_facename);
2097
2098 Write(_T ( "Fullscreen" ), g_bFullscreen);
2099 Write(_T ( "ShowCompassWindow" ), g_bShowCompassWin);
2100 Write(_T ( "SetSystemTime" ), s_bSetSystemTime);
2101 Write(_T ( "ShowGrid" ), g_bDisplayGrid);
2102 Write(_T ( "PlayShipsBells" ), g_bPlayShipsBells);
2103 Write(_T ( "SoundDeviceIndex" ), g_iSoundDeviceIndex);
2104 Write(_T ( "FullscreenToolbar" ), g_bFullscreenToolbar);
2105 Write(_T ( "TransparentToolbar" ), g_bTransparentToolbar);
2106 Write(_T ( "PermanentMOBIcon" ), g_bPermanentMOBIcon);
2107 Write(_T ( "ShowLayers" ), g_bShowLayers);
2108 Write(_T ( "AutoAnchorDrop" ), g_bAutoAnchorMark);
2109 Write(_T ( "ShowChartOutlines" ), g_bShowOutlines);
2110 Write(_T ( "ShowActiveRouteTotal" ), g_bShowRouteTotal);
2111 Write(_T ( "ShowActiveRouteHighway" ), g_bShowActiveRouteHighway);
2112 Write(_T ( "SDMMFormat" ), g_iSDMMFormat);
2113 Write(_T ( "MostRecentGPSUploadConnection" ), g_uploadConnection);
2114 Write(_T ( "ShowChartBar" ), g_bShowChartBar);
2115
2116 Write(_T ( "GUIScaleFactor" ), g_GUIScaleFactor);
2117 Write(_T ( "ChartObjectScaleFactor" ), g_ChartScaleFactor);
2118 Write(_T ( "ShipScaleFactor" ), g_ShipScaleFactor);
2119 Write(_T ( "ENCSoundingScaleFactor" ), g_ENCSoundingScaleFactor);
2120 Write(_T ( "ENCTextScaleFactor" ), g_ENCTextScaleFactor);
2121 Write(_T ( "ObjQueryAppendFilesExt" ), g_ObjQFileExt);
2122
2123 // Plugin catalog persistent values.
2124 Write(_T( "CatalogCustomURL"), g_catalog_custom_url);
2125 Write(_T( "CatalogChannel"), g_catalog_channel);
2126
2127 Write("NetmaskBits", g_netmask_bits);
2128 Write(_T ( "FilterNMEA_Avg" ), g_bfilter_cogsog);
2129 Write(_T ( "FilterNMEA_Sec" ), g_COGFilterSec);
2130
2131 Write(_T ( "TrackContinuous" ), g_btrackContinuous);
2132
2133 Write(_T ( "ShowTrue" ), g_bShowTrue);
2134 Write(_T ( "ShowMag" ), g_bShowMag);
2135 Write(_T ( "UserMagVariation" ), wxString::Format(_T("%.2f"), g_UserVar));
2136
2137 Write(_T ( "CM93DetailFactor" ), g_cm93_zoom_factor);
2138 Write(_T ( "CM93DetailZoomPosX" ), g_detailslider_dialog_x);
2139 Write(_T ( "CM93DetailZoomPosY" ), g_detailslider_dialog_y);
2140 Write(_T ( "ShowCM93DetailSlider" ), g_bShowDetailSlider);
2141
2142 Write(_T ( "SkewToNorthUp" ), g_bskew_comp);
2143 if (!g_bdisable_opengl) { // Only modify the saved value if OpenGL is not
2144 // force-disabled from the command line
2145 Write(_T ( "OpenGL" ), g_bopengl);
2146 }
2147 Write(_T ( "SoftwareGL" ), g_bSoftwareGL);
2148
2149 Write(_T ( "ZoomDetailFactor" ), g_chart_zoom_modifier_raster);
2150 Write(_T ( "ZoomDetailFactorVector" ), g_chart_zoom_modifier_vector);
2151
2152 Write(_T ( "FogOnOverzoom" ), g_fog_overzoom);
2153 Write(_T ( "OverzoomVectorScale" ), g_oz_vector_scale);
2154 Write(_T ( "OverzoomEmphasisBase" ), g_overzoom_emphasis_base);
2155 Write(_T ( "PlusMinusZoomFactor" ), g_plus_minus_zoom_factor);
2156 Write("MouseZoomSensitivity",
2157 MouseZoom::ui_to_config(g_mouse_zoom_sensitivity_ui));
2158 Write(_T ( "ShowMUIZoomButtons" ), g_bShowMuiZoomButtons);
2159
2160#ifdef ocpnUSE_GL
2161 /* opengl options */
2162 Write(_T ( "UseAcceleratedPanning" ), g_GLOptions.m_bUseAcceleratedPanning);
2163
2164 Write(_T ( "GPUTextureCompression" ), g_GLOptions.m_bTextureCompression);
2165 Write(_T ( "GPUTextureCompressionCaching" ),
2166 g_GLOptions.m_bTextureCompressionCaching);
2167 Write(_T ( "GPUTextureDimension" ), g_GLOptions.m_iTextureDimension);
2168 Write(_T ( "GPUTextureMemSize" ), g_GLOptions.m_iTextureMemorySize);
2169 Write(_T ( "PolygonSmoothing" ), g_GLOptions.m_GLPolygonSmoothing);
2170 Write(_T ( "LineSmoothing" ), g_GLOptions.m_GLLineSmoothing);
2171#endif
2172 Write(_T ( "SmoothPanZoom" ), g_bsmoothpanzoom);
2173
2174 Write(_T ( "CourseUpMode" ), g_bCourseUp);
2175 if (!g_bInlandEcdis) Write(_T ( "LookAheadMode" ), g_bLookAhead);
2176 Write(_T ( "TenHzUpdate" ), g_btenhertz);
2177
2178 Write(_T ( "COGUPAvgSeconds" ), g_COGAvgSec);
2179 Write(_T ( "UseMagAPB" ), g_bMagneticAPB);
2180
2181 Write(_T ( "OwnshipCOGPredictorMinutes" ), g_ownship_predictor_minutes);
2182 Write(_T ( "OwnshipCOGPredictorStyle" ), g_cog_predictor_style);
2183 Write(_T ( "OwnshipCOGPredictorColor" ), g_cog_predictor_color);
2184 Write(_T ( "OwnshipCOGPredictorEndmarker" ), g_cog_predictor_endmarker);
2185 Write(_T ( "OwnshipCOGPredictorWidth" ), g_cog_predictor_width);
2186 Write(_T ( "OwnshipHDTPredictorStyle" ), g_ownship_HDTpredictor_style);
2187 Write(_T ( "OwnshipHDTPredictorColor" ), g_ownship_HDTpredictor_color);
2188 Write(_T ( "OwnshipHDTPredictorEndmarker" ),
2189 g_ownship_HDTpredictor_endmarker);
2190 Write(_T ( "OwnShipMMSINumber" ), g_OwnShipmmsi);
2191 Write(_T ( "OwnshipHDTPredictorWidth" ), g_ownship_HDTpredictor_width);
2192 Write(_T ( "OwnshipHDTPredictorMiles" ), g_ownship_HDTpredictor_miles);
2193
2194 Write(_T ( "OwnShipIconType" ), g_OwnShipIconType);
2195 Write(_T ( "OwnShipLength" ), g_n_ownship_length_meters);
2196 Write(_T ( "OwnShipWidth" ), g_n_ownship_beam_meters);
2197 Write(_T ( "OwnShipGPSOffsetX" ), g_n_gps_antenna_offset_x);
2198 Write(_T ( "OwnShipGPSOffsetY" ), g_n_gps_antenna_offset_y);
2199 Write(_T ( "OwnShipMinSize" ), g_n_ownship_min_mm);
2200 Write(_T ( "OwnShipSogCogCalc" ), g_own_ship_sog_cog_calc);
2201 Write(_T ( "OwnShipSogCogCalcDampSec"), g_own_ship_sog_cog_calc_damp_sec);
2202 Write(_T ( "ShowDirectRouteLine"), g_bShowShipToActive);
2203 Write(_T ( "DirectRouteLineStyle"), g_shipToActiveStyle);
2204 Write(_T ( "DirectRouteLineColor" ), g_shipToActiveColor);
2205
2206 wxString racr;
2207 // racr.Printf( _T ( "%g" ), g_n_arrival_circle_radius );
2208 // Write( _T ( "RouteArrivalCircleRadius" ), racr );
2209 Write(_T ( "RouteArrivalCircleRadius" ),
2210 wxString::Format(_T("%.2f"), g_n_arrival_circle_radius));
2211
2212 Write(_T ( "ChartQuilting" ), g_bQuiltEnable);
2213
2214 Write(_T ( "PreserveScaleOnX" ), g_bPreserveScaleOnX);
2215
2216 Write(_T ( "StartWithTrackActive" ), g_bTrackCarryOver);
2217 Write(_T ( "AutomaticDailyTracks" ), g_bTrackDaily);
2218 Write(_T ( "TrackRotateAt" ), g_track_rotate_time);
2219 Write(_T ( "TrackRotateTimeType" ), g_track_rotate_time_type);
2220 Write(_T ( "HighlightTracks" ), g_bHighliteTracks);
2221
2222 Write(_T ( "DateTimeFormat" ), g_datetime_format);
2223 Write(_T ( "InitialStackIndex" ), g_restore_stackindex);
2224 Write(_T ( "InitialdBIndex" ), g_restore_dbindex);
2225
2226 Write(_T( "NMEAAPBPrecision" ), g_NMEAAPBPrecision);
2227
2228 Write(_T("TalkerIdText"), g_TalkerIdText);
2229 Write(_T("ShowTrackPointTime"), g_bShowTrackPointTime);
2230
2231 Write(_T ( "AnchorWatch1GUID" ), g_AW1GUID);
2232 Write(_T ( "AnchorWatch2GUID" ), g_AW2GUID);
2233
2234 Write(_T ( "ToolbarX" ), g_maintoolbar_x);
2235 Write(_T ( "ToolbarY" ), g_maintoolbar_y);
2236 // Write( _T ( "ToolbarOrient" ), g_maintoolbar_orient );
2237
2238 Write(_T ( "iENCToolbarX" ), g_iENCToolbarPosX);
2239 Write(_T ( "iENCToolbarY" ), g_iENCToolbarPosY);
2240
2241 if (!g_bInlandEcdis) {
2242 Write(_T ( "GlobalToolbarConfig" ), g_toolbarConfig);
2243 Write(_T ( "DistanceFormat" ), g_iDistanceFormat);
2244 Write(_T ( "SpeedFormat" ), g_iSpeedFormat);
2245 Write(_T ( "WindSpeedFormat" ), g_iWindSpeedFormat);
2246 Write(_T ( "ShowDepthUnits" ), g_bShowDepthUnits);
2247 Write(_T ( "TemperatureFormat" ), g_iTempFormat);
2248 }
2249 Write(_T ( "GPSIdent" ), g_GPS_Ident);
2250 Write("ActiveRoute", g_active_route);
2251 Write("PersistActiveRoute", g_persist_active_route);
2252 Write(_T ( "UseGarminHostUpload" ), g_bGarminHostUpload);
2253
2254 Write(_T ( "MobileTouch" ), g_btouch);
2255 Write(_T ( "ResponsiveGraphics" ), g_bresponsive);
2256 Write(_T ( "EnableRolloverBlock" ), g_bRollover);
2257
2258 Write(_T ( "AutoHideToolbar" ), g_bAutoHideToolbar);
2259 Write(_T ( "AutoHideToolbarSecs" ), g_nAutoHideToolbar);
2260
2261 wxString st0;
2262 for (const auto &mm : g_config_display_size_mm) {
2263 st0.Append(wxString::Format(_T ( "%zu," ), mm));
2264 }
2265 st0.RemoveLast(); // Strip last comma
2266 Write(_T ( "DisplaySizeMM" ), st0);
2267 Write(_T ( "DisplaySizeManual" ), g_config_display_size_manual);
2268
2269 Write(_T ( "SelectionRadiusMM" ), g_selection_radius_mm);
2270 Write(_T ( "SelectionRadiusTouchMM" ), g_selection_radius_touch_mm);
2271
2272 st0.Printf(_T ( "%g" ), g_PlanSpeed);
2273 Write(_T ( "PlanSpeed" ), st0);
2274
2275 if (g_bLayersLoaded) {
2276 wxString vis, invis, visnames, invisnames;
2277 LayerList::iterator it;
2278 int index = 0;
2279 for (it = (*pLayerList).begin(); it != (*pLayerList).end(); ++it, ++index) {
2280 Layer *lay = (Layer *)(*it);
2281 if (lay->IsVisibleOnChart())
2282 vis += (lay->m_LayerName) + _T(";");
2283 else
2284 invis += (lay->m_LayerName) + _T(";");
2285
2286 if (lay->HasVisibleNames() == wxCHK_CHECKED) {
2287 visnames += (lay->m_LayerName) + _T(";");
2288 } else if (lay->HasVisibleNames() == wxCHK_UNCHECKED) {
2289 invisnames += (lay->m_LayerName) + _T(";");
2290 }
2291 }
2292 Write(_T ( "VisibleLayers" ), vis);
2293 Write(_T ( "InvisibleLayers" ), invis);
2294 Write(_T ( "VisNameInLayers" ), visnames);
2295 Write(_T ( "InvisNameInLayers" ), invisnames);
2296 }
2297 Write(_T ( "Locale" ), g_locale);
2298 Write(_T ( "LocaleOverride" ), g_localeOverride);
2299
2300 Write(_T ( "KeepNavobjBackups" ), g_navobjbackups);
2301 Write(_T ( "LegacyInputCOMPortFilterBehaviour" ),
2302 g_b_legacy_input_filter_behaviour);
2303 Write(_T( "AdvanceRouteWaypointOnArrivalOnly" ),
2304 g_bAdvanceRouteWaypointOnArrivalOnly);
2305 Write("EnableRootMenuDebug", g_enable_root_menu_debug);
2306
2307 // LIVE ETA OPTION
2308 Write(_T( "LiveETA" ), g_bShowLiveETA);
2309 Write(_T( "DefaultBoatSpeed" ), g_defaultBoatSpeed);
2310
2311 // S57 Object Filter Settings
2312
2313 SetPath(_T ( "/Settings/ObjectFilter" ));
2314
2315 if (ps52plib) {
2316 for (unsigned int iPtr = 0; iPtr < ps52plib->pOBJLArray->GetCount();
2317 iPtr++) {
2318 OBJLElement *pOLE = (OBJLElement *)(ps52plib->pOBJLArray->Item(iPtr));
2319
2320 wxString st1(_T ( "viz" ));
2321 char name[7];
2322 strncpy(name, pOLE->OBJLName, 6);
2323 name[6] = 0;
2324 st1.Append(wxString(name, wxConvUTF8));
2325 Write(st1, pOLE->nViz);
2326 }
2327 }
2328
2329 // Global State
2330
2331 SetPath(_T ( "/Settings/GlobalState" ));
2332
2333 wxString st1;
2334
2335 // if( cc1 ) {
2336 // ViewPort vp = cc1->GetVP();
2337 //
2338 // if( vp.IsValid() ) {
2339 // st1.Printf( _T ( "%10.4f,%10.4f" ), vp.clat, vp.clon );
2340 // Write( _T ( "VPLatLon" ), st1 );
2341 // st1.Printf( _T ( "%g" ), vp.view_scale_ppm );
2342 // Write( _T ( "VPScale" ), st1 );
2343 // st1.Printf( _T ( "%i" ), ((int)(vp.rotation * 180 / PI)) % 360
2344 // ); Write( _T ( "VPRotation" ), st1 );
2345 // }
2346 // }
2347
2348 st1.Printf(_T ( "%10.4f, %10.4f" ), gLat, gLon);
2349 Write(_T ( "OwnShipLatLon" ), st1);
2350
2351 // Various Options
2352 SetPath(_T ( "/Settings/GlobalState" ));
2353 if (!g_bInlandEcdis)
2354 Write(_T ( "nColorScheme" ), (int)gFrame->GetColorScheme());
2355
2356 Write(_T ( "FrameWinX" ), g_nframewin_x);
2357 Write(_T ( "FrameWinY" ), g_nframewin_y);
2358 Write(_T ( "FrameWinPosX" ), g_nframewin_posx);
2359 Write(_T ( "FrameWinPosY" ), g_nframewin_posy);
2360 Write(_T ( "FrameMax" ), g_bframemax);
2361
2362 Write(_T ( "ClientPosX" ), g_lastClientRectx);
2363 Write(_T ( "ClientPosY" ), g_lastClientRecty);
2364 Write(_T ( "ClientSzX" ), g_lastClientRectw);
2365 Write(_T ( "ClientSzY" ), g_lastClientRecth);
2366
2367 Write(_T ( "S52_DEPTH_UNIT_SHOW" ), g_nDepthUnitDisplay);
2368
2369 Write(_T( "RoutePropSizeX" ), g_route_prop_sx);
2370 Write(_T( "RoutePropSizeY" ), g_route_prop_sy);
2371 Write(_T( "RoutePropPosX" ), g_route_prop_x);
2372 Write(_T( "RoutePropPosY" ), g_route_prop_y);
2373
2374 // Sounds
2375 SetPath(_T ( "/Settings/Audio" ));
2376 Write(_T ( "AISAlertSoundFile" ), g_AIS_sound_file);
2377 Write(_T ( "DSCAlertSoundFile" ), g_DSC_sound_file);
2378 Write(_T ( "SARTAlertSoundFile" ), g_SART_sound_file);
2379 Write(_T ( "AnchorAlarmSoundFile" ), g_anchorwatch_sound_file);
2380
2381 Write(_T ( "bAIS_GCPA_AlertAudio" ), g_bAIS_GCPA_Alert_Audio);
2382 Write(_T ( "bAIS_SART_AlertAudio" ), g_bAIS_SART_Alert_Audio);
2383 Write(_T ( "bAIS_DSC_AlertAudio" ), g_bAIS_DSC_Alert_Audio);
2384 Write(_T ( "bAnchorAlertAudio" ), g_bAnchor_Alert_Audio);
2385
2386 // AIS
2387 SetPath(_T ( "/Settings/AIS" ));
2388
2389 Write(_T ( "bNoCPAMax" ), g_bCPAMax);
2390 Write(_T ( "NoCPAMaxNMi" ), g_CPAMax_NM);
2391 Write(_T ( "bCPAWarn" ), g_bCPAWarn);
2392 Write(_T ( "CPAWarnNMi" ), g_CPAWarn_NM);
2393 Write(_T ( "bTCPAMax" ), g_bTCPA_Max);
2394 Write(_T ( "TCPAMaxMinutes" ), g_TCPA_Max);
2395 Write(_T ( "bMarkLostTargets" ), g_bMarkLost);
2396 Write(_T ( "MarkLost_Minutes" ), g_MarkLost_Mins);
2397 Write(_T ( "bRemoveLostTargets" ), g_bRemoveLost);
2398 Write(_T ( "RemoveLost_Minutes" ), g_RemoveLost_Mins);
2399 Write(_T ( "bShowCOGArrows" ), g_bShowCOG);
2400 Write(_T ( "bSyncCogPredictors" ), g_bSyncCogPredictors);
2401 Write(_T ( "CogArrowMinutes" ), g_ShowCOG_Mins);
2402 Write(_T ( "bShowTargetTracks" ), g_bAISShowTracks);
2403 Write(_T ( "TargetTracksMinutes" ), g_AISShowTracks_Mins);
2404
2405 Write(_T ( "bHideMooredTargets" ), g_bHideMoored);
2406 Write(_T ( "MooredTargetMaxSpeedKnots" ), g_ShowMoored_Kts);
2407
2408 Write(_T ( "bAISAlertDialog" ), g_bAIS_CPA_Alert);
2409 Write(_T ( "bAISAlertAudio" ), g_bAIS_CPA_Alert_Audio);
2410
2411 Write(_T ( "AISAlertAudioFile" ), g_sAIS_Alert_Sound_File);
2412 Write(_T ( "bAISAlertSuppressMoored" ), g_bAIS_CPA_Alert_Suppress_Moored);
2413 Write(_T ( "bShowAreaNotices" ), g_bShowAreaNotices);
2414 Write(_T ( "bDrawAISSize" ), g_bDrawAISSize);
2415 Write(_T ( "bDrawAISRealtime" ), g_bDrawAISRealtime);
2416 Write(_T ( "AISRealtimeMinSpeedKnots" ), g_AIS_RealtPred_Kts);
2417 Write(_T ( "bShowAISName" ), g_bShowAISName);
2418 Write(_T ( "ShowAISTargetNameScale" ), g_Show_Target_Name_Scale);
2419 Write(_T ( "bWplIsAprsPositionReport" ), g_bWplUsePosition);
2420 Write(_T ( "WplSelAction" ), g_WplAction);
2421 Write(_T ( "AISCOGPredictorWidth" ), g_ais_cog_predictor_width);
2422 Write(_T ( "bShowScaledTargets" ), g_bAllowShowScaled);
2423 Write(_T ( "AISScaledNumber" ), g_ShowScaled_Num);
2424 Write(_T ( "AISScaledNumberWeightSOG" ), g_ScaledNumWeightSOG);
2425 Write(_T ( "AISScaledNumberWeightCPA" ), g_ScaledNumWeightCPA);
2426 Write(_T ( "AISScaledNumberWeightTCPA" ), g_ScaledNumWeightTCPA);
2427 Write(_T ( "AISScaledNumberWeightRange" ), g_ScaledNumWeightRange);
2428 Write(_T ( "AISScaledNumberWeightSizeOfTarget" ), g_ScaledNumWeightSizeOfT);
2429 Write(_T ( "AISScaledSizeMinimal" ), g_ScaledSizeMinimal);
2430 Write(_T ( "AISShowScaled"), g_bShowScaled);
2431
2432 Write(_T ( "AlertDialogSizeX" ), g_ais_alert_dialog_sx);
2433 Write(_T ( "AlertDialogSizeY" ), g_ais_alert_dialog_sy);
2434 Write(_T ( "AlertDialogPosX" ), g_ais_alert_dialog_x);
2435 Write(_T ( "AlertDialogPosY" ), g_ais_alert_dialog_y);
2436 Write(_T ( "QueryDialogPosX" ), g_ais_query_dialog_x);
2437 Write(_T ( "QueryDialogPosY" ), g_ais_query_dialog_y);
2438 Write(_T ( "AISTargetListPerspective" ), g_AisTargetList_perspective);
2439 Write(_T ( "AISTargetListRange" ), g_AisTargetList_range);
2440 Write(_T ( "AISTargetListSortColumn" ), g_AisTargetList_sortColumn);
2441 Write(_T ( "bAISTargetListSortReverse" ), g_bAisTargetList_sortReverse);
2442 Write(_T ( "AISTargetListColumnSpec" ), g_AisTargetList_column_spec);
2443 Write(_T ("AISTargetListColumnOrder"), g_AisTargetList_column_order);
2444
2445 Write(_T ( "S57QueryDialogSizeX" ), g_S57_dialog_sx);
2446 Write(_T ( "S57QueryDialogSizeY" ), g_S57_dialog_sy);
2447 Write(_T ( "S57QueryExtraDialogSizeX" ), g_S57_extradialog_sx);
2448 Write(_T ( "S57QueryExtraDialogSizeY" ), g_S57_extradialog_sy);
2449
2450 Write(_T ( "bAISRolloverShowClass" ), g_bAISRolloverShowClass);
2451 Write(_T ( "bAISRolloverShowCOG" ), g_bAISRolloverShowCOG);
2452 Write(_T ( "bAISRolloverShowCPA" ), g_bAISRolloverShowCPA);
2453
2454 Write(_T ( "bAISAlertAckTimeout" ), g_bAIS_ACK_Timeout);
2455 Write(_T ( "AlertAckTimeoutMinutes" ), g_AckTimeout_Mins);
2456
2457 SetPath(_T ( "/Settings/GlobalState" ));
2458 if (ps52plib) {
2459 Write(_T ( "bShowS57Text" ), ps52plib->GetShowS57Text());
2460 Write(_T ( "bShowS57ImportantTextOnly" ),
2461 ps52plib->GetShowS57ImportantTextOnly());
2462 if (!g_bInlandEcdis)
2463 Write(_T ( "nDisplayCategory" ), (long)ps52plib->GetDisplayCategory());
2464 Write(_T ( "nSymbolStyle" ), (int)ps52plib->m_nSymbolStyle);
2465 Write(_T ( "nBoundaryStyle" ), (int)ps52plib->m_nBoundaryStyle);
2466
2467 Write(_T ( "bShowSoundg" ), ps52plib->m_bShowSoundg);
2468 Write(_T ( "bShowMeta" ), ps52plib->m_bShowMeta);
2469 Write(_T ( "bUseSCAMIN" ), ps52plib->m_bUseSCAMIN);
2470 Write(_T ( "bUseSUPER_SCAMIN" ), ps52plib->m_bUseSUPER_SCAMIN);
2471 Write(_T ( "bShowAtonText" ), ps52plib->m_bShowAtonText);
2472 Write(_T ( "bShowLightDescription" ), ps52plib->m_bShowLdisText);
2473 Write(_T ( "bExtendLightSectors" ), ps52plib->m_bExtendLightSectors);
2474 Write(_T ( "bDeClutterText" ), ps52plib->m_bDeClutterText);
2475 Write(_T ( "bShowNationalText" ), ps52plib->m_bShowNationalTexts);
2476
2477 Write(_T ( "S52_MAR_SAFETY_CONTOUR" ),
2478 S52_getMarinerParam(S52_MAR_SAFETY_CONTOUR));
2479 Write(_T ( "S52_MAR_SHALLOW_CONTOUR" ),
2480 S52_getMarinerParam(S52_MAR_SHALLOW_CONTOUR));
2481 Write(_T ( "S52_MAR_DEEP_CONTOUR" ),
2482 S52_getMarinerParam(S52_MAR_DEEP_CONTOUR));
2483 Write(_T ( "S52_MAR_TWO_SHADES" ), S52_getMarinerParam(S52_MAR_TWO_SHADES));
2484 Write(_T ( "S52_DEPTH_UNIT_SHOW" ), ps52plib->m_nDepthUnitDisplay);
2485 Write(_T ( "ENCSoundingScaleFactor" ), g_ENCSoundingScaleFactor);
2486 Write(_T ( "ENCTextScaleFactor" ), g_ENCTextScaleFactor);
2487 }
2488 SetPath(_T ( "/Directories" ));
2489 Write(_T ( "S57DataLocation" ), _T(""));
2490 // Write( _T ( "SENCFileLocation" ), _T("") );
2491
2492 SetPath(_T ( "/Directories" ));
2493 Write(_T ( "InitChartDir" ), *pInit_Chart_Dir);
2494 Write(_T ( "GPXIODir" ), g_gpx_path);
2495 Write(_T ( "TCDataDir" ), g_TCData_Dir);
2496 Write(_T ( "BasemapDir" ), g_Platform->NormalizePath(gWorldMapLocation));
2497 Write(_T ( "BaseShapefileDir" ),
2498 g_Platform->NormalizePath(gWorldShapefileLocation));
2499 Write(_T ( "pluginInstallDir" ), g_Platform->NormalizePath(g_winPluginDir));
2500
2501 SetPath(_T ( "/Settings/NMEADataSource" ));
2502 wxString connectionconfigs;
2503 for (size_t i = 0; i < TheConnectionParams().size(); i++) {
2504 if (i > 0) connectionconfigs.Append(_T("|"));
2505 connectionconfigs.Append(TheConnectionParams()[i]->Serialize());
2506 }
2507 Write(_T ( "DataConnections" ), connectionconfigs);
2508
2509 // Fonts
2510
2511 // Store the persistent Auxiliary Font descriptor Keys
2512 SetPath(_T ( "/Settings/AuxFontKeys" ));
2513
2514 wxArrayString keyArray = FontMgr::Get().GetAuxKeyArray();
2515 for (unsigned int i = 0; i < keyArray.GetCount(); i++) {
2516 wxString key;
2517 key.Printf(_T("Key%i"), i);
2518 wxString keyval = keyArray[i];
2519 Write(key, keyval);
2520 }
2521
2522 wxString font_path;
2523#ifdef __WXX11__
2524 font_path = (_T ( "/Settings/X11Fonts" ));
2525#endif
2526
2527#ifdef __WXGTK__
2528 font_path = (_T ( "/Settings/GTKFonts" ));
2529#endif
2530
2531#ifdef __WXMSW__
2532 font_path = (_T ( "/Settings/MSWFonts" ));
2533#endif
2534
2535#ifdef __WXMAC__
2536 font_path = (_T ( "/Settings/MacFonts" ));
2537#endif
2538
2539#ifdef __WXQT__
2540 font_path = (_T ( "/Settings/QTFonts" ));
2541#endif
2542
2543 DeleteGroup(font_path);
2544
2545 SetPath(font_path);
2546
2547 int nFonts = FontMgr::Get().GetNumFonts();
2548
2549 for (int i = 0; i < nFonts; i++) {
2550 wxString cfstring(FontMgr::Get().GetConfigString(i));
2551 wxString valstring = FontMgr::Get().GetFullConfigDesc(i);
2552 Write(cfstring, valstring);
2553 }
2554
2555 // Tide/Current Data Sources
2556 DeleteGroup(_T ( "/TideCurrentDataSources" ));
2557 SetPath(_T ( "/TideCurrentDataSources" ));
2558 unsigned int id = 0;
2559 for (auto val : TideCurrentDataSet) {
2560 wxString key;
2561 key.Printf(_T("tcds%d"), id);
2562 Write(key, wxString(val));
2563 ++id;
2564 }
2565
2566 SetPath(_T ( "/Settings/Others" ));
2567
2568 // Radar rings
2569 Write(_T ( "ShowRadarRings" ),
2570 (bool)(g_iNavAidRadarRingsNumberVisible > 0)); // 3.0.0 config support
2571 Write(_T ( "RadarRingsNumberVisible" ), g_iNavAidRadarRingsNumberVisible);
2572 Write(_T ( "RadarRingsStep" ), g_fNavAidRadarRingsStep);
2573 Write(_T ( "RadarRingsStepUnits" ), g_pNavAidRadarRingsStepUnits);
2574 Write(_T ( "RadarRingsColour" ),
2575 g_colourOwnshipRangeRingsColour.GetAsString(wxC2S_HTML_SYNTAX));
2576 Write(_T( "WaypointUseScaMin" ), g_bUseWptScaMin);
2577 Write(_T( "WaypointScaMinValue" ), g_iWpt_ScaMin);
2578 Write(_T( "WaypointUseScaMinOverrule" ), g_bOverruleScaMin);
2579 Write(_T("WaypointsShowName"), g_bShowWptName);
2580 Write(_T("UserIconsFirst"), g_bUserIconsFirst);
2581
2582 // Waypoint Radar rings
2583 Write(_T ( "WaypointRangeRingsNumber" ), g_iWaypointRangeRingsNumber);
2584 Write(_T ( "WaypointRangeRingsStep" ), g_fWaypointRangeRingsStep);
2585 Write(_T ( "WaypointRangeRingsStepUnits" ), g_iWaypointRangeRingsStepUnits);
2586 Write(_T ( "WaypointRangeRingsColour" ),
2587 g_colourWaypointRangeRingsColour.GetAsString(wxC2S_HTML_SYNTAX));
2588
2589 Write(_T ( "ConfirmObjectDeletion" ), g_bConfirmObjectDelete);
2590
2591 // Waypoint dragging with mouse; toh, 2009.02.24
2592 Write(_T ( "WaypointPreventDragging" ), g_bWayPointPreventDragging);
2593
2594 Write(_T ( "EnableZoomToCursor" ), g_bEnableZoomToCursor);
2595
2596 Write(_T ( "TrackIntervalSeconds" ), g_TrackIntervalSeconds);
2597 Write(_T ( "TrackDeltaDistance" ), g_TrackDeltaDistance);
2598 Write(_T ( "TrackPrecision" ), g_nTrackPrecision);
2599
2600 Write(_T ( "RouteLineWidth" ), g_route_line_width);
2601 Write(_T ( "TrackLineWidth" ), g_track_line_width);
2602 Write(_T ( "TrackLineColour" ),
2603 g_colourTrackLineColour.GetAsString(wxC2S_HTML_SYNTAX));
2604 Write(_T ( "DefaultWPIcon" ), g_default_wp_icon);
2605 Write(_T ( "DefaultRPIcon" ), g_default_routepoint_icon);
2606
2607 DeleteGroup(_T ( "/MmsiProperties" ));
2608 SetPath(_T ( "/MmsiProperties" ));
2609 for (unsigned int i = 0; i < g_MMSI_Props_Array.GetCount(); i++) {
2610 wxString p;
2611 p.Printf(_T("Props%d"), i);
2612 Write(p, g_MMSI_Props_Array[i]->Serialize());
2613 }
2614
2615 SaveCanvasConfigs();
2616
2617 Flush();
2618 SendMessageToAllPlugins("GLOBAL_SETTINGS_UPDATED", wxEmptyString);
2619}
2620
2621static wxFileName exportFileName(wxWindow *parent,
2622 const wxString suggestedName) {
2623 wxFileName ret;
2624 wxString path;
2625 wxString valid_name = SanitizeFileName(suggestedName);
2626
2627#ifdef __ANDROID__
2628 if (!valid_name.EndsWith(".gpx")) {
2629 wxFileName fn(valid_name);
2630 fn.ClearExt();
2631 fn.SetExt("gpx");
2632 valid_name = fn.GetFullName();
2633 }
2634#endif
2635 int response =
2636 g_Platform->DoFileSelectorDialog(parent, &path, _("Export GPX file"),
2637 g_gpx_path, valid_name, wxT("*.gpx"));
2638
2639 if (response == wxID_OK) {
2640 wxFileName fn(path);
2641 g_gpx_path = fn.GetPath();
2642 fn.SetExt(_T("gpx"));
2643
2644#ifndef __WXMAC__
2645 if (wxFileExists(fn.GetFullPath())) {
2646 int answer =
2647 OCPNMessageBox(NULL, _("Overwrite existing file?"), _T("Confirm"),
2648 wxICON_QUESTION | wxYES_NO | wxCANCEL);
2649 if (answer != wxID_YES) return ret;
2650 }
2651#endif
2652 ret = fn;
2653 }
2654 return ret;
2655}
2656
2657bool ExportGPXRoutes(wxWindow *parent, RouteList *pRoutes,
2658 const wxString suggestedName) {
2659 wxFileName fn = exportFileName(parent, suggestedName);
2660 if (fn.IsOk()) {
2662 pgpx->AddGPXRoutesList(pRoutes);
2663
2664#ifdef __ANDROID__
2665 wxString fns = androidGetCacheDir() + wxFileName::GetPathSeparator() +
2666 fn.GetFullName();
2667 pgpx->SaveFile(fns);
2668 AndroidSecureCopyFile(fns, fn.GetFullPath());
2669#else
2670 pgpx->SaveFile(fn.GetFullPath());
2671
2672#endif
2673
2674 delete pgpx;
2675
2676 return true;
2677 }
2678 return false;
2679}
2680
2681bool ExportGPXTracks(wxWindow *parent, std::vector<Track *> *pTracks,
2682 const wxString suggestedName) {
2683 wxFileName fn = exportFileName(parent, suggestedName);
2684 if (fn.IsOk()) {
2686 pgpx->AddGPXTracksList(pTracks);
2687#ifdef __ANDROID__
2688 wxString fns = androidGetCacheDir() + wxFileName::GetPathSeparator() +
2689 fn.GetFullName();
2690 pgpx->SaveFile(fns);
2691 AndroidSecureCopyFile(fns, fn.GetFullPath());
2692#else
2693 pgpx->SaveFile(fn.GetFullPath());
2694#endif
2695 delete pgpx;
2696
2697 return true;
2698 }
2699 return false;
2700}
2701
2702bool ExportGPXWaypoints(wxWindow *parent, RoutePointList *pRoutePoints,
2703 const wxString suggestedName) {
2704 wxFileName fn = exportFileName(parent, suggestedName);
2705 if (fn.IsOk()) {
2707 pgpx->AddGPXPointsList(pRoutePoints);
2708
2709#ifdef __ANDROID__
2710 wxString fns = androidGetCacheDir() + wxFileName::GetPathSeparator() +
2711 fn.GetFullName();
2712 pgpx->SaveFile(fns);
2713 AndroidSecureCopyFile(fns, fn.GetFullPath());
2714#else
2715 pgpx->SaveFile(fn.GetFullPath());
2716#endif
2717
2718 delete pgpx;
2719
2720 return true;
2721 }
2722 return false;
2723}
2724
2725void ExportGPX(wxWindow *parent, bool bviz_only, bool blayer) {
2726 wxFileName fn = exportFileName(parent, _T("userobjects.gpx"));
2727 if (fn.IsOk()) {
2728 ::wxBeginBusyCursor();
2729
2731
2732 wxGenericProgressDialog *pprog = nullptr;
2733 int count = pWayPointMan->GetWaypointList()->GetCount();
2734 int progStep = count / 32;
2735 if (count > 200) {
2736 pprog = new wxGenericProgressDialog(
2737 _("Export GPX file"), _T("0/0"), count, NULL,
2738 wxPD_APP_MODAL | wxPD_SMOOTH | wxPD_ELAPSED_TIME |
2739 wxPD_ESTIMATED_TIME | wxPD_REMAINING_TIME);
2740 pprog->SetSize(400, wxDefaultCoord);
2741 pprog->Centre();
2742 }
2743
2744 // WPTs
2745 int ic = 1;
2746
2747 wxRoutePointListNode *node = pWayPointMan->GetWaypointList()->GetFirst();
2748 RoutePoint *pr;
2749 while (node) {
2750 if (pprog && !(ic % progStep)) {
2751 wxString msg;
2752 msg.Printf(_T("%d/%d"), ic, count);
2753 pprog->Update(ic, msg);
2754 }
2755 ic++;
2756
2757 pr = node->GetData();
2758
2759 bool b_add = true;
2760
2761 if (bviz_only && !pr->m_bIsVisible) b_add = false;
2762
2763 if (pr->m_bIsInLayer && !blayer) b_add = false;
2764 if (b_add) {
2765 if (pr->IsShared() || !WptIsInRouteList(pr)) pgpx->AddGPXWaypoint(pr);
2766 }
2767
2768 node = node->GetNext();
2769 }
2770 // RTEs and TRKs
2771 wxRouteListNode *node1 = pRouteList->GetFirst();
2772 while (node1) {
2773 Route *pRoute = node1->GetData();
2774
2775 bool b_add = true;
2776
2777 if (bviz_only && !pRoute->IsVisible()) b_add = false;
2778
2779 if (pRoute->m_bIsInLayer && !blayer) b_add = false;
2780
2781 if (b_add) pgpx->AddGPXRoute(pRoute);
2782
2783 node1 = node1->GetNext();
2784 }
2785
2786 for (Track *pTrack : g_TrackList) {
2787 bool b_add = true;
2788
2789 if (bviz_only && !pTrack->IsVisible()) b_add = false;
2790
2791 if (pTrack->m_bIsInLayer && !blayer) b_add = false;
2792
2793 if (b_add) pgpx->AddGPXTrack(pTrack);
2794 }
2795
2796 // Android 5+ requires special handling to support native app file writes to
2797 // SDCard We need to use a two step copy process using a guaranteed
2798 // accessible location for the first step.
2799#ifdef __ANDROID__
2800 wxString fns = androidGetCacheDir() + wxFileName::GetPathSeparator() +
2801 fn.GetFullName();
2802 pgpx->SaveFile(fns);
2803 AndroidSecureCopyFile(fns, fn.GetFullPath());
2804#else
2805 pgpx->SaveFile(fn.GetFullPath());
2806#endif
2807
2808 delete pgpx;
2809 ::wxEndBusyCursor();
2810
2811 delete pprog;
2812 }
2813}
2814
2815void UI_ImportGPX(wxWindow *parent, bool islayer, wxString dirpath,
2816 bool isdirectory, bool isPersistent) {
2817 int response = wxID_CANCEL;
2818 wxArrayString file_array;
2819 Layer *l = NULL;
2820
2821 if (!islayer || dirpath.IsSameAs(_T(""))) {
2822 // Platform DoFileSelectorDialog method does not properly handle multiple
2823 // selections So use native method if not Android, which means Android gets
2824 // single selection only.
2825#ifndef __ANDROID__
2826 wxFileDialog *popenDialog =
2827 new wxFileDialog(NULL, _("Import GPX file"), g_gpx_path, wxT(""),
2828 wxT("GPX files (*.gpx)|*.gpx|All files (*.*)|*.*"),
2829 wxFD_OPEN | wxFD_MULTIPLE);
2830
2831 if (g_bresponsive && parent)
2832 popenDialog = g_Platform->AdjustFileDialogFont(parent, popenDialog);
2833
2834 popenDialog->Centre();
2835
2836#ifdef __WXOSX__
2837 if (parent) parent->HideWithEffect(wxSHOW_EFFECT_BLEND);
2838#endif
2839
2840 response = popenDialog->ShowModal();
2841
2842#ifdef __WXOSX__
2843 if (parent) parent->ShowWithEffect(wxSHOW_EFFECT_BLEND);
2844#endif
2845
2846 if (response == wxID_OK) {
2847 popenDialog->GetPaths(file_array);
2848
2849 // Record the currently selected directory for later use
2850 if (file_array.GetCount()) {
2851 wxFileName fn(file_array[0]);
2852 g_gpx_path = fn.GetPath();
2853 }
2854 }
2855 delete popenDialog;
2856#else
2857 wxString path;
2858 response = g_Platform->DoFileSelectorDialog(
2859 NULL, &path, _("Import GPX file"), g_gpx_path, _T(""), wxT("*.gpx"));
2860
2861 file_array.Add(path);
2862 wxFileName fn(path);
2863 g_gpx_path = fn.GetPath();
2864
2865#endif
2866
2867 } else {
2868 if (isdirectory) {
2869 if (wxDir::GetAllFiles(dirpath, &file_array, wxT("*.gpx")))
2870 response = wxID_OK;
2871 } else {
2872 file_array.Add(dirpath);
2873 response = wxID_OK;
2874 }
2875 }
2876
2877 if (response == wxID_OK) {
2878 if (islayer) {
2879 l = new Layer();
2880 l->m_LayerID = ++g_LayerIdx;
2881 l->m_LayerFileName = file_array[0];
2882 if (file_array.GetCount() <= 1)
2883 wxFileName::SplitPath(file_array[0], NULL, NULL, &(l->m_LayerName),
2884 NULL, NULL);
2885 else {
2886 if (dirpath.IsSameAs(_T("")))
2887 wxFileName::SplitPath(g_gpx_path, NULL, NULL, &(l->m_LayerName), NULL,
2888 NULL);
2889 else
2890 wxFileName::SplitPath(dirpath, NULL, NULL, &(l->m_LayerName), NULL,
2891 NULL);
2892 }
2893
2894 bool bLayerViz = g_bShowLayers;
2895 if (g_VisibleLayers.Contains(l->m_LayerName)) bLayerViz = true;
2896 if (g_InvisibleLayers.Contains(l->m_LayerName)) bLayerViz = false;
2897 l->m_bIsVisibleOnChart = bLayerViz;
2898
2899 // Default for new layers is "Names visible"
2900 l->m_bHasVisibleNames = wxCHK_CHECKED;
2901
2902 wxString laymsg;
2903 laymsg.Printf(wxT("New layer %d: %s"), l->m_LayerID,
2904 l->m_LayerName.c_str());
2905 wxLogMessage(laymsg);
2906
2907 pLayerList->Insert(l);
2908 }
2909
2910 for (unsigned int i = 0; i < file_array.GetCount(); i++) {
2911 wxString path = file_array[i];
2912
2913 if (::wxFileExists(path)) {
2915 if (pSet->load_file(path.fn_str()).status !=
2916 pugi::xml_parse_status::status_ok) {
2917 wxLogMessage("Error loading GPX file " + path);
2918 pSet->reset();
2919 delete pSet;
2920 continue;
2921 }
2922
2923 if (islayer) {
2924 l->m_NoOfItems = pSet->LoadAllGPXObjectsAsLayer(
2925 l->m_LayerID, l->m_bIsVisibleOnChart, l->m_bHasVisibleNames);
2926 l->m_LayerType = isPersistent ? _("Persistent") : _("Temporary");
2927
2928 if (isPersistent) {
2929 // If this is a persistent layer also copy the file to config file
2930 // dir /layers
2931 wxString destf, f, name, ext;
2932 f = l->m_LayerFileName;
2933 wxFileName::SplitPath(f, NULL, NULL, &name, &ext);
2934 destf = g_Platform->GetPrivateDataDir();
2935 appendOSDirSlash(&destf);
2936 destf.Append(_T("layers"));
2937 appendOSDirSlash(&destf);
2938 if (!wxDirExists(destf)) {
2939 if (!wxMkdir(destf, wxS_DIR_DEFAULT))
2940 wxLogMessage(_T("Error creating layer directory"));
2941 }
2942
2943 destf << name << _T(".") << ext;
2944 wxString msg;
2945 if (wxCopyFile(f, destf, true))
2946 msg.Printf(_T("File: %s.%s also added to persistent layers"),
2947 name, ext);
2948 else
2949 msg.Printf(_T("Failed adding %s.%s to persistent layers"), name,
2950 ext);
2951 wxLogMessage(msg);
2952 }
2953 } else {
2954 int wpt_dups;
2955 pSet->LoadAllGPXObjects(
2956 !pSet->IsOpenCPN(),
2957 wpt_dups); // Import with full visibility of names and objects
2958 if (wpt_dups > 0) {
2959 OCPNMessageBox(
2960 parent,
2961 wxString::Format(_T("%d ") + _("duplicate waypoints detected "
2962 "during import and ignored."),
2963 wpt_dups),
2964 _("OpenCPN Info"), wxICON_INFORMATION | wxOK, 10);
2965 }
2966 }
2967 delete pSet;
2968 }
2969 }
2970 }
2971}
2972
2973//-------------------------------------------------------------------------
2974// Static Routine Switch to Inland Ecdis Mode
2975//-------------------------------------------------------------------------
2976void SwitchInlandEcdisMode(bool Switch) {
2977 if (Switch) {
2978 wxLogMessage(_T("Switch InlandEcdis mode On"));
2979 LoadS57();
2980 // Overule some sewttings to comply with InlandEcdis
2981 // g_toolbarConfig = _T ( ".....XXXX.X...XX.XXXXXXXXXXXX" );
2982 g_iDistanceFormat = 2; // 0 = "Nautical miles"), 1 = "Statute miles", 2 =
2983 // "Kilometers", 3 = "Meters"
2984 g_iSpeedFormat = 2; // 0 = "kts"), 1 = "mph", 2 = "km/h", 3 = "m/s"
2985 if (ps52plib) ps52plib->SetDisplayCategory(STANDARD);
2986 g_bDrawAISSize = false;
2987 if (gFrame) gFrame->RequestNewToolbars(true);
2988 } else {
2989 wxLogMessage(_T("Switch InlandEcdis mode Off"));
2990 // reread the settings overruled by inlandEcdis
2991 if (pConfig) {
2992 pConfig->SetPath(_T ( "/Settings" ));
2993 pConfig->Read(_T ( "GlobalToolbarConfig" ), &g_toolbarConfig);
2994 pConfig->Read(_T ( "DistanceFormat" ), &g_iDistanceFormat);
2995 pConfig->Read(_T ( "SpeedFormat" ), &g_iSpeedFormat);
2996 pConfig->Read(_T ( "ShowDepthUnits" ), &g_bShowDepthUnits, 1);
2997 int read_int;
2998 pConfig->Read(_T ( "nDisplayCategory" ), &read_int,
2999 (enum _DisCat)STANDARD);
3000 if (ps52plib) ps52plib->SetDisplayCategory((enum _DisCat)read_int);
3001 pConfig->SetPath(_T ( "/Settings/AIS" ));
3002 pConfig->Read(_T ( "bDrawAISSize" ), &g_bDrawAISSize);
3003 pConfig->Read(_T ( "bDrawAISRealtime" ), &g_bDrawAISRealtime);
3004 }
3005 if (gFrame) gFrame->RequestNewToolbars(true);
3006 }
3007}
3008
3009//-------------------------------------------------------------------------
3010//
3011// Static GPX Support Routines
3012//
3013//-------------------------------------------------------------------------
3014// This function formats the input date/time into a valid GPX ISO 8601
3015// time string specified in the UTC time zone.
3016
3017wxString FormatGPXDateTime(wxDateTime dt) {
3018 // return dt.Format(wxT("%Y-%m-%dT%TZ"), wxDateTime::GMT0);
3019 return dt.Format(wxT("%Y-%m-%dT%H:%M:%SZ"));
3020}
3021
3022/**************************************************************************/
3023/* LogMessageOnce */
3024/**************************************************************************/
3025
3026bool LogMessageOnce(const wxString &msg) {
3027 // Search the array for a match
3028
3029 for (unsigned int i = 0; i < pMessageOnceArray->GetCount(); i++) {
3030 if (msg.IsSameAs(pMessageOnceArray->Item(i))) return false;
3031 }
3032
3033 // Not found, so add to the array
3034 pMessageOnceArray->Add(msg);
3035
3036 // And print it
3037 wxLogMessage(msg);
3038 return true;
3039}
3040
3041/**************************************************************************/
3042/* Some assorted utilities */
3043/**************************************************************************/
3044
3045wxDateTime toUsrDateTime(const wxDateTime ts, const int format,
3046 const double lon) {
3047 if (!ts.IsValid()) {
3048 return ts;
3049 }
3050 int effective_format = format;
3051 if (effective_format == GLOBAL_SETTINGS_INPUT) {
3052 if (::g_datetime_format == "UTC") {
3053 effective_format = UTCINPUT;
3054 } else if (::g_datetime_format == "LMT") {
3055 effective_format = LMTINPUT;
3056 } else if (::g_datetime_format == "Local Time") {
3057 effective_format = LTINPUT;
3058 } else {
3059 // Default to UTC
3060 effective_format = UTCINPUT;
3061 }
3062 }
3063 wxDateTime dt;
3064 switch (effective_format) {
3065 case LMTINPUT: // LMT@Location
3066 if (std::isnan(lon)) {
3067 dt = wxInvalidDateTime;
3068 } else {
3069 dt =
3070 ts.Add(wxTimeSpan(wxTimeSpan(0, 0, wxLongLong(lon * 3600. / 15.))));
3071 }
3072 break;
3073 case LTINPUT: // Local@PC
3074 // Convert date/time from UTC to local time.
3075 dt = ts.FromUTC();
3076 break;
3077 case UTCINPUT: // UTC
3078 // The date/time is already in UTC.
3079 dt = ts;
3080 break;
3081 }
3082 return dt;
3083}
3084
3085wxDateTime fromUsrDateTime(const wxDateTime ts, const int format,
3086 const double lon) {
3087 if (!ts.IsValid()) {
3088 return ts;
3089 }
3090 int effective_format = format;
3091 if (effective_format == GLOBAL_SETTINGS_INPUT) {
3092 if (::g_datetime_format == "UTC") {
3093 effective_format = UTCINPUT;
3094 } else if (::g_datetime_format == "LMT") {
3095 effective_format = LMTINPUT;
3096 } else if (::g_datetime_format == "Local Time") {
3097 effective_format = LTINPUT;
3098 } else {
3099 // Default to UTC
3100 effective_format = UTCINPUT;
3101 }
3102 }
3103 wxDateTime dt;
3104 switch (effective_format) {
3105 case LMTINPUT: // LMT@Location
3106 if (std::isnan(lon)) {
3107 dt = wxInvalidDateTime;
3108 } else {
3109 dt = ts.Subtract(wxTimeSpan(0, 0, wxLongLong(lon * 3600. / 15.)));
3110 }
3111 break;
3112 case LTINPUT: // Local@PC
3113 // The input date/time is in local time, so convert it to UTC.
3114 dt = ts.ToUTC();
3115 break;
3116 case UTCINPUT: // UTC
3117 dt = ts;
3118 break;
3119 }
3120 return dt;
3121}
3122
3123/**************************************************************************/
3124/* Converts the distance from the units selected by user to NMi */
3125/**************************************************************************/
3126double fromUsrDistance(double usr_distance, int unit) {
3127 double ret = NAN;
3128 if (unit == -1) unit = g_iDistanceFormat;
3129 switch (unit) {
3130 case DISTANCE_NMI: // Nautical miles
3131 ret = usr_distance;
3132 break;
3133 case DISTANCE_MI: // Statute miles
3134 ret = usr_distance / 1.15078;
3135 break;
3136 case DISTANCE_KM:
3137 ret = usr_distance / 1.852;
3138 break;
3139 case DISTANCE_M:
3140 ret = usr_distance / 1852;
3141 break;
3142 case DISTANCE_FT:
3143 ret = usr_distance / 6076.12;
3144 break;
3145 }
3146 return ret;
3147}
3148/**************************************************************************/
3149/* Converts the speed from the units selected by user to knots */
3150/**************************************************************************/
3151double fromUsrSpeed(double usr_speed, int unit) {
3152 double ret = NAN;
3153 if (unit == -1) unit = g_iSpeedFormat;
3154 switch (unit) {
3155 case SPEED_KTS: // kts
3156 ret = usr_speed;
3157 break;
3158 case SPEED_MPH: // mph
3159 ret = usr_speed / 1.15078;
3160 break;
3161 case SPEED_KMH: // km/h
3162 ret = usr_speed / 1.852;
3163 break;
3164 case SPEED_MS: // m/s
3165 ret = usr_speed / 0.514444444;
3166 break;
3167 }
3168 return ret;
3169}
3170/**************************************************************************/
3171/* Converts the wind speed from the units selected by user to knots */
3172/**************************************************************************/
3173double fromUsrWindSpeed(double usr_wspeed, int unit) {
3174 double ret = NAN;
3175 if (unit == -1) unit = g_iWindSpeedFormat;
3176 switch (unit) {
3177 case WSPEED_KTS: // kts
3178 ret = usr_wspeed;
3179 break;
3180 case WSPEED_MS: // m/s
3181 ret = usr_wspeed / 0.514444444;
3182 break;
3183 case WSPEED_MPH: // mph
3184 ret = usr_wspeed / 1.15078;
3185 break;
3186 case WSPEED_KMH: // km/h
3187 ret = usr_wspeed / 1.852;
3188 break;
3189 }
3190 return ret;
3191}
3192
3193/**************************************************************************/
3194/* Converts the temperature from the units selected by user to Celsius */
3195/**************************************************************************/
3196double fromUsrTemp(double usr_temp, int unit) {
3197 double ret = NAN;
3198 if (unit == -1) unit = g_iTempFormat;
3199 switch (unit) {
3200 case TEMPERATURE_C: // C
3201 ret = usr_temp;
3202 break;
3203 case TEMPERATURE_F: // F
3204 ret = (usr_temp - 32) * 5.0 / 9.0;
3205 break;
3206 case TEMPERATURE_K: // K
3207 ret = usr_temp - 273.15;
3208 break;
3209 }
3210 return ret;
3211}
3212
3213wxString formatAngle(double angle) {
3214 wxString out;
3215 if (g_bShowMag && g_bShowTrue) {
3216 out.Printf(wxT("%03.0f %cT (%.0f %cM)"), angle, 0x00B0, toMagnetic(angle),
3217 0x00B0);
3218 } else if (g_bShowTrue) {
3219 out.Printf(wxT("%03.0f %cT"), angle, 0x00B0);
3220 } else {
3221 out.Printf(wxT("%03.0f %cM"), toMagnetic(angle), 0x00B0);
3222 }
3223 return out;
3224}
3225
3226/* render a rectangle at a given color and transparency */
3227void AlphaBlending(ocpnDC &dc, int x, int y, int size_x, int size_y,
3228 float radius, wxColour color, unsigned char transparency) {
3229 wxDC *pdc = dc.GetDC();
3230 if (pdc) {
3231 // Get wxImage of area of interest
3232 wxBitmap obm(size_x, size_y);
3233 wxMemoryDC mdc1;
3234 mdc1.SelectObject(obm);
3235 mdc1.Blit(0, 0, size_x, size_y, pdc, x, y);
3236 mdc1.SelectObject(wxNullBitmap);
3237 wxImage oim = obm.ConvertToImage();
3238
3239 // Create destination image
3240 wxBitmap olbm(size_x, size_y);
3241 wxMemoryDC oldc(olbm);
3242 if (!oldc.IsOk()) return;
3243
3244 oldc.SetBackground(*wxBLACK_BRUSH);
3245 oldc.SetBrush(*wxWHITE_BRUSH);
3246 oldc.Clear();
3247
3248 if (radius > 0.0) oldc.DrawRoundedRectangle(0, 0, size_x, size_y, radius);
3249
3250 wxImage dest = olbm.ConvertToImage();
3251 unsigned char *dest_data =
3252 (unsigned char *)malloc(size_x * size_y * 3 * sizeof(unsigned char));
3253 unsigned char *bg = oim.GetData();
3254 unsigned char *box = dest.GetData();
3255 unsigned char *d = dest_data;
3256
3257 // Sometimes, on Windows, the destination image is corrupt...
3258 if (NULL == box) {
3259 free(d);
3260 return;
3261 }
3262 float alpha = 1.0 - (float)transparency / 255.0;
3263 int sb = size_x * size_y;
3264 for (int i = 0; i < sb; i++) {
3265 float a = alpha;
3266 if (*box == 0 && radius > 0.0) a = 1.0;
3267 int r = ((*bg++) * a) + (1.0 - a) * color.Red();
3268 *d++ = r;
3269 box++;
3270 int g = ((*bg++) * a) + (1.0 - a) * color.Green();
3271 *d++ = g;
3272 box++;
3273 int b = ((*bg++) * a) + (1.0 - a) * color.Blue();
3274 *d++ = b;
3275 box++;
3276 }
3277
3278 dest.SetData(dest_data);
3279
3280 // Convert destination to bitmap and draw it
3281 wxBitmap dbm(dest);
3282 dc.DrawBitmap(dbm, x, y, false);
3283
3284 // on MSW, the dc Bounding box is not updated on DrawBitmap() method.
3285 // Do it explicitely here for all platforms.
3286 dc.CalcBoundingBox(x, y);
3287 dc.CalcBoundingBox(x + size_x, y + size_y);
3288 } else {
3289#ifdef ocpnUSE_GL
3290 glEnable(GL_BLEND);
3291
3292 float radMod = wxMax(radius, 2.0);
3293 wxColour c(color.Red(), color.Green(), color.Blue(), transparency);
3294 dc.SetBrush(wxBrush(c));
3295 dc.SetPen(wxPen(c, 1));
3296 dc.DrawRoundedRectangle(x, y, size_x, size_y, radMod);
3297
3298 glDisable(GL_BLEND);
3299
3300#endif
3301 }
3302}
3303
3304void DimeControl(wxWindow *ctrl) {
3305#ifdef __WXOSX__
3306 // On macOS 10.14+, we use the native colours in both light mode and dark
3307 // mode, and do not need to do anything else. Dark mode is toggled at the
3308 // application level in `SetAndApplyColorScheme`, and is also respected if it
3309 // is enabled system-wide.
3310 if (wxPlatformInfo::Get().CheckOSVersion(10, 14)) {
3311 return;
3312 }
3313#endif
3314#ifdef __WXQT__
3315 return; // this is seriously broken on wxqt
3316#endif
3317
3318 if (wxSystemSettings::GetColour(wxSystemColour::wxSYS_COLOUR_WINDOW).Red() <
3319 128) {
3320 // Dark system color themes usually do better job than we do on diming UI
3321 // controls, do not fight with them
3322 return;
3323 }
3324
3325 if (NULL == ctrl) return;
3326
3327 wxColour col, window_back_color, gridline, uitext, udkrd, ctrl_back_color,
3328 text_color;
3329 col = GetGlobalColor(_T("DILG0")); // Dialog Background white
3330 window_back_color = GetGlobalColor(_T("DILG1")); // Dialog Background
3331 ctrl_back_color = GetGlobalColor(_T("DILG1")); // Control Background
3332 text_color = GetGlobalColor(_T("DILG3")); // Text
3333 uitext = GetGlobalColor(_T("UITX1")); // Menu Text, derived from UINFF
3334 udkrd = GetGlobalColor(_T("UDKRD"));
3335 gridline = GetGlobalColor(_T("GREY2"));
3336
3337 DimeControl(ctrl, col, window_back_color, ctrl_back_color, text_color, uitext,
3338 udkrd, gridline);
3339}
3340
3341void DimeControl(wxWindow *ctrl, wxColour col, wxColour window_back_color,
3342 wxColour ctrl_back_color, wxColour text_color, wxColour uitext,
3343 wxColour udkrd, wxColour gridline) {
3344#ifdef __WXOSX__
3345 // On macOS 10.14+, we use the native colours in both light mode and dark
3346 // mode, and do not need to do anything else. Dark mode is toggled at the
3347 // application level in `SetAndApplyColorScheme`, and is also respected if it
3348 // is enabled system-wide.
3349 if (wxPlatformInfo::Get().CheckOSVersion(10, 14)) {
3350 return;
3351 }
3352#endif
3353
3354 ColorScheme cs = global_color_scheme;
3355
3356 // Are we in dusk or night mode? (Used below in several places.)
3357 bool darkMode =
3358 (cs == GLOBAL_COLOR_SCHEME_DUSK || cs == GLOBAL_COLOR_SCHEME_NIGHT);
3359
3360 static int depth = 0; // recursion count
3361 if (depth == 0) { // only for the window root, not for every child
3362 // If the color scheme is DAY or RGB, use the default platform native colour
3363 // for backgrounds
3364 if (!darkMode) {
3365#ifdef _WIN32
3366 window_back_color = wxNullColour;
3367#else
3368 window_back_color = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW);
3369#endif
3370 col = wxSystemSettings::GetColour(wxSYS_COLOUR_LISTBOX);
3371 uitext = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT);
3372 }
3373
3374 ctrl->SetBackgroundColour(window_back_color);
3375 if (darkMode) ctrl->SetForegroundColour(text_color);
3376 }
3377
3378 wxWindowList kids = ctrl->GetChildren();
3379 for (unsigned int i = 0; i < kids.GetCount(); i++) {
3380 wxWindowListNode *node = kids.Item(i);
3381 wxWindow *win = node->GetData();
3382
3383 if (dynamic_cast<wxListBox *>(win) || dynamic_cast<wxListCtrl *>(win) ||
3384 dynamic_cast<wxTextCtrl *>(win) ||
3385 dynamic_cast<wxTimePickerCtrl *>(win)) {
3386 win->SetBackgroundColour(col);
3387 } else if (dynamic_cast<wxStaticText *>(win) ||
3388 dynamic_cast<wxCheckBox *>(win) ||
3389 dynamic_cast<wxRadioButton *>(win)) {
3390 win->SetForegroundColour(uitext);
3391 }
3392#ifndef __WXOSX__
3393 // On macOS most controls can't be styled, and trying to do so only creates
3394 // weird coloured boxes around them. Fortunately, however, many of them
3395 // inherit a colour or tint from the background of their parent.
3396
3397 else if (dynamic_cast<wxBitmapComboBox *>(win) ||
3398 dynamic_cast<wxChoice *>(win) || dynamic_cast<wxComboBox *>(win) ||
3399 dynamic_cast<wxTreeCtrl *>(win)) {
3400 win->SetBackgroundColour(col);
3401 }
3402
3403 else if (dynamic_cast<wxScrolledWindow *>(win) ||
3404 dynamic_cast<wxGenericDirCtrl *>(win) ||
3405 dynamic_cast<wxListbook *>(win) || dynamic_cast<wxButton *>(win) ||
3406 dynamic_cast<wxToggleButton *>(win)) {
3407 win->SetBackgroundColour(window_back_color);
3408 }
3409
3410 else if (dynamic_cast<wxNotebook *>(win)) {
3411 win->SetBackgroundColour(window_back_color);
3412 win->SetForegroundColour(text_color);
3413 }
3414#endif
3415
3416 else if (dynamic_cast<wxHtmlWindow *>(win)) {
3417 if (cs != GLOBAL_COLOR_SCHEME_DAY && cs != GLOBAL_COLOR_SCHEME_RGB)
3418 win->SetBackgroundColour(ctrl_back_color);
3419 else
3420 win->SetBackgroundColour(wxNullColour);
3421 }
3422
3423 else if (dynamic_cast<wxGrid *>(win)) {
3424 dynamic_cast<wxGrid *>(win)->SetDefaultCellBackgroundColour(
3425 window_back_color);
3426 dynamic_cast<wxGrid *>(win)->SetDefaultCellTextColour(uitext);
3427 dynamic_cast<wxGrid *>(win)->SetLabelBackgroundColour(col);
3428 dynamic_cast<wxGrid *>(win)->SetLabelTextColour(uitext);
3429 dynamic_cast<wxGrid *>(win)->SetGridLineColour(gridline);
3430 }
3431
3432 if (win->GetChildren().GetCount() > 0) {
3433 depth++;
3434 wxWindow *w = win;
3435 DimeControl(w, col, window_back_color, ctrl_back_color, text_color,
3436 uitext, udkrd, gridline);
3437 depth--;
3438 }
3439 }
3440}
3441
3442#define LUMIMOSITY_NIGHT (-0.8)
3443#define LUMIMOSITY_DUSK (-0.5)
3444
3445wxColor GetDimedColor(const wxColor &c) {
3446 switch (global_color_scheme) {
3447 case ColorScheme::GLOBAL_COLOR_SCHEME_NIGHT:
3448 return (wxColor(
3449 wxMax(0, wxMin(c.Red() + c.Red() * LUMIMOSITY_NIGHT, 255)),
3450 wxMax(0, wxMin(c.Green() + c.Green() * LUMIMOSITY_NIGHT, 255)),
3451 wxMax(0, wxMin(c.Blue() + c.Blue() * LUMIMOSITY_NIGHT, 255))));
3452 case ColorScheme::GLOBAL_COLOR_SCHEME_DUSK:
3453 return (
3454 wxColor(wxMax(0, wxMin(c.Red() + c.Red() * LUMIMOSITY_DUSK, 255)),
3455 wxMax(0, wxMin(c.Green() + c.Green() * LUMIMOSITY_DUSK, 255)),
3456 wxMax(0, wxMin(c.Blue() + c.Blue() * LUMIMOSITY_DUSK, 255))));
3457 default:
3458 return c;
3459 }
3460}
bool g_bresponsive
Flag to control adaptive UI scaling.
Definition ocpn_app.cpp:662
Global state for AIS decoder.
wxString & GetPrivateDataDir()
Return dir path for opencpn.log, etc., respecting -c cli option.
Represents an individual component within a ChartGroup.
Definition chartdbs.h:444
Represents a user-defined collection of logically related charts.
Definition chartdbs.h:464
wxString GetFullConfigDesc(int i) const
Gets description of font at index i.
Definition FontMgr.cpp:362
bool AddAuxKey(wxString key)
Adds new plugin-defined font configuration key.
Definition FontMgr.cpp:667
void LoadFontNative(wxString *pConfigString, wxString *pNativeDesc)
Loads font settings from a string descriptor.
Definition FontMgr.cpp:392
static wxString GetFontConfigKey(const wxString &description)
Creates configuration key from UI element name by combining locale with hash.
Definition FontMgr.cpp:132
int GetNumFonts(void) const
Gets the total number of font configurations currently loaded.
Definition FontMgr.cpp:325
wxArrayString & GetAuxKeyArray()
Gets array of plugin-defined font configuration keys.
Definition FontMgr.h:181
Represents a layer of chart objects in OpenCPN.
Definition Layer.h:38
static int config_to_ui(double value)
Convert configuration 1.02..3.0 value to slider scale 1..100.
Definition navutil.h:165
static double ui_to_config(int slider_pos)
Convert a slider scale 1-100 value to configuration value 1.02..3.0.
Definition navutil.h:160
Main application frame.
Definition ocpn_frame.h:136
Provides platform-specific support utilities for OpenCPN.
Represents a waypoint or mark within the navigation system.
Definition route_point.h:70
bool m_bIsVisible
Flag indicating if the waypoint should be drawn on the chart.
bool m_bIsInLayer
Flag indicating if the waypoint belongs to a layer.
Represents a navigational route in the navigation system.
Definition route.h:98
bool m_bIsInLayer
Flag indicating whether this route belongs to a layer.
Definition route.h:277
Represents a track, which is a series of connected track points.
Definition track.h:111
ViewPort - Core geographic projection and coordinate transformation engine.
Definition viewport.h:81
double view_scale_ppm
Requested view scale in physical pixels per meter (ppm), before applying projections.
Definition viewport.h:229
double rotation
Rotation angle of the viewport in radians.
Definition viewport.h:239
double clon
Center longitude of the viewport in degrees.
Definition viewport.h:224
double clat
Center latitude of the viewport in degrees.
Definition viewport.h:222
Encapsulates persistent canvas configuration.
double iLat
Latitude of the center of the chart, in degrees.
bool bShowOutlines
Display chart outlines.
wxSize canvasSize
Canvas dimensions.
bool bShowDepthUnits
Display depth unit indicators.
double iLon
Longitude of the center of the chart, in degrees.
double iRotation
Initial rotation angle in radians.
bool bCourseUp
Orient display to course up.
bool bQuilt
Enable chart quilting.
bool bFollow
Enable vessel following mode.
double iScale
Initial chart scale factor.
bool bShowENCText
Display ENC text elements.
bool bShowAIS
Display AIS targets.
bool bShowGrid
Display coordinate grid.
ChartCanvas * canvas
Pointer to associated chart canvas.
bool bShowCurrents
Display current information.
bool bShowTides
Display tide information.
bool bLookahead
Enable lookahead mode.
bool bHeadUp
Orient display to heading up.
bool bAttenAIS
Enable AIS target attenuation.
Device context class that can use either wxDC or OpenGL for drawing.
Definition ocpndc.h:64
Global variables reflecting command line options and arguments.
NavmsgFilter Read(const std::string &name)
Read filter with given name from disk.
bool Write(const NavmsgFilter &filter, const std::string &name)
Write contents for given filter to disk.
PlugIn Object Definition/API.
Tools to send data to plugins.