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 <algorithm>
34#include <stdlib.h>
35#include <time.h>
36#include <locale>
37#include <list>
38
39#ifndef WX_PRECOMP
40#include <wx/wx.h>
41#endif // precompiled headers
42
43#include <wx/bmpcbox.h>
44#include <wx/dir.h>
45#include "wx/dirctrl.h"
46#include <wx/filename.h>
47#include <wx/graphics.h>
48#include <wx/image.h>
49#include <wx/listbook.h>
50#include <wx/listimpl.cpp>
51#include <wx/progdlg.h>
52#include <wx/sstream.h>
53#include <wx/tglbtn.h>
54#include <wx/timectrl.h>
55#include <wx/tokenzr.h>
56
57#include "model/ais_decoder.h"
59#include "model/cmdline.h"
60#include "model/config_vars.h"
61#include "model/conn_params.h"
62#include "model/cutil.h"
63#include "model/geodesic.h"
64#include "model/georef.h"
65#include "model/idents.h"
66#include "model/multiplexer.h"
67#include "model/nav_object_database.h"
68#include "model/navutil_base.h"
69#include "model/navobj_db.h"
70#include "model/own_ship.h"
71#include "model/plugin_comm.h"
72#include "model/route.h"
73#include "model/routeman.h"
74#include "model/select.h"
75#include "model/track.h"
76
77#include "ais.h"
78#include "canvas_config.h"
79#include "chartbase.h"
80#include "chartdb.h"
81#include "chcanv.h"
82#include "cm93.h"
83#include "config.h"
84#include "config_mgr.h"
85#include "displays.h"
86#include "dychart.h"
87#include "FontMgr.h"
88#include "Layer.h"
89#include "navutil.h"
90#include "nmea0183.h"
91#include "observable_globvar.h"
92#include "ocpndc.h"
93#include "ocpn_frame.h"
94#include "ocpn_plugin.h"
95#include "OCPNPlatform.h"
96#include "OCPN_Sound.h"
97#include "s52plib.h"
98#include "s52utils.h"
99#include "snd_config.h"
100#include "styles.h"
101
102#ifdef ocpnUSE_GL
103#include "glChartCanvas.h"
104#endif
105
106#ifdef __ANDROID__
107#include "androidUTIL.h"
108#endif
109
110// Statics
111
112extern OCPNPlatform *g_Platform;
113extern MyFrame *gFrame;
114
115extern double g_ChartNotRenderScaleFactor;
116extern int g_restore_stackindex;
117extern int g_restore_dbindex;
118extern RouteList *pRouteList;
119extern std::vector<Track *> g_TrackList;
120extern LayerList *pLayerList;
121extern MyConfig *pConfig;
122extern double vLat, vLon;
123extern double kLat, kLon;
124extern ColorScheme global_color_scheme;
125extern int g_nbrightness;
126extern bool g_bShowStatusBar;
127extern bool g_bUIexpert;
128extern bool g_bFullscreen;
129
130extern wxString g_SENCPrefix;
131extern wxString g_UserPresLibData;
132
133extern wxString *pInit_Chart_Dir;
134extern wxString gWorldMapLocation;
135extern wxString gWorldShapefileLocation;
136
137extern bool s_bSetSystemTime;
138extern bool g_bDisplayGrid; // Flag indicating if grid is to be displayed
139extern bool g_bPlayShipsBells;
140extern int g_iSoundDeviceIndex;
141extern bool g_bFullscreenToolbar;
142extern bool g_bShowLayers;
143extern bool g_bTransparentToolbar;
144extern bool g_bPermanentMOBIcon;
145
146extern bool g_bShowDepthUnits;
147extern bool g_bAutoAnchorMark;
148extern bool g_bskew_comp;
149extern bool g_bopengl;
150extern bool g_bSoftwareGL;
151extern bool g_bsmoothpanzoom;
152extern bool g_fog_overzoom;
153extern double g_overzoom_emphasis_base;
154extern bool g_oz_vector_scale;
155extern double g_plus_minus_zoom_factor;
156extern bool g_bShowOutlines;
157extern bool g_bShowActiveRouteHighway;
158extern bool g_bShowRouteTotal;
159extern int g_nAWDefault;
160extern int g_nAWMax;
161extern bool g_btenhertz;
162extern bool g_declutter_anchorage;
163
164extern int g_nframewin_x;
165extern int g_nframewin_y;
166extern int g_nframewin_posx;
167extern int g_nframewin_posy;
168extern bool g_bframemax;
169
170extern wxString g_VisibleLayers;
171extern wxString g_InvisibleLayers;
172extern wxString g_VisiNameinLayers;
173extern wxString g_InVisiNameinLayers;
174
175extern wxArrayString *pMessageOnceArray;
176
177// LIVE ETA OPTION
178extern bool g_bShowLiveETA;
179extern double g_defaultBoatSpeed;
180extern double g_defaultBoatSpeedUserUnit;
181
182extern bool g_bUseOnlyConfirmedAISName;
183extern int g_ScaledNumWeightSOG;
184
185extern int g_S57_dialog_sx, g_S57_dialog_sy;
186int g_S57_extradialog_sx, g_S57_extradialog_sy;
187
188extern int g_iNavAidRadarRingsNumberVisible;
189extern bool g_bNavAidRadarRingsShown;
190extern float g_fNavAidRadarRingsStep;
191extern int g_pNavAidRadarRingsStepUnits;
192extern bool g_bWayPointPreventDragging;
193extern bool g_bConfirmObjectDelete;
194extern wxColour g_colourOwnshipRangeRingsColour;
195
196extern bool g_bEnableZoomToCursor;
197extern wxString g_toolbarConfig;
198extern double g_TrackIntervalSeconds;
199
200extern int g_nCacheLimit;
201extern int g_memCacheLimit;
202
203extern bool g_bGDAL_Debug;
204extern bool g_bDebugCM93;
205extern bool g_bDebugS57;
206
207extern double g_ownship_predictor_minutes;
208extern int g_cog_predictor_style;
209extern wxString g_cog_predictor_color;
210extern int g_cog_predictor_endmarker;
211extern int g_cog_predictor_width;
212extern int g_ownship_HDTpredictor_style;
213extern wxString g_ownship_HDTpredictor_color;
214extern int g_ownship_HDTpredictor_endmarker;
215extern int g_ownship_HDTpredictor_width;
216extern double g_ownship_HDTpredictor_miles;
217
218extern bool g_own_ship_sog_cog_calc;
219extern int g_own_ship_sog_cog_calc_damp_sec;
220
221extern bool g_bShowMenuBar;
222extern bool g_bShowCompassWin;
223
224extern s52plib *ps52plib;
225
226extern int g_cm93_zoom_factor;
227extern bool g_b_legacy_input_filter_behaviour;
228extern bool g_bShowDetailSlider;
229extern int g_detailslider_dialog_x, g_detailslider_dialog_y;
230
231extern bool g_bUseGreenShip;
232
233extern unsigned g_OwnShipmmsi;
234extern int g_OwnShipIconType;
235extern double g_n_ownship_length_meters;
236extern double g_n_ownship_beam_meters;
237extern double g_n_gps_antenna_offset_y;
238extern double g_n_gps_antenna_offset_x;
239extern int g_n_ownship_min_mm;
240extern int g_maxzoomin;
241
242extern bool g_bShowShipToActive;
243extern int g_shipToActiveStyle;
244extern int g_shipToActiveColor;
245
246extern bool g_bPreserveScaleOnX;
247extern bool g_bsimplifiedScalebar;
248
249extern bool g_bUseGLL;
250
251extern wxString g_locale;
252extern wxString g_localeOverride;
253
254extern bool g_bCourseUp;
255extern bool g_bLookAhead;
256extern int g_COGAvgSec;
257extern bool g_bShowChartBar;
258
259extern int g_MemFootMB;
260
261extern wxString g_AW1GUID;
262extern wxString g_AW2GUID;
263extern int g_BSBImgDebug;
264
265extern int n_NavMessageShown;
266extern wxString g_config_version_string;
267
268extern wxString g_CmdSoundString;
269
270extern bool g_bDebugGPSD;
271
272extern bool g_bQuiltEnable;
273extern bool g_bFullScreenQuilt;
274extern bool g_bQuiltStart;
275
276extern int g_SkewCompUpdatePeriod;
277
278extern int g_maintoolbar_x;
279extern int g_maintoolbar_y;
280extern long g_maintoolbar_orient;
281
282extern int g_lastClientRectx;
283extern int g_lastClientRecty;
284extern int g_lastClientRectw;
285extern int g_lastClientRecth;
286
287extern bool g_bHighliteTracks;
288extern int g_cog_predictor_width;
289extern int g_ais_cog_predictor_width;
290
291extern wxColour g_colourTrackLineColour;
292extern wxString g_default_wp_icon;
293
294extern ChartGroupArray *g_pGroupArray;
295
296extern bool g_bDebugOGL;
297extern int g_tcwin_scale;
298extern wxString g_uploadConnection;
299
300extern ocpnStyle::StyleManager *g_StyleManager;
301extern std::vector<std::string> TideCurrentDataSet;
302extern wxString g_TCData_Dir;
303
304extern bool g_bresponsive;
305
306extern bool g_bGLexpert;
307
308extern int g_SENC_LOD_pixels;
309extern ArrayOfMmsiProperties g_MMSI_Props_Array;
310
311extern int g_chart_zoom_modifier_raster;
312extern int g_chart_zoom_modifier_vector;
313
314extern bool g_bShowTrackPointTime;
315
316extern bool g_bAdvanceRouteWaypointOnArrivalOnly;
317extern double g_display_size_mm;
318extern std::vector<size_t> g_config_display_size_mm;
319extern bool g_config_display_size_manual;
320
321extern bool g_benable_rotate;
322extern bool g_bEmailCrashReport;
323
324extern int g_default_font_size;
325extern wxString g_default_font_facename;
326
327extern bool g_bAutoHideToolbar;
328extern int g_nAutoHideToolbar;
329extern int g_GUIScaleFactor;
330extern int g_ChartScaleFactor;
331extern float g_MarkScaleFactorExp;
332
333extern int g_ShipScaleFactor;
334extern float g_ShipScaleFactorExp;
335extern int g_ENCSoundingScaleFactor;
336extern int g_ENCTextScaleFactor;
337
338extern int g_iENCToolbarPosX;
339extern int g_iENCToolbarPosY;
340extern bool g_bRollover;
341
342extern bool g_bSpaceDropMark;
343
344extern bool g_bShowTide;
345extern bool g_bShowCurrent;
346
347extern wxString g_uiStyle;
348extern bool g_btrackContinuous;
349extern bool g_useMUI;
350
351int g_nCPUCount;
352
353extern unsigned int g_canvasConfig;
354extern wxString g_lastAppliedTemplateGUID;
355
356extern int g_route_prop_x, g_route_prop_y;
357extern int g_route_prop_sx, g_route_prop_sy;
358extern int g_AndroidVersionCode;
359
360extern wxString g_ObjQFileExt;
361
362MyConfig *pConfig;
363bool g_bLayersLoaded;
364bool g_bShowMuiZoomButtons = true;
365
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("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 = "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 = "triangle";
525 g_default_routepoint_icon = "diamond";
526
527 g_nAWDefault = 50;
528 g_nAWMax = 1852;
529 g_ObjQFileExt = "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;
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("AlwaysSendRmbRmc", &g_always_send_rmb_rmc);
625 Read(_T ( "LastAppliedTemplate" ), &g_lastAppliedTemplateGUID);
626 Read(_T ( "CompatOS" ), &g_compatOS);
627 Read(_T ( "CompatOsVersion" ), &g_compatOsVersion);
628
629 // Some undocumented values
630 Read(_T ( "ConfigVersionString" ), &g_config_version_string);
631 Read("CmdSoundString", &g_CmdSoundString, wxString(OCPN_SOUND_CMD));
632 if (wxIsEmpty(g_CmdSoundString)) g_CmdSoundString = wxString(OCPN_SOUND_CMD);
633 Read(_T ( "NavMessageShown" ), &n_NavMessageShown);
634
635 Read(_T ( "AndroidVersionCode" ), &g_AndroidVersionCode);
636
637 Read(_T ( "UIexpert" ), &g_bUIexpert);
638
639 Read(_T ( "UIStyle" ), &g_uiStyle);
640
641 Read(_T ( "NCacheLimit" ), &g_nCacheLimit);
642
643 Read(_T ( "InlandEcdis" ),
644 &g_bInlandEcdis); // First read if in iENC mode as this will override
645 // some config settings
646
647 Read(_T( "SpaceDropMark" ), &g_bSpaceDropMark);
648
649 int mem_limit = 0;
650 Read(_T ( "MEMCacheLimit" ), &mem_limit);
651 if (mem_limit > 0)
652 g_memCacheLimit = mem_limit * 1024; // convert from MBytes to kBytes
653
654 Read(_T ( "UseModernUI5" ), &g_useMUI);
655
656 Read(_T( "NCPUCount" ), &g_nCPUCount);
657
658 Read(_T ( "DebugGDAL" ), &g_bGDAL_Debug);
659 Read(_T ( "DebugNMEA" ), &g_nNMEADebug);
660 Read(_T ( "AnchorWatchDefault" ), &g_nAWDefault);
661 Read(_T ( "AnchorWatchMax" ), &g_nAWMax);
662 Read(_T ( "GPSDogTimeout" ), &gps_watchdog_timeout_ticks);
663 Read(_T ( "DebugCM93" ), &g_bDebugCM93);
664 Read(_T ( "DebugS57" ),
665 &g_bDebugS57); // Show LUP and Feature info in object query
666 Read(_T ( "DebugBSBImg" ), &g_BSBImgDebug);
667 Read(_T ( "DebugGPSD" ), &g_bDebugGPSD);
668 Read(_T ( "MaxZoomScale" ), &g_maxzoomin);
669 g_maxzoomin = wxMax(g_maxzoomin, 50);
670
671 Read(_T ( "DefaultFontSize"), &g_default_font_size);
672 Read(_T ( "DefaultFontFacename"), &g_default_font_facename);
673
674 Read(_T ( "UseGreenShipIcon" ), &g_bUseGreenShip);
675
676 Read(_T ( "AutoHideToolbar" ), &g_bAutoHideToolbar);
677 Read(_T ( "AutoHideToolbarSecs" ), &g_nAutoHideToolbar);
678
679 Read(_T ( "UseSimplifiedScalebar" ), &g_bsimplifiedScalebar);
680 Read(_T ( "ShowTide" ), &g_bShowTide);
681 Read(_T ( "ShowCurrent" ), &g_bShowCurrent);
682
683 wxString size_mm;
684 Read(_T ( "DisplaySizeMM" ), &size_mm);
685
686 Read(_T ( "SelectionRadiusMM" ), &g_selection_radius_mm);
687 Read(_T ( "SelectionRadiusTouchMM" ), &g_selection_radius_touch_mm);
688
689 if (!bAsTemplate) {
691 wxStringTokenizer tokenizer(size_mm, ",");
692 while (tokenizer.HasMoreTokens()) {
693 wxString token = tokenizer.GetNextToken();
694 int size;
695 try {
696 size = std::stoi(token.ToStdString());
697 } catch (std::invalid_argument &e) {
698 size = 0;
699 }
700 if (size > 100 && size < 2000) {
701 g_config_display_size_mm.push_back(size);
702 } else {
703 g_config_display_size_mm.push_back(0);
704 }
705 }
706 Read(_T ( "DisplaySizeManual" ), &g_config_display_size_manual);
707 }
708
709 Read(_T ( "GUIScaleFactor" ), &g_GUIScaleFactor);
710
711 Read(_T ( "ChartObjectScaleFactor" ), &g_ChartScaleFactor);
712 Read(_T ( "ShipScaleFactor" ), &g_ShipScaleFactor);
713 Read(_T ( "ENCSoundingScaleFactor" ), &g_ENCSoundingScaleFactor);
714 Read(_T ( "ENCTextScaleFactor" ), &g_ENCTextScaleFactor);
715 Read(_T ( "ObjQueryAppendFilesExt" ), &g_ObjQFileExt);
716
717 // Plugin catalog handler persistent variables.
718 Read("CatalogCustomURL", &g_catalog_custom_url);
719 Read("CatalogChannel", &g_catalog_channel);
720
721 Read("NetmaskBits", &g_netmask_bits);
722
723 // NMEA connection options.
724 if (!bAsTemplate) {
725 Read(_T ( "FilterNMEA_Avg" ), &g_bfilter_cogsog);
726 Read(_T ( "FilterNMEA_Sec" ), &g_COGFilterSec);
727 Read(_T ( "GPSIdent" ), &g_GPS_Ident);
728 Read(_T ( "UseGarminHostUpload" ), &g_bGarminHostUpload);
729 Read(_T ( "UseNMEA_GLL" ), &g_bUseGLL);
730 Read(_T ( "UseMagAPB" ), &g_bMagneticAPB);
731 Read(_T ( "TrackContinuous" ), &g_btrackContinuous, false);
732 Read(_T ( "FilterTrackDropLargeJump" ), &g_trackFilterMax, 1000);
733 }
734
735 Read(_T ( "ShowTrue" ), &g_bShowTrue);
736 Read(_T ( "ShowMag" ), &g_bShowMag);
737
738 wxString umv;
739 Read(_T ( "UserMagVariation" ), &umv);
740 if (umv.Len()) umv.ToDouble(&g_UserVar);
741
742 Read(_T ( "ScreenBrightness" ), &g_nbrightness);
743
744 Read(_T ( "MemFootprintTargetMB" ), &g_MemFootMB);
745
746 Read(_T ( "WindowsComPortMax" ), &g_nCOMPortCheck);
747
748 Read(_T ( "ChartQuilting" ), &g_bQuiltEnable);
749 Read(_T ( "ChartQuiltingInitial" ), &g_bQuiltStart);
750
751 Read(_T ( "CourseUpMode" ), &g_bCourseUp);
752 Read(_T ( "COGUPAvgSeconds" ), &g_COGAvgSec);
753 Read(_T ( "LookAheadMode" ), &g_bLookAhead);
754 Read(_T ( "SkewToNorthUp" ), &g_bskew_comp);
755 Read(_T ( "TenHzUpdate" ), &g_btenhertz, 0);
756 Read(_T ( "DeclutterAnchorage" ), &g_declutter_anchorage, 0);
757
758 Read(_T( "NMEAAPBPrecision" ), &g_NMEAAPBPrecision);
759
760 Read(_T( "TalkerIdText" ), &g_TalkerIdText);
761 Read(_T( "MaxWaypointNameLength" ), &g_maxWPNameLength);
762 Read(_T( "MbtilesMaxLayers" ), &g_mbtilesMaxLayers);
763
764 Read(_T( "ShowTrackPointTime" ), &g_bShowTrackPointTime, true);
765 /* opengl options */
766#ifdef ocpnUSE_GL
767 if (!bAsTemplate) {
768 Read(_T ( "OpenGLExpert" ), &g_bGLexpert, false);
769 Read(_T ( "UseAcceleratedPanning" ), &g_GLOptions.m_bUseAcceleratedPanning,
770 true);
771 Read(_T ( "GPUTextureCompression" ), &g_GLOptions.m_bTextureCompression);
772 Read(_T ( "GPUTextureCompressionCaching" ),
773 &g_GLOptions.m_bTextureCompressionCaching);
774 Read(_T ( "PolygonSmoothing" ), &g_GLOptions.m_GLPolygonSmoothing);
775 Read(_T ( "LineSmoothing" ), &g_GLOptions.m_GLLineSmoothing);
776 Read(_T ( "GPUTextureDimension" ), &g_GLOptions.m_iTextureDimension);
777 Read(_T ( "GPUTextureMemSize" ), &g_GLOptions.m_iTextureMemorySize);
778 Read(_T ( "DebugOpenGL" ), &g_bDebugOGL);
779 Read(_T ( "OpenGL" ), &g_bopengl);
780 Read(_T ( "SoftwareGL" ), &g_bSoftwareGL);
781 }
782#endif
783
784 Read(_T ( "SmoothPanZoom" ), &g_bsmoothpanzoom);
785
786 Read(_T ( "ToolbarX"), &g_maintoolbar_x);
787 Read(_T ( "ToolbarY" ), &g_maintoolbar_y);
788 Read(_T ( "ToolbarOrient" ), &g_maintoolbar_orient);
789 Read(_T ( "GlobalToolbarConfig" ), &g_toolbarConfig);
790
791 Read(_T ( "iENCToolbarX"), &g_iENCToolbarPosX);
792 Read(_T ( "iENCToolbarY"), &g_iENCToolbarPosY);
793
794 Read(_T ( "AnchorWatch1GUID" ), &g_AW1GUID);
795 Read(_T ( "AnchorWatch2GUID" ), &g_AW2GUID);
796
797 Read(_T ( "InitialStackIndex" ), &g_restore_stackindex);
798 Read(_T ( "InitialdBIndex" ), &g_restore_dbindex);
799
800 Read(_T ( "ChartNotRenderScaleFactor" ), &g_ChartNotRenderScaleFactor);
801
802 Read(_T ( "MobileTouch" ), &g_btouch);
803
804// "Responsive graphics" option deprecated in O58+
805// Read(_T ( "ResponsiveGraphics" ), &g_bresponsive);
806#ifdef __ANDROID__
807 g_bresponsive = true;
808#else
809 g_bresponsive = false;
810#endif
811
812 Read(_T ( "EnableRolloverBlock" ), &g_bRollover);
813
814 Read(_T ( "ZoomDetailFactor" ), &g_chart_zoom_modifier_raster);
815 Read(_T ( "ZoomDetailFactorVector" ), &g_chart_zoom_modifier_vector);
816 Read(_T ( "PlusMinusZoomFactor" ), &g_plus_minus_zoom_factor, 2.0);
817 Read("MouseZoomSensitivity", &g_mouse_zoom_sensitivity, 1.3);
818 g_mouse_zoom_sensitivity_ui =
819 MouseZoom::config_to_ui(g_mouse_zoom_sensitivity);
820 Read(_T ( "CM93DetailFactor" ), &g_cm93_zoom_factor);
821
822 Read(_T ( "CM93DetailZoomPosX" ), &g_detailslider_dialog_x);
823 Read(_T ( "CM93DetailZoomPosY" ), &g_detailslider_dialog_y);
824 Read(_T ( "ShowCM93DetailSlider" ), &g_bShowDetailSlider);
825
826 Read(_T ( "SENC_LOD_Pixels" ), &g_SENC_LOD_pixels);
827
828 Read(_T ( "SkewCompUpdatePeriod" ), &g_SkewCompUpdatePeriod);
829
830 Read(_T ( "SetSystemTime" ), &s_bSetSystemTime);
831 Read(_T ( "ShowStatusBar" ), &g_bShowStatusBar);
832#ifndef __WXOSX__
833 Read(_T ( "ShowMenuBar" ), &g_bShowMenuBar);
834#endif
835 Read(_T ( "Fullscreen" ), &g_bFullscreen);
836 Read(_T ( "ShowCompassWindow" ), &g_bShowCompassWin);
837 Read(_T ( "ShowGrid" ), &g_bDisplayGrid);
838 Read(_T ( "PlayShipsBells" ), &g_bPlayShipsBells);
839 Read(_T ( "SoundDeviceIndex" ), &g_iSoundDeviceIndex);
840 Read(_T ( "FullscreenToolbar" ), &g_bFullscreenToolbar);
841 Read(_T ( "PermanentMOBIcon" ), &g_bPermanentMOBIcon);
842 Read(_T ( "ShowLayers" ), &g_bShowLayers);
843 Read(_T ( "ShowDepthUnits" ), &g_bShowDepthUnits);
844 Read(_T ( "AutoAnchorDrop" ), &g_bAutoAnchorMark);
845 Read(_T ( "ShowChartOutlines" ), &g_bShowOutlines);
846 Read(_T ( "ShowActiveRouteHighway" ), &g_bShowActiveRouteHighway);
847 Read(_T ( "ShowActiveRouteTotal" ), &g_bShowRouteTotal);
848 Read(_T ( "MostRecentGPSUploadConnection" ), &g_uploadConnection);
849 Read(_T ( "ShowChartBar" ), &g_bShowChartBar);
850 Read(_T ( "SDMMFormat" ),
851 &g_iSDMMFormat); // 0 = "Degrees, Decimal minutes"), 1 = "Decimal
852 // degrees", 2 = "Degrees,Minutes, Seconds"
853
854 Read(_T ( "DistanceFormat" ),
855 &g_iDistanceFormat); // 0 = "Nautical miles"), 1 = "Statute miles", 2 =
856 // "Kilometers", 3 = "Meters"
857 Read(_T ( "SpeedFormat" ),
858 &g_iSpeedFormat); // 0 = "kts"), 1 = "mph", 2 = "km/h", 3 = "m/s"
859 Read(_T ( "WindSpeedFormat" ),
860 &g_iWindSpeedFormat); // 0 = "knots"), 1 = "m/s", 2 = "Mph", 3 = "km/h"
861 Read(_T ("TemperatureFormat"), &g_iTempFormat); // 0 = C, 1 = F, 2 = K
862
863 // LIVE ETA OPTION
864 Read(_T ( "LiveETA" ), &g_bShowLiveETA);
865 Read(_T ( "DefaultBoatSpeed" ), &g_defaultBoatSpeed);
866
867 Read(_T ( "OwnshipCOGPredictorMinutes" ), &g_ownship_predictor_minutes);
868 Read(_T ( "OwnshipCOGPredictorStyle" ), &g_cog_predictor_style);
869 Read(_T ( "OwnshipCOGPredictorColor" ), &g_cog_predictor_color);
870 Read(_T ( "OwnshipCOGPredictorEndmarker" ), &g_cog_predictor_endmarker);
871 Read(_T ( "OwnshipCOGPredictorWidth" ), &g_cog_predictor_width);
872 Read(_T ( "OwnshipHDTPredictorStyle" ), &g_ownship_HDTpredictor_style);
873 Read(_T ( "OwnshipHDTPredictorColor" ), &g_ownship_HDTpredictor_color);
874 Read(_T ( "OwnshipHDTPredictorEndmarker" ),
875 &g_ownship_HDTpredictor_endmarker);
876 Read(_T ( "OwnshipHDTPredictorWidth" ), &g_ownship_HDTpredictor_width);
877 Read(_T ( "OwnshipHDTPredictorMiles" ), &g_ownship_HDTpredictor_miles);
878 int mmsi;
879 Read(_T ( "OwnShipMMSINumber" ), &mmsi);
880 g_OwnShipmmsi = mmsi >= 0 ? static_cast<unsigned>(mmsi) : 0;
881 Read(_T ( "OwnShipIconType" ), &g_OwnShipIconType);
882 Read(_T ( "OwnShipLength" ), &g_n_ownship_length_meters);
883 Read(_T ( "OwnShipWidth" ), &g_n_ownship_beam_meters);
884 Read(_T ( "OwnShipGPSOffsetX" ), &g_n_gps_antenna_offset_x);
885 Read(_T ( "OwnShipGPSOffsetY" ), &g_n_gps_antenna_offset_y);
886 Read(_T ( "OwnShipMinSize" ), &g_n_ownship_min_mm);
887 Read(_T ( "OwnShipSogCogCalc" ), &g_own_ship_sog_cog_calc);
888 Read(_T ( "OwnShipSogCogCalcDampSec"), &g_own_ship_sog_cog_calc_damp_sec);
889 Read(_T ( "ShowDirectRouteLine"), &g_bShowShipToActive);
890 Read(_T ( "DirectRouteLineStyle"), &g_shipToActiveStyle);
891 Read(_T( "DirectRouteLineColor" ), &g_shipToActiveColor);
892
893 wxString racr;
894 Read(_T ( "RouteArrivalCircleRadius" ), &racr);
895 if (racr.Len()) racr.ToDouble(&g_n_arrival_circle_radius);
896
897 Read(_T ( "FullScreenQuilt" ), &g_bFullScreenQuilt);
898
899 Read(_T ( "StartWithTrackActive" ), &g_bTrackCarryOver);
900 Read(_T ( "AutomaticDailyTracks" ), &g_bTrackDaily);
901 Read(_T ( "TrackRotateAt" ), &g_track_rotate_time);
902 Read(_T ( "TrackRotateTimeType" ), &g_track_rotate_time_type);
903 Read(_T ( "HighlightTracks" ), &g_bHighliteTracks);
904
905 Read(_T ( "DateTimeFormat" ), &g_datetime_format);
906
907 wxString stps;
908 Read(_T ( "PlanSpeed" ), &stps);
909 if (!stps.IsEmpty()) stps.ToDouble(&g_PlanSpeed);
910
911 Read(_T ( "VisibleLayers" ), &g_VisibleLayers);
912 Read(_T ( "InvisibleLayers" ), &g_InvisibleLayers);
913 Read(_T ( "VisNameInLayers" ), &g_VisiNameinLayers);
914 Read(_T ( "InvisNameInLayers" ), &g_InVisiNameinLayers);
915
916 Read(_T ( "PreserveScaleOnX" ), &g_bPreserveScaleOnX);
917
918 Read(_T ( "ShowMUIZoomButtons" ), &g_bShowMuiZoomButtons);
919
920 Read(_T ( "Locale" ), &g_locale);
921 Read(_T ( "LocaleOverride" ), &g_localeOverride);
922
923 // We allow 0-99 backups ov navobj.xml
924 Read(_T ( "KeepNavobjBackups" ), &g_navobjbackups);
925
926 // Boolean to cater for legacy Input COM Port filer behaviour, i.e. show msg
927 // filtered but put msg on bus.
928 Read(_T ( "LegacyInputCOMPortFilterBehaviour" ),
929 &g_b_legacy_input_filter_behaviour);
930
931 // Boolean to cater for sailing when not approaching waypoint
932 Read(_T( "AdvanceRouteWaypointOnArrivalOnly" ),
933 &g_bAdvanceRouteWaypointOnArrivalOnly);
934 Read("EnableRootMenuDebug", &g_enable_root_menu_debug);
935
936 Read(_T ( "EnableRotateKeys" ), &g_benable_rotate);
937 Read(_T ( "EmailCrashReport" ), &g_bEmailCrashReport);
938
939 g_benableAISNameCache = true;
940 Read(_T ( "EnableAISNameCache" ), &g_benableAISNameCache);
941
942 Read(_T ( "EnableUDPNullHeader" ), &g_benableUDPNullHeader);
943
944 SetPath(_T ( "/Settings/GlobalState" ));
945
946 Read(_T ( "FrameWinX" ), &g_nframewin_x);
947 Read(_T ( "FrameWinY" ), &g_nframewin_y);
948 Read(_T ( "FrameWinPosX" ), &g_nframewin_posx);
949 Read(_T ( "FrameWinPosY" ), &g_nframewin_posy);
950 Read(_T ( "FrameMax" ), &g_bframemax);
951
952 Read(_T ( "ClientPosX" ), &g_lastClientRectx);
953 Read(_T ( "ClientPosY" ), &g_lastClientRecty);
954 Read(_T ( "ClientSzX" ), &g_lastClientRectw);
955 Read(_T ( "ClientSzY" ), &g_lastClientRecth);
956
957 Read(_T( "RoutePropSizeX" ), &g_route_prop_sx);
958 Read(_T( "RoutePropSizeY" ), &g_route_prop_sy);
959 Read(_T( "RoutePropPosX" ), &g_route_prop_x);
960 Read(_T( "RoutePropPosY" ), &g_route_prop_y);
961
962 read_int = -1;
963 Read(_T ( "S52_DEPTH_UNIT_SHOW" ), &read_int); // default is metres
964 if (read_int >= 0) {
965 read_int = wxMax(read_int, 0); // qualify value
966 read_int = wxMin(read_int, 2);
967 g_nDepthUnitDisplay = read_int;
968 }
969
970 // Sounds
971 SetPath(_T ( "/Settings/Audio" ));
972
973 // Set reasonable defaults
974 wxString sound_dir = g_Platform->GetSharedDataDir();
975 sound_dir.Append("sounds");
976 sound_dir.Append(wxFileName::GetPathSeparator());
977
978 g_AIS_sound_file = sound_dir + "beep_ssl.wav";
979 g_DSC_sound_file = sound_dir + "phonering1.wav";
980 g_SART_sound_file = sound_dir + "beep3.wav";
981 g_anchorwatch_sound_file = sound_dir + "beep1.wav";
982
983 Read(_T ( "AISAlertSoundFile" ), &g_AIS_sound_file);
984 Read(_T ( "DSCAlertSoundFile" ), &g_DSC_sound_file);
985 Read(_T ( "SARTAlertSoundFile" ), &g_SART_sound_file);
986 Read(_T ( "AnchorAlarmSoundFile" ), &g_anchorwatch_sound_file);
987
988 Read(_T ( "bAIS_GCPA_AlertAudio" ), &g_bAIS_GCPA_Alert_Audio);
989 Read(_T ( "bAIS_SART_AlertAudio" ), &g_bAIS_SART_Alert_Audio);
990 Read(_T ( "bAIS_DSC_AlertAudio" ), &g_bAIS_DSC_Alert_Audio);
991 Read(_T ( "bAnchorAlertAudio" ), &g_bAnchor_Alert_Audio);
992
993 // AIS
994 wxString s;
995 SetPath(_T ( "/Settings/AIS" ));
996
997 g_bUseOnlyConfirmedAISName = false;
998 Read(_T ( "UseOnlyConfirmedAISName" ), &g_bUseOnlyConfirmedAISName);
999
1000 Read(_T ( "bNoCPAMax" ), &g_bCPAMax);
1001
1002 Read(_T ( "NoCPAMaxNMi" ), &s);
1003 s.ToDouble(&g_CPAMax_NM);
1004
1005 Read(_T ( "bCPAWarn" ), &g_bCPAWarn);
1006
1007 Read(_T ( "CPAWarnNMi" ), &s);
1008 s.ToDouble(&g_CPAWarn_NM);
1009
1010 Read(_T ( "bTCPAMax" ), &g_bTCPA_Max);
1011
1012 Read(_T ( "TCPAMaxMinutes" ), &s);
1013 s.ToDouble(&g_TCPA_Max);
1014
1015 Read(_T ( "bMarkLostTargets" ), &g_bMarkLost);
1016
1017 Read(_T ( "MarkLost_Minutes" ), &s);
1018 s.ToDouble(&g_MarkLost_Mins);
1019
1020 Read(_T ( "bRemoveLostTargets" ), &g_bRemoveLost);
1021
1022 Read(_T ( "RemoveLost_Minutes" ), &s);
1023 s.ToDouble(&g_RemoveLost_Mins);
1024
1025 Read(_T ( "bShowCOGArrows" ), &g_bShowCOG);
1026
1027 Read(_T ("bSyncCogPredictors"), &g_bSyncCogPredictors);
1028
1029 Read(_T ( "CogArrowMinutes" ), &s);
1030 s.ToDouble(&g_ShowCOG_Mins);
1031
1032 Read(_T ( "bShowTargetTracks" ), &g_bAISShowTracks);
1033
1034 if (Read(_T ( "TargetTracksLimit" ), &s)) {
1035 s.ToDouble(&g_AISShowTracks_Limit);
1036 g_AISShowTracks_Limit = wxMax(300.0, g_AISShowTracks_Limit);
1037 }
1038 if (Read(_T ( "TargetTracksMinutes" ), &s)) {
1039 s.ToDouble(&g_AISShowTracks_Mins);
1040 g_AISShowTracks_Mins = wxMax(1.0, g_AISShowTracks_Mins);
1041 g_AISShowTracks_Mins = wxMin(g_AISShowTracks_Limit, g_AISShowTracks_Mins);
1042 }
1043
1044 Read(_T ( "bHideMooredTargets" ), &g_bHideMoored);
1045 if (Read(_T ( "MooredTargetMaxSpeedKnots" ), &s))
1046 s.ToDouble(&g_ShowMoored_Kts);
1047
1048 g_SOGminCOG_kts = 0.2;
1049 if (Read(_T ( "SOGMinimumForCOGDisplay" ), &s)) s.ToDouble(&g_SOGminCOG_kts);
1050
1051 Read(_T ("bShowScaledTargets"), &g_bAllowShowScaled);
1052 Read(_T ( "AISScaledNumber" ), &g_ShowScaled_Num);
1053 Read(_T ( "AISScaledNumberWeightSOG" ), &g_ScaledNumWeightSOG);
1054 Read(_T ( "AISScaledNumberWeightCPA" ), &g_ScaledNumWeightCPA);
1055 Read(_T ( "AISScaledNumberWeightTCPA" ), &g_ScaledNumWeightTCPA);
1056 Read(_T ( "AISScaledNumberWeightRange" ), &g_ScaledNumWeightRange);
1057 Read(_T ( "AISScaledNumberWeightSizeOfTarget" ), &g_ScaledNumWeightSizeOfT);
1058 Read(_T ( "AISScaledSizeMinimal" ), &g_ScaledSizeMinimal);
1059 Read("AISShowScaled", &g_bShowScaled);
1060
1061 Read(_T ( "bShowAreaNotices" ), &g_bShowAreaNotices);
1062 Read(_T ( "bDrawAISSize" ), &g_bDrawAISSize);
1063 Read(_T ( "bDrawAISRealtime" ), &g_bDrawAISRealtime);
1064 Read(_T ( "bShowAISName" ), &g_bShowAISName);
1065 Read(_T ( "AISRealtimeMinSpeedKnots" ), &g_AIS_RealtPred_Kts, 0.7);
1066 Read(_T ( "bAISAlertDialog" ), &g_bAIS_CPA_Alert);
1067 Read(_T ( "ShowAISTargetNameScale" ), &g_Show_Target_Name_Scale);
1068 Read(_T ( "bWplIsAprsPositionReport" ), &g_bWplUsePosition);
1069 Read(_T ( "WplSelAction"), &g_WplAction);
1070 Read(_T ( "AISCOGPredictorWidth" ), &g_ais_cog_predictor_width);
1071
1072 Read(_T ( "bAISAlertAudio" ), &g_bAIS_CPA_Alert_Audio);
1073 Read(_T ( "AISAlertAudioFile" ), &g_sAIS_Alert_Sound_File);
1074 Read(_T ( "bAISAlertSuppressMoored" ), &g_bAIS_CPA_Alert_Suppress_Moored);
1075
1076 Read(_T ( "bAISAlertAckTimeout" ), &g_bAIS_ACK_Timeout);
1077 if (Read(_T ( "AlertAckTimeoutMinutes" ), &s)) s.ToDouble(&g_AckTimeout_Mins);
1078
1079 Read(_T ( "AlertDialogSizeX" ), &g_ais_alert_dialog_sx);
1080 Read(_T ( "AlertDialogSizeY" ), &g_ais_alert_dialog_sy);
1081 Read(_T ( "AlertDialogPosX" ), &g_ais_alert_dialog_x);
1082 Read(_T ( "AlertDialogPosY" ), &g_ais_alert_dialog_y);
1083 Read(_T ( "QueryDialogPosX" ), &g_ais_query_dialog_x);
1084 Read(_T ( "QueryDialogPosY" ), &g_ais_query_dialog_y);
1085
1086 Read(_T ( "AISTargetListPerspective" ), &g_AisTargetList_perspective);
1087 Read(_T ( "AISTargetListRange" ), &g_AisTargetList_range);
1088 Read(_T ( "AISTargetListSortColumn" ), &g_AisTargetList_sortColumn);
1089 Read(_T ( "bAISTargetListSortReverse" ), &g_bAisTargetList_sortReverse);
1090 Read(_T ( "AISTargetListColumnSpec" ), &g_AisTargetList_column_spec);
1091 Read(_T ("AISTargetListColumnOrder"), &g_AisTargetList_column_order);
1092
1093 Read(_T ( "bAISRolloverShowClass" ), &g_bAISRolloverShowClass);
1094 Read(_T ( "bAISRolloverShowCOG" ), &g_bAISRolloverShowCOG);
1095 Read(_T ( "bAISRolloverShowCPA" ), &g_bAISRolloverShowCPA);
1096
1097 Read(_T ( "S57QueryDialogSizeX" ), &g_S57_dialog_sx);
1098 Read(_T ( "S57QueryDialogSizeY" ), &g_S57_dialog_sy);
1099 Read(_T ( "S57QueryExtraDialogSizeX" ), &g_S57_extradialog_sx);
1100 Read(_T ( "S57QueryExtraDialogSizeY" ), &g_S57_extradialog_sy);
1101
1102 wxString strpres(_T ( "PresentationLibraryData" ));
1103 wxString valpres;
1104 SetPath(_T ( "/Directories" ));
1105 Read(strpres, &valpres); // Get the File name
1106 if (!valpres.IsEmpty()) g_UserPresLibData = valpres;
1107
1108 wxString strs(_T ( "SENCFileLocation" ));
1109 SetPath(_T ( "/Directories" ));
1110 wxString vals;
1111 Read(strs, &vals); // Get the Directory name
1112 if (!vals.IsEmpty()) g_SENCPrefix = vals;
1113
1114 SetPath(_T ( "/Directories" ));
1115 wxString vald;
1116 Read(_T ( "InitChartDir" ), &vald); // Get the Directory name
1117
1118 wxString dirnamed(vald);
1119 if (!dirnamed.IsEmpty()) {
1120 if (pInit_Chart_Dir->IsEmpty()) // on second pass, don't overwrite
1121 {
1122 pInit_Chart_Dir->Clear();
1123 pInit_Chart_Dir->Append(vald);
1124 }
1125 }
1126
1127 Read(_T ( "GPXIODir" ), &g_gpx_path); // Get the Directory name
1128 Read(_T ( "TCDataDir" ), &g_TCData_Dir); // Get the Directory name
1129 Read(_T ( "BasemapDir"), &gWorldMapLocation);
1130 Read(_T ( "BaseShapefileDir"), &gWorldShapefileLocation);
1131 Read(_T ( "pluginInstallDir"), &g_winPluginDir);
1132 wxLogMessage("winPluginDir, read from ini file: %s",
1133 g_winPluginDir.mb_str().data());
1134
1135 SetPath(_T ( "/Settings/GlobalState" ));
1136
1137 if (Read(_T ( "nColorScheme" ), &read_int))
1138 global_color_scheme = (ColorScheme)read_int;
1139
1140 if (!bAsTemplate) {
1141 SetPath(_T ( "/Settings/NMEADataSource" ));
1142
1143 TheConnectionParams().clear();
1144 wxString connectionconfigs;
1145 Read(_T( "DataConnections" ), &connectionconfigs);
1146 if (!connectionconfigs.IsEmpty()) {
1147 wxArrayString confs = wxStringTokenize(connectionconfigs, "|");
1148 for (size_t i = 0; i < confs.Count(); i++) {
1149 ConnectionParams *prm = new ConnectionParams(confs[i]);
1150 if (!prm->Valid) {
1151 wxLogMessage(_T( "Skipped invalid DataStream config"));
1152 delete prm;
1153 continue;
1154 }
1155 TheConnectionParams().push_back(prm);
1156 }
1157 }
1158 }
1159
1160 SetPath(_T ( "/Settings/GlobalState" ));
1161 wxString st;
1162
1163 double st_lat, st_lon;
1164 if (Read(_T ( "VPLatLon" ), &st)) {
1165 sscanf(st.mb_str(wxConvUTF8), "%lf,%lf", &st_lat, &st_lon);
1166
1167 // Sanity check the lat/lon...both have to be reasonable.
1168 if (fabs(st_lon) < 360.) {
1169 while (st_lon < -180.) st_lon += 360.;
1170
1171 while (st_lon > 180.) st_lon -= 360.;
1172
1173 vLon = st_lon;
1174 }
1175
1176 if (fabs(st_lat) < 90.0) vLat = st_lat;
1177
1178 s.Printf(_T ( "Setting Viewpoint Lat/Lon %g, %g" ), vLat, vLon);
1179 wxLogMessage(s);
1180 }
1181
1182 double st_view_scale, st_rotation;
1183 if (Read(wxString(_T ( "VPScale" )), &st)) {
1184 sscanf(st.mb_str(wxConvUTF8), "%lf", &st_view_scale);
1185 // Sanity check the scale
1186 st_view_scale = fmax(st_view_scale, .001 / 32);
1187 st_view_scale = fmin(st_view_scale, 4);
1188 }
1189
1190 if (Read(wxString(_T ( "VPRotation" )), &st)) {
1191 sscanf(st.mb_str(wxConvUTF8), "%lf", &st_rotation);
1192 // Sanity check the rotation
1193 st_rotation = fmin(st_rotation, 360);
1194 st_rotation = fmax(st_rotation, 0);
1195 }
1196
1197 wxString sll;
1198 double lat, lon;
1199 if (Read(_T ( "OwnShipLatLon" ), &sll)) {
1200 sscanf(sll.mb_str(wxConvUTF8), "%lf,%lf", &lat, &lon);
1201
1202 // Sanity check the lat/lon...both have to be reasonable.
1203 if (fabs(lon) < 360.) {
1204 while (lon < -180.) lon += 360.;
1205
1206 while (lon > 180.) lon -= 360.;
1207
1208 gLon = lon;
1209 }
1210
1211 if (fabs(lat) < 90.0) gLat = lat;
1212
1213 s.Printf(_T ( "Setting Ownship Lat/Lon %g, %g" ), gLat, gLon);
1214 wxLogMessage(s);
1215 }
1216
1217 // Fonts
1218
1219 // Load the persistent Auxiliary Font descriptor Keys
1220 SetPath(_T ( "/Settings/AuxFontKeys" ));
1221
1222 wxString strk;
1223 long dummyk;
1224 wxString kval;
1225 bool bContk = GetFirstEntry(strk, dummyk);
1226 bool bNewKey = false;
1227 while (bContk) {
1228 Read(strk, &kval);
1229 bNewKey = FontMgr::Get().AddAuxKey(kval);
1230 if (!bAsTemplate && !bNewKey) {
1231 DeleteEntry(strk);
1232 dummyk--;
1233 }
1234 bContk = GetNextEntry(strk, dummyk);
1235 }
1236
1237#ifdef __WXX11__
1238 SetPath(_T ( "/Settings/X11Fonts" ));
1239#endif
1240
1241#ifdef __WXGTK__
1242 SetPath(_T ( "/Settings/GTKFonts" ));
1243#endif
1244
1245#ifdef __WXMSW__
1246 SetPath(_T ( "/Settings/MSWFonts" ));
1247#endif
1248
1249#ifdef __WXMAC__
1250 SetPath(_T ( "/Settings/MacFonts" ));
1251#endif
1252
1253#ifdef __WXQT__
1254 SetPath(_T ( "/Settings/QTFonts" ));
1255#endif
1256
1257 wxString str;
1258 long dummy;
1259 wxString pval;
1260 wxArrayString deleteList;
1261
1262 bool bCont = GetFirstEntry(str, dummy);
1263 while (bCont) {
1264 pval = Read(str);
1265
1266 if (str.StartsWith("Font")) {
1267 // Convert pre 3.1 setting. Can't delete old entries from inside the
1268 // GetNextEntry() loop, so we need to save those and delete outside.
1269 deleteList.Add(str);
1270 wxString oldKey = pval.BeforeFirst(_T(':'));
1271 str = FontMgr::GetFontConfigKey(oldKey);
1272 }
1273
1274 if (pval.IsEmpty() || pval.StartsWith(":")) {
1275 deleteList.Add(str);
1276 } else
1277 FontMgr::Get().LoadFontNative(&str, &pval);
1278
1279 bCont = GetNextEntry(str, dummy);
1280 }
1281
1282 for (unsigned int i = 0; i < deleteList.Count(); i++) {
1283 DeleteEntry(deleteList[i]);
1284 }
1285 deleteList.Clear();
1286
1287 // Tide/Current Data Sources
1288 SetPath(_T ( "/TideCurrentDataSources" ));
1289 if (GetNumberOfEntries()) {
1290 TideCurrentDataSet.clear();
1291 wxString str, val;
1292 long dummy;
1293 bool bCont = GetFirstEntry(str, dummy);
1294 while (bCont) {
1295 Read(str, &val); // Get a file name and add it to the list just in case
1296 // it is not repeated
1297 // We have seen duplication of dataset entries in
1298 // https://github.com/OpenCPN/OpenCPN/issues/3042, this effectively gets
1299 // rid of them.
1300 if (std::find(TideCurrentDataSet.begin(), TideCurrentDataSet.end(),
1301 val.ToStdString()) == TideCurrentDataSet.end()) {
1302 TideCurrentDataSet.push_back(val.ToStdString());
1303 }
1304 bCont = GetNextEntry(str, dummy);
1305 }
1306 }
1307
1308 // Groups
1309 LoadConfigGroups(g_pGroupArray);
1310
1311 // // Multicanvas Settings
1312 // LoadCanvasConfigs();
1313
1314 SetPath(_T ( "/Settings/Others" ));
1315
1316 // Radar rings
1317 Read(_T ( "RadarRingsNumberVisible" ), &val);
1318 if (val.Length() > 0) g_iNavAidRadarRingsNumberVisible = atoi(val.mb_str());
1319 g_bNavAidRadarRingsShown = g_iNavAidRadarRingsNumberVisible > 0;
1320
1321 Read(_T ( "RadarRingsStep" ), &val);
1322 if (val.Length() > 0) g_fNavAidRadarRingsStep = atof(val.mb_str());
1323
1324 Read(_T ( "RadarRingsStepUnits" ), &g_pNavAidRadarRingsStepUnits);
1325
1326 wxString l_wxsOwnshipRangeRingsColour;
1327 Read(_T ( "RadarRingsColour" ), &l_wxsOwnshipRangeRingsColour);
1328 if (l_wxsOwnshipRangeRingsColour.Length())
1329 g_colourOwnshipRangeRingsColour.Set(l_wxsOwnshipRangeRingsColour);
1330
1331 // Waypoint Radar rings
1332 Read(_T ( "WaypointRangeRingsNumber" ), &val);
1333 if (val.Length() > 0) g_iWaypointRangeRingsNumber = atoi(val.mb_str());
1334
1335 Read(_T ( "WaypointRangeRingsStep" ), &val);
1336 if (val.Length() > 0) g_fWaypointRangeRingsStep = atof(val.mb_str());
1337
1338 Read(_T ( "WaypointRangeRingsStepUnits" ), &g_iWaypointRangeRingsStepUnits);
1339
1340 wxString l_wxsWaypointRangeRingsColour;
1341 Read(_T( "WaypointRangeRingsColour" ), &l_wxsWaypointRangeRingsColour);
1342 g_colourWaypointRangeRingsColour.Set(l_wxsWaypointRangeRingsColour);
1343
1344 if (!Read("WaypointUseScaMin", &g_bUseWptScaMin)) g_bUseWptScaMin = false;
1345 if (!Read("WaypointScaMinValue", &g_iWpt_ScaMin)) g_iWpt_ScaMin = 2147483646;
1346 if (!Read("WaypointUseScaMinOverrule", &g_bOverruleScaMin))
1347 g_bOverruleScaMin = false;
1348 if (!Read("WaypointsShowName", &g_bShowWptName)) g_bShowWptName = true;
1349 if (!Read("UserIconsFirst", &g_bUserIconsFirst)) g_bUserIconsFirst = true;
1350
1351 // Support Version 3.0 and prior config setting for Radar Rings
1352 bool b300RadarRings = true;
1353 if (Read(_T ( "ShowRadarRings" ), &b300RadarRings)) {
1354 if (!b300RadarRings) g_iNavAidRadarRingsNumberVisible = 0;
1355 }
1356
1357 Read(_T ( "ConfirmObjectDeletion" ), &g_bConfirmObjectDelete);
1358
1359 // Waypoint dragging with mouse
1360 g_bWayPointPreventDragging = false;
1361 Read(_T ( "WaypointPreventDragging" ), &g_bWayPointPreventDragging);
1362
1363 g_bEnableZoomToCursor = false;
1364 Read(_T ( "EnableZoomToCursor" ), &g_bEnableZoomToCursor);
1365
1366 val.Clear();
1367 Read(_T ( "TrackIntervalSeconds" ), &val);
1368 if (val.Length() > 0) {
1369 double tval = atof(val.mb_str());
1370 if (tval >= 2.) g_TrackIntervalSeconds = tval;
1371 }
1372
1373 val.Clear();
1374 Read(_T ( "TrackDeltaDistance" ), &val);
1375 if (val.Length() > 0) {
1376 double tval = atof(val.mb_str());
1377 if (tval >= 0.05) g_TrackDeltaDistance = tval;
1378 }
1379
1380 Read(_T ( "TrackPrecision" ), &g_nTrackPrecision);
1381
1382 Read(_T ( "RouteLineWidth" ), &g_route_line_width);
1383 Read(_T ( "TrackLineWidth" ), &g_track_line_width);
1384
1385 wxString l_wxsTrackLineColour;
1386 if (Read(_T( "TrackLineColour" ), &l_wxsTrackLineColour))
1387 g_colourTrackLineColour.Set(l_wxsTrackLineColour);
1388
1389 Read(_T ( "TideCurrentWindowScale" ), &g_tcwin_scale);
1390 Read(_T ( "DefaultWPIcon" ), &g_default_wp_icon);
1391 Read(_T ( "DefaultRPIcon" ), &g_default_routepoint_icon);
1392
1393 SetPath(_T ( "/MmsiProperties" ));
1394 int iPMax = GetNumberOfEntries();
1395 if (iPMax) {
1396 g_MMSI_Props_Array.Empty();
1397 wxString str, val;
1398 long dummy;
1399 bool bCont = pConfig->GetFirstEntry(str, dummy);
1400 while (bCont) {
1401 pConfig->Read(str, &val); // Get an entry
1402
1403 MmsiProperties *pProps = new MmsiProperties(val);
1404 g_MMSI_Props_Array.Add(pProps);
1405
1406 bCont = pConfig->GetNextEntry(str, dummy);
1407 }
1408 }
1409
1410 return (0);
1411}
1412
1413void MyConfig::LoadS57Config() {
1414 if (!ps52plib) return;
1415
1416 int read_int;
1417 double dval;
1418 SetPath(_T ( "/Settings/GlobalState" ));
1419
1420 Read(_T ( "bShowS57Text" ), &read_int, 1);
1421 ps52plib->SetShowS57Text(!(read_int == 0));
1422
1423 Read(_T ( "bShowS57ImportantTextOnly" ), &read_int, 0);
1424 ps52plib->SetShowS57ImportantTextOnly(!(read_int == 0));
1425
1426 Read(_T ( "bShowLightDescription" ), &read_int, 0);
1427 ps52plib->SetShowLdisText(!(read_int == 0));
1428
1429 Read(_T ( "bExtendLightSectors" ), &read_int, 0);
1430 ps52plib->SetExtendLightSectors(!(read_int == 0));
1431
1432 Read(_T ( "nDisplayCategory" ), &read_int, (enum _DisCat)STANDARD);
1433 ps52plib->SetDisplayCategory((enum _DisCat)read_int);
1434
1435 Read(_T ( "nSymbolStyle" ), &read_int, (enum _LUPname)PAPER_CHART);
1436 ps52plib->m_nSymbolStyle = (LUPname)read_int;
1437
1438 Read(_T ( "nBoundaryStyle" ), &read_int, PLAIN_BOUNDARIES);
1439 ps52plib->m_nBoundaryStyle = (LUPname)read_int;
1440
1441 Read(_T ( "bShowSoundg" ), &read_int, 1);
1442 ps52plib->m_bShowSoundg = !(read_int == 0);
1443
1444 Read(_T ( "bShowMeta" ), &read_int, 0);
1445 ps52plib->m_bShowMeta = !(read_int == 0);
1446
1447 Read(_T ( "bUseSCAMIN" ), &read_int, 1);
1448 ps52plib->m_bUseSCAMIN = !(read_int == 0);
1449
1450 Read(_T ( "bUseSUPER_SCAMIN" ), &read_int, 0);
1451 ps52plib->m_bUseSUPER_SCAMIN = !(read_int == 0);
1452
1453 Read(_T ( "bShowAtonText" ), &read_int, 1);
1454 ps52plib->m_bShowAtonText = !(read_int == 0);
1455
1456 Read(_T ( "bDeClutterText" ), &read_int, 0);
1457 ps52plib->m_bDeClutterText = !(read_int == 0);
1458
1459 Read(_T ( "bShowNationalText" ), &read_int, 0);
1460 ps52plib->m_bShowNationalTexts = !(read_int == 0);
1461
1462 Read(_T ( "ENCSoundingScaleFactor" ), &read_int, 0);
1463 ps52plib->m_nSoundingFactor = read_int;
1464
1465 Read(_T ( "ENCTextScaleFactor" ), &read_int, 0);
1466 ps52plib->m_nTextFactor = read_int;
1467
1468 if (Read(_T ( "S52_MAR_SAFETY_CONTOUR" ), &dval, 3.0)) {
1469 S52_setMarinerParam(S52_MAR_SAFETY_CONTOUR, dval);
1470 S52_setMarinerParam(S52_MAR_SAFETY_DEPTH,
1471 dval); // Set safety_contour and safety_depth the same
1472 }
1473
1474 if (Read(_T ( "S52_MAR_SHALLOW_CONTOUR" ), &dval, 2.0))
1475 S52_setMarinerParam(S52_MAR_SHALLOW_CONTOUR, dval);
1476
1477 if (Read(_T ( "S52_MAR_DEEP_CONTOUR" ), &dval, 6.0))
1478 S52_setMarinerParam(S52_MAR_DEEP_CONTOUR, dval);
1479
1480 if (Read(_T ( "S52_MAR_TWO_SHADES" ), &dval, 0.0))
1481 S52_setMarinerParam(S52_MAR_TWO_SHADES, dval);
1482
1483 ps52plib->UpdateMarinerParams();
1484
1485 SetPath(_T ( "/Settings/GlobalState" ));
1486 Read(_T ( "S52_DEPTH_UNIT_SHOW" ), &read_int, 1); // default is metres
1487 read_int = wxMax(read_int, 0); // qualify value
1488 read_int = wxMin(read_int, 2);
1489 ps52plib->m_nDepthUnitDisplay = read_int;
1490 g_nDepthUnitDisplay = read_int;
1491
1492 // S57 Object Class Visibility
1493
1494 OBJLElement *pOLE;
1495
1496 SetPath(_T ( "/Settings/ObjectFilter" ));
1497
1498 int iOBJMax = GetNumberOfEntries();
1499 if (iOBJMax) {
1500 wxString str;
1501 long val;
1502 long dummy;
1503
1504 wxString sObj;
1505
1506 bool bCont = pConfig->GetFirstEntry(str, dummy);
1507 while (bCont) {
1508 pConfig->Read(str, &val); // Get an Object Viz
1509
1510 bool bNeedNew = true;
1511
1512 if (str.StartsWith(_T ( "viz" ), &sObj)) {
1513 for (unsigned int iPtr = 0; iPtr < ps52plib->pOBJLArray->GetCount();
1514 iPtr++) {
1515 pOLE = (OBJLElement *)(ps52plib->pOBJLArray->Item(iPtr));
1516 if (!strncmp(pOLE->OBJLName, sObj.mb_str(), 6)) {
1517 pOLE->nViz = val;
1518 bNeedNew = false;
1519 break;
1520 }
1521 }
1522
1523 if (bNeedNew) {
1524 pOLE = (OBJLElement *)calloc(sizeof(OBJLElement), 1);
1525 memcpy(pOLE->OBJLName, sObj.mb_str(), OBJL_NAME_LEN);
1526 pOLE->nViz = 1;
1527
1528 ps52plib->pOBJLArray->Add((void *)pOLE);
1529 }
1530 }
1531 bCont = pConfig->GetNextEntry(str, dummy);
1532 }
1533 }
1534}
1535
1536bool MyConfig::LoadLayers(wxString &path) {
1537 wxArrayString file_array;
1538 wxDir dir;
1539 Layer *l;
1540 dir.Open(path);
1541 if (dir.IsOpened()) {
1542 wxString filename;
1543 bool cont = dir.GetFirst(&filename);
1544 while (cont) {
1545 file_array.Clear();
1546 filename.Prepend(wxFileName::GetPathSeparator());
1547 filename.Prepend(path);
1548 wxFileName f(filename);
1549 size_t nfiles = 0;
1550 if (f.GetExt().IsSameAs("gpx"))
1551 file_array.Add(filename); // single-gpx-file layer
1552 else {
1553 if (wxDir::Exists(filename)) {
1554 wxDir dir(filename);
1555 if (dir.IsOpened()) {
1556 nfiles = dir.GetAllFiles(filename, &file_array,
1557 "*.gpx"); // layers subdirectory set
1558 }
1559 }
1560 }
1561
1562 if (file_array.GetCount()) {
1563 l = new Layer();
1564 l->m_LayerID = ++g_LayerIdx;
1565 l->m_LayerFileName = file_array[0];
1566 if (file_array.GetCount() <= 1)
1567 wxFileName::SplitPath(file_array[0], NULL, NULL, &(l->m_LayerName),
1568 NULL, NULL);
1569 else
1570 wxFileName::SplitPath(filename, NULL, NULL, &(l->m_LayerName), NULL,
1571 NULL);
1572
1573 bool bLayerViz = g_bShowLayers;
1574
1575 if (g_VisibleLayers.Contains(l->m_LayerName)) bLayerViz = true;
1576 if (g_InvisibleLayers.Contains(l->m_LayerName)) bLayerViz = false;
1577
1578 l->m_bHasVisibleNames = wxCHK_UNDETERMINED;
1579 if (g_VisiNameinLayers.Contains(l->m_LayerName))
1580 l->m_bHasVisibleNames = wxCHK_CHECKED;
1581 if (g_InVisiNameinLayers.Contains(l->m_LayerName))
1582 l->m_bHasVisibleNames = wxCHK_UNCHECKED;
1583
1584 l->m_bIsVisibleOnChart = bLayerViz;
1585
1586 wxString laymsg;
1587 laymsg.Printf("New layer %d: %s", l->m_LayerID, l->m_LayerName.c_str());
1588 wxLogMessage(laymsg);
1589
1590 pLayerList->insert(pLayerList->begin(), 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("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("^");
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("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("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 += ";";
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("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("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, ";");
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("/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("/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("/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("/Canvas/CanvasConfig%d", 2);
1847 SetPath(s);
1848 LoadConfigCanvas(pcca, bApplyAsTemplate);
1849 } else {
1850 s.Printf("/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("/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("/Canvas/CanvasConfig%d", 1);
1978 SetPath(s);
1979 pcc = config_array.Item(0);
1980 if (pcc) {
1981 SaveConfigCanvas(pcc);
1982 }
1983
1984 s.Printf("/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("%.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("%.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("TalkerIdText", g_TalkerIdText);
2229 Write("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("AlwaysSendRmbRmc", g_always_send_rmb_rmc);
2253
2254 Write(_T ( "UseGarminHostUpload" ), g_bGarminHostUpload);
2255
2256 Write(_T ( "MobileTouch" ), g_btouch);
2257 Write(_T ( "ResponsiveGraphics" ), g_bresponsive);
2258 Write(_T ( "EnableRolloverBlock" ), g_bRollover);
2259
2260 Write(_T ( "AutoHideToolbar" ), g_bAutoHideToolbar);
2261 Write(_T ( "AutoHideToolbarSecs" ), g_nAutoHideToolbar);
2262
2263 wxString st0;
2264 for (const auto &mm : g_config_display_size_mm) {
2265 st0.Append(wxString::Format(_T ( "%zu," ), mm));
2266 }
2267 st0.RemoveLast(); // Strip last comma
2268 Write(_T ( "DisplaySizeMM" ), st0);
2269 Write(_T ( "DisplaySizeManual" ), g_config_display_size_manual);
2270
2271 Write(_T ( "SelectionRadiusMM" ), g_selection_radius_mm);
2272 Write(_T ( "SelectionRadiusTouchMM" ), g_selection_radius_touch_mm);
2273
2274 st0.Printf(_T ( "%g" ), g_PlanSpeed);
2275 Write(_T ( "PlanSpeed" ), st0);
2276
2277 if (g_bLayersLoaded) {
2278 wxString vis, invis, visnames, invisnames;
2279 LayerList::iterator it;
2280 int index = 0;
2281 for (it = (*pLayerList).begin(); it != (*pLayerList).end(); ++it, ++index) {
2282 Layer *lay = (Layer *)(*it);
2283 if (lay->IsVisibleOnChart())
2284 vis += (lay->m_LayerName) + ";";
2285 else
2286 invis += (lay->m_LayerName) + ";";
2287
2288 if (lay->HasVisibleNames() == wxCHK_CHECKED) {
2289 visnames += (lay->m_LayerName) + ";";
2290 } else if (lay->HasVisibleNames() == wxCHK_UNCHECKED) {
2291 invisnames += (lay->m_LayerName) + ";";
2292 }
2293 }
2294 Write(_T ( "VisibleLayers" ), vis);
2295 Write(_T ( "InvisibleLayers" ), invis);
2296 Write(_T ( "VisNameInLayers" ), visnames);
2297 Write(_T ( "InvisNameInLayers" ), invisnames);
2298 }
2299 Write(_T ( "Locale" ), g_locale);
2300 Write(_T ( "LocaleOverride" ), g_localeOverride);
2301
2302 Write(_T ( "KeepNavobjBackups" ), g_navobjbackups);
2303 Write(_T ( "LegacyInputCOMPortFilterBehaviour" ),
2304 g_b_legacy_input_filter_behaviour);
2305 Write(_T( "AdvanceRouteWaypointOnArrivalOnly" ),
2306 g_bAdvanceRouteWaypointOnArrivalOnly);
2307 Write("EnableRootMenuDebug", g_enable_root_menu_debug);
2308
2309 // LIVE ETA OPTION
2310 Write(_T( "LiveETA" ), g_bShowLiveETA);
2311 Write(_T( "DefaultBoatSpeed" ), g_defaultBoatSpeed);
2312
2313 // S57 Object Filter Settings
2314
2315 SetPath(_T ( "/Settings/ObjectFilter" ));
2316
2317 if (ps52plib) {
2318 for (unsigned int iPtr = 0; iPtr < ps52plib->pOBJLArray->GetCount();
2319 iPtr++) {
2320 OBJLElement *pOLE = (OBJLElement *)(ps52plib->pOBJLArray->Item(iPtr));
2321
2322 wxString st1(_T ( "viz" ));
2323 char name[7];
2324 strncpy(name, pOLE->OBJLName, 6);
2325 name[6] = 0;
2326 st1.Append(wxString(name, wxConvUTF8));
2327 Write(st1, pOLE->nViz);
2328 }
2329 }
2330
2331 // Global State
2332
2333 SetPath(_T ( "/Settings/GlobalState" ));
2334
2335 wxString st1;
2336
2337 // if( cc1 ) {
2338 // ViewPort vp = cc1->GetVP();
2339 //
2340 // if( vp.IsValid() ) {
2341 // st1.Printf( _T ( "%10.4f,%10.4f" ), vp.clat, vp.clon );
2342 // Write( _T ( "VPLatLon" ), st1 );
2343 // st1.Printf( _T ( "%g" ), vp.view_scale_ppm );
2344 // Write( _T ( "VPScale" ), st1 );
2345 // st1.Printf( _T ( "%i" ), ((int)(vp.rotation * 180 / PI)) % 360
2346 // ); Write( _T ( "VPRotation" ), st1 );
2347 // }
2348 // }
2349
2350 st1.Printf(_T ( "%10.4f, %10.4f" ), gLat, gLon);
2351 Write(_T ( "OwnShipLatLon" ), st1);
2352
2353 // Various Options
2354 SetPath(_T ( "/Settings/GlobalState" ));
2355 if (!g_bInlandEcdis)
2356 Write(_T ( "nColorScheme" ), (int)gFrame->GetColorScheme());
2357
2358 Write(_T ( "FrameWinX" ), g_nframewin_x);
2359 Write(_T ( "FrameWinY" ), g_nframewin_y);
2360 Write(_T ( "FrameWinPosX" ), g_nframewin_posx);
2361 Write(_T ( "FrameWinPosY" ), g_nframewin_posy);
2362 Write(_T ( "FrameMax" ), g_bframemax);
2363
2364 Write(_T ( "ClientPosX" ), g_lastClientRectx);
2365 Write(_T ( "ClientPosY" ), g_lastClientRecty);
2366 Write(_T ( "ClientSzX" ), g_lastClientRectw);
2367 Write(_T ( "ClientSzY" ), g_lastClientRecth);
2368
2369 Write(_T ( "S52_DEPTH_UNIT_SHOW" ), g_nDepthUnitDisplay);
2370
2371 Write(_T( "RoutePropSizeX" ), g_route_prop_sx);
2372 Write(_T( "RoutePropSizeY" ), g_route_prop_sy);
2373 Write(_T( "RoutePropPosX" ), g_route_prop_x);
2374 Write(_T( "RoutePropPosY" ), g_route_prop_y);
2375
2376 // Sounds
2377 SetPath(_T ( "/Settings/Audio" ));
2378 Write(_T ( "AISAlertSoundFile" ), g_AIS_sound_file);
2379 Write(_T ( "DSCAlertSoundFile" ), g_DSC_sound_file);
2380 Write(_T ( "SARTAlertSoundFile" ), g_SART_sound_file);
2381 Write(_T ( "AnchorAlarmSoundFile" ), g_anchorwatch_sound_file);
2382
2383 Write(_T ( "bAIS_GCPA_AlertAudio" ), g_bAIS_GCPA_Alert_Audio);
2384 Write(_T ( "bAIS_SART_AlertAudio" ), g_bAIS_SART_Alert_Audio);
2385 Write(_T ( "bAIS_DSC_AlertAudio" ), g_bAIS_DSC_Alert_Audio);
2386 Write(_T ( "bAnchorAlertAudio" ), g_bAnchor_Alert_Audio);
2387
2388 // AIS
2389 SetPath(_T ( "/Settings/AIS" ));
2390
2391 Write(_T ( "bNoCPAMax" ), g_bCPAMax);
2392 Write(_T ( "NoCPAMaxNMi" ), g_CPAMax_NM);
2393 Write(_T ( "bCPAWarn" ), g_bCPAWarn);
2394 Write(_T ( "CPAWarnNMi" ), g_CPAWarn_NM);
2395 Write(_T ( "bTCPAMax" ), g_bTCPA_Max);
2396 Write(_T ( "TCPAMaxMinutes" ), g_TCPA_Max);
2397 Write(_T ( "bMarkLostTargets" ), g_bMarkLost);
2398 Write(_T ( "MarkLost_Minutes" ), g_MarkLost_Mins);
2399 Write(_T ( "bRemoveLostTargets" ), g_bRemoveLost);
2400 Write(_T ( "RemoveLost_Minutes" ), g_RemoveLost_Mins);
2401 Write(_T ( "bShowCOGArrows" ), g_bShowCOG);
2402 Write(_T ( "bSyncCogPredictors" ), g_bSyncCogPredictors);
2403 Write(_T ( "CogArrowMinutes" ), g_ShowCOG_Mins);
2404 Write(_T ( "bShowTargetTracks" ), g_bAISShowTracks);
2405 Write(_T ( "TargetTracksMinutes" ), g_AISShowTracks_Mins);
2406
2407 Write(_T ( "bHideMooredTargets" ), g_bHideMoored);
2408 Write(_T ( "MooredTargetMaxSpeedKnots" ), g_ShowMoored_Kts);
2409
2410 Write(_T ( "bAISAlertDialog" ), g_bAIS_CPA_Alert);
2411 Write(_T ( "bAISAlertAudio" ), g_bAIS_CPA_Alert_Audio);
2412
2413 Write(_T ( "AISAlertAudioFile" ), g_sAIS_Alert_Sound_File);
2414 Write(_T ( "bAISAlertSuppressMoored" ), g_bAIS_CPA_Alert_Suppress_Moored);
2415 Write(_T ( "bShowAreaNotices" ), g_bShowAreaNotices);
2416 Write(_T ( "bDrawAISSize" ), g_bDrawAISSize);
2417 Write(_T ( "bDrawAISRealtime" ), g_bDrawAISRealtime);
2418 Write(_T ( "AISRealtimeMinSpeedKnots" ), g_AIS_RealtPred_Kts);
2419 Write(_T ( "bShowAISName" ), g_bShowAISName);
2420 Write(_T ( "ShowAISTargetNameScale" ), g_Show_Target_Name_Scale);
2421 Write(_T ( "bWplIsAprsPositionReport" ), g_bWplUsePosition);
2422 Write(_T ( "WplSelAction" ), g_WplAction);
2423 Write(_T ( "AISCOGPredictorWidth" ), g_ais_cog_predictor_width);
2424 Write(_T ( "bShowScaledTargets" ), g_bAllowShowScaled);
2425 Write(_T ( "AISScaledNumber" ), g_ShowScaled_Num);
2426 Write(_T ( "AISScaledNumberWeightSOG" ), g_ScaledNumWeightSOG);
2427 Write(_T ( "AISScaledNumberWeightCPA" ), g_ScaledNumWeightCPA);
2428 Write(_T ( "AISScaledNumberWeightTCPA" ), g_ScaledNumWeightTCPA);
2429 Write(_T ( "AISScaledNumberWeightRange" ), g_ScaledNumWeightRange);
2430 Write(_T ( "AISScaledNumberWeightSizeOfTarget" ), g_ScaledNumWeightSizeOfT);
2431 Write(_T ( "AISScaledSizeMinimal" ), g_ScaledSizeMinimal);
2432 Write(_T ( "AISShowScaled"), g_bShowScaled);
2433
2434 Write(_T ( "AlertDialogSizeX" ), g_ais_alert_dialog_sx);
2435 Write(_T ( "AlertDialogSizeY" ), g_ais_alert_dialog_sy);
2436 Write(_T ( "AlertDialogPosX" ), g_ais_alert_dialog_x);
2437 Write(_T ( "AlertDialogPosY" ), g_ais_alert_dialog_y);
2438 Write(_T ( "QueryDialogPosX" ), g_ais_query_dialog_x);
2439 Write(_T ( "QueryDialogPosY" ), g_ais_query_dialog_y);
2440 Write(_T ( "AISTargetListPerspective" ), g_AisTargetList_perspective);
2441 Write(_T ( "AISTargetListRange" ), g_AisTargetList_range);
2442 Write(_T ( "AISTargetListSortColumn" ), g_AisTargetList_sortColumn);
2443 Write(_T ( "bAISTargetListSortReverse" ), g_bAisTargetList_sortReverse);
2444 Write(_T ( "AISTargetListColumnSpec" ), g_AisTargetList_column_spec);
2445 Write(_T ("AISTargetListColumnOrder"), g_AisTargetList_column_order);
2446
2447 Write(_T ( "S57QueryDialogSizeX" ), g_S57_dialog_sx);
2448 Write(_T ( "S57QueryDialogSizeY" ), g_S57_dialog_sy);
2449 Write(_T ( "S57QueryExtraDialogSizeX" ), g_S57_extradialog_sx);
2450 Write(_T ( "S57QueryExtraDialogSizeY" ), g_S57_extradialog_sy);
2451
2452 Write(_T ( "bAISRolloverShowClass" ), g_bAISRolloverShowClass);
2453 Write(_T ( "bAISRolloverShowCOG" ), g_bAISRolloverShowCOG);
2454 Write(_T ( "bAISRolloverShowCPA" ), g_bAISRolloverShowCPA);
2455
2456 Write(_T ( "bAISAlertAckTimeout" ), g_bAIS_ACK_Timeout);
2457 Write(_T ( "AlertAckTimeoutMinutes" ), g_AckTimeout_Mins);
2458
2459 SetPath(_T ( "/Settings/GlobalState" ));
2460 if (ps52plib) {
2461 Write(_T ( "bShowS57Text" ), ps52plib->GetShowS57Text());
2462 Write(_T ( "bShowS57ImportantTextOnly" ),
2463 ps52plib->GetShowS57ImportantTextOnly());
2464 if (!g_bInlandEcdis)
2465 Write(_T ( "nDisplayCategory" ), (long)ps52plib->GetDisplayCategory());
2466 Write(_T ( "nSymbolStyle" ), (int)ps52plib->m_nSymbolStyle);
2467 Write(_T ( "nBoundaryStyle" ), (int)ps52plib->m_nBoundaryStyle);
2468
2469 Write(_T ( "bShowSoundg" ), ps52plib->m_bShowSoundg);
2470 Write(_T ( "bShowMeta" ), ps52plib->m_bShowMeta);
2471 Write(_T ( "bUseSCAMIN" ), ps52plib->m_bUseSCAMIN);
2472 Write(_T ( "bUseSUPER_SCAMIN" ), ps52plib->m_bUseSUPER_SCAMIN);
2473 Write(_T ( "bShowAtonText" ), ps52plib->m_bShowAtonText);
2474 Write(_T ( "bShowLightDescription" ), ps52plib->m_bShowLdisText);
2475 Write(_T ( "bExtendLightSectors" ), ps52plib->m_bExtendLightSectors);
2476 Write(_T ( "bDeClutterText" ), ps52plib->m_bDeClutterText);
2477 Write(_T ( "bShowNationalText" ), ps52plib->m_bShowNationalTexts);
2478
2479 Write(_T ( "S52_MAR_SAFETY_CONTOUR" ),
2480 S52_getMarinerParam(S52_MAR_SAFETY_CONTOUR));
2481 Write(_T ( "S52_MAR_SHALLOW_CONTOUR" ),
2482 S52_getMarinerParam(S52_MAR_SHALLOW_CONTOUR));
2483 Write(_T ( "S52_MAR_DEEP_CONTOUR" ),
2484 S52_getMarinerParam(S52_MAR_DEEP_CONTOUR));
2485 Write(_T ( "S52_MAR_TWO_SHADES" ), S52_getMarinerParam(S52_MAR_TWO_SHADES));
2486 Write(_T ( "S52_DEPTH_UNIT_SHOW" ), ps52plib->m_nDepthUnitDisplay);
2487 Write(_T ( "ENCSoundingScaleFactor" ), g_ENCSoundingScaleFactor);
2488 Write(_T ( "ENCTextScaleFactor" ), g_ENCTextScaleFactor);
2489 }
2490 SetPath(_T ( "/Directories" ));
2491 Write(_T ( "S57DataLocation" ), "");
2492 // Write( _T ( "SENCFileLocation" ), "" );
2493
2494 SetPath(_T ( "/Directories" ));
2495 Write(_T ( "InitChartDir" ), *pInit_Chart_Dir);
2496 Write(_T ( "GPXIODir" ), g_gpx_path);
2497 Write(_T ( "TCDataDir" ), g_TCData_Dir);
2498 Write(_T ( "BasemapDir" ), g_Platform->NormalizePath(gWorldMapLocation));
2499 Write(_T ( "BaseShapefileDir" ),
2500 g_Platform->NormalizePath(gWorldShapefileLocation));
2501 Write(_T ( "pluginInstallDir" ), g_Platform->NormalizePath(g_winPluginDir));
2502
2503 SetPath(_T ( "/Settings/NMEADataSource" ));
2504 wxString connectionconfigs;
2505 for (size_t i = 0; i < TheConnectionParams().size(); i++) {
2506 if (i > 0) connectionconfigs.Append("|");
2507 connectionconfigs.Append(TheConnectionParams()[i]->Serialize());
2508 }
2509 Write(_T ( "DataConnections" ), connectionconfigs);
2510
2511 // Fonts
2512
2513 // Store the persistent Auxiliary Font descriptor Keys
2514 SetPath(_T ( "/Settings/AuxFontKeys" ));
2515
2516 wxArrayString keyArray = FontMgr::Get().GetAuxKeyArray();
2517 for (unsigned int i = 0; i < keyArray.GetCount(); i++) {
2518 wxString key;
2519 key.Printf("Key%i", i);
2520 wxString keyval = keyArray[i];
2521 Write(key, keyval);
2522 }
2523
2524 wxString font_path;
2525#ifdef __WXX11__
2526 font_path = (_T ( "/Settings/X11Fonts" ));
2527#endif
2528
2529#ifdef __WXGTK__
2530 font_path = (_T ( "/Settings/GTKFonts" ));
2531#endif
2532
2533#ifdef __WXMSW__
2534 font_path = (_T ( "/Settings/MSWFonts" ));
2535#endif
2536
2537#ifdef __WXMAC__
2538 font_path = (_T ( "/Settings/MacFonts" ));
2539#endif
2540
2541#ifdef __WXQT__
2542 font_path = (_T ( "/Settings/QTFonts" ));
2543#endif
2544
2545 DeleteGroup(font_path);
2546
2547 SetPath(font_path);
2548
2549 int nFonts = FontMgr::Get().GetNumFonts();
2550
2551 for (int i = 0; i < nFonts; i++) {
2552 wxString cfstring(FontMgr::Get().GetConfigString(i));
2553 wxString valstring = FontMgr::Get().GetFullConfigDesc(i);
2554 Write(cfstring, valstring);
2555 }
2556
2557 // Tide/Current Data Sources
2558 DeleteGroup(_T ( "/TideCurrentDataSources" ));
2559 SetPath(_T ( "/TideCurrentDataSources" ));
2560 unsigned int id = 0;
2561 for (auto val : TideCurrentDataSet) {
2562 wxString key;
2563 key.Printf("tcds%d", id);
2564 Write(key, wxString(val));
2565 ++id;
2566 }
2567
2568 SetPath(_T ( "/Settings/Others" ));
2569
2570 // Radar rings
2571 Write(_T ( "ShowRadarRings" ),
2572 (bool)(g_iNavAidRadarRingsNumberVisible > 0)); // 3.0.0 config support
2573 Write(_T ( "RadarRingsNumberVisible" ), g_iNavAidRadarRingsNumberVisible);
2574 Write(_T ( "RadarRingsStep" ), g_fNavAidRadarRingsStep);
2575 Write(_T ( "RadarRingsStepUnits" ), g_pNavAidRadarRingsStepUnits);
2576 Write(_T ( "RadarRingsColour" ),
2577 g_colourOwnshipRangeRingsColour.GetAsString(wxC2S_HTML_SYNTAX));
2578 Write(_T( "WaypointUseScaMin" ), g_bUseWptScaMin);
2579 Write(_T( "WaypointScaMinValue" ), g_iWpt_ScaMin);
2580 Write(_T( "WaypointUseScaMinOverrule" ), g_bOverruleScaMin);
2581 Write("WaypointsShowName", g_bShowWptName);
2582 Write("UserIconsFirst", g_bUserIconsFirst);
2583
2584 // Waypoint Radar rings
2585 Write(_T ( "WaypointRangeRingsNumber" ), g_iWaypointRangeRingsNumber);
2586 Write(_T ( "WaypointRangeRingsStep" ), g_fWaypointRangeRingsStep);
2587 Write(_T ( "WaypointRangeRingsStepUnits" ), g_iWaypointRangeRingsStepUnits);
2588 Write(_T ( "WaypointRangeRingsColour" ),
2589 g_colourWaypointRangeRingsColour.GetAsString(wxC2S_HTML_SYNTAX));
2590
2591 Write(_T ( "ConfirmObjectDeletion" ), g_bConfirmObjectDelete);
2592
2593 // Waypoint dragging with mouse; toh, 2009.02.24
2594 Write(_T ( "WaypointPreventDragging" ), g_bWayPointPreventDragging);
2595
2596 Write(_T ( "EnableZoomToCursor" ), g_bEnableZoomToCursor);
2597
2598 Write(_T ( "TrackIntervalSeconds" ), g_TrackIntervalSeconds);
2599 Write(_T ( "TrackDeltaDistance" ), g_TrackDeltaDistance);
2600 Write(_T ( "TrackPrecision" ), g_nTrackPrecision);
2601
2602 Write(_T ( "RouteLineWidth" ), g_route_line_width);
2603 Write(_T ( "TrackLineWidth" ), g_track_line_width);
2604 Write(_T ( "TrackLineColour" ),
2605 g_colourTrackLineColour.GetAsString(wxC2S_HTML_SYNTAX));
2606 Write(_T ( "DefaultWPIcon" ), g_default_wp_icon);
2607 Write(_T ( "DefaultRPIcon" ), g_default_routepoint_icon);
2608
2609 DeleteGroup(_T ( "/MmsiProperties" ));
2610 SetPath(_T ( "/MmsiProperties" ));
2611 for (unsigned int i = 0; i < g_MMSI_Props_Array.GetCount(); i++) {
2612 wxString p;
2613 p.Printf("Props%d", i);
2614 Write(p, g_MMSI_Props_Array[i]->Serialize());
2615 }
2616
2617 SaveCanvasConfigs();
2618
2619 Flush();
2620 SendMessageToAllPlugins("GLOBAL_SETTINGS_UPDATED", "{\"updated\":\"1\"}");
2621}
2622
2623static wxFileName exportFileName(wxWindow *parent,
2624 const wxString suggestedName) {
2625 wxFileName ret;
2626 wxString path;
2627 wxString valid_name = SanitizeFileName(suggestedName);
2628
2629#ifdef __ANDROID__
2630 if (!valid_name.EndsWith(".gpx")) {
2631 wxFileName fn(valid_name);
2632 fn.ClearExt();
2633 fn.SetExt("gpx");
2634 valid_name = fn.GetFullName();
2635 }
2636#endif
2637 int response = g_Platform->DoFileSelectorDialog(
2638 parent, &path, _("Export GPX file"), g_gpx_path, valid_name, "*.gpx");
2639
2640 if (response == wxID_OK) {
2641 wxFileName fn(path);
2642 g_gpx_path = fn.GetPath();
2643 if (!fn.GetExt().StartsWith("gpx")) fn.SetExt("gpx");
2644
2645#if defined(__WXMSW__) || defined(__WXGTK__)
2646 if (wxFileExists(fn.GetFullPath())) {
2647 int answer = OCPNMessageBox(NULL, _("Overwrite existing file?"),
2648 "Confirm", wxICON_QUESTION | wxYES_NO);
2649 if (answer != wxID_YES) return ret;
2650 }
2651#endif
2652 ret = fn;
2653 }
2654 return ret;
2655}
2656
2657int BackupDatabase(wxWindow *parent) {
2658 bool backupResult = false;
2659 wxDateTime tm = wxDateTime::Now();
2660 wxString proposedName = tm.Format("navobj-%Y-%m-%d_%H_%M");
2661 wxString acceptedName;
2662
2663 if (wxID_OK ==
2664 g_Platform->DoFileSelectorDialog(parent, &acceptedName, _("Backup"),
2665 wxStandardPaths::Get().GetDocumentsDir(),
2666 proposedName, "*.bkp")) {
2667 wxFileName fileName(acceptedName);
2668 if (fileName.IsOk()) {
2669#if defined(__WXMSW__) || defined(__WXGTK__)
2670 if (fileName.FileExists()) {
2671 if (wxID_YES != OCPNMessageBox(NULL, _("Overwrite existing file?"),
2672 "Confirm", wxICON_QUESTION | wxYES_NO)) {
2673 return wxID_ABORT; // We've decided not to overwrite a file, aborting
2674 }
2675 }
2676#endif
2677
2678#ifdef __ANDROID__
2679 wxString secureFileName = androidGetCacheDir() +
2680 wxFileName::GetPathSeparator() +
2681 fileName.GetFullName();
2682 backupResult = NavObj_dB::GetInstance().Backup(secureFileName);
2683 AndroidSecureCopyFile(secureFileName, fileName.GetFullPath());
2684#else
2685 backupResult = NavObj_dB::GetInstance().Backup(fileName.GetFullPath());
2686#endif
2687 }
2688 return backupResult ? wxID_YES : wxID_NO;
2689 }
2690 return wxID_ABORT; // Cancelled the file open dialog, aborting
2691}
2692
2693bool ExportGPXRoutes(wxWindow *parent, RouteList *pRoutes,
2694 const wxString suggestedName) {
2695#ifndef __ANDROID__
2696 wxFileName fn = exportFileName(parent, suggestedName);
2697 if (fn.IsOk()) {
2699 pgpx->AddGPXRoutesList(pRoutes);
2700 pgpx->SaveFile(fn.GetFullPath());
2701 delete pgpx;
2702 return true;
2703 }
2704#else
2705 // Create the .GPX file, saving it in the OCPN Android cache directory
2706 wxString fns = androidGetCacheDir() + wxFileName::GetPathSeparator() +
2707 suggestedName + ".gpx";
2709 pgpx->AddGPXRoutesList(pRoutes);
2710 pgpx->SaveFile(fns);
2711 delete pgpx;
2712
2713 // Kick off the Android file chooser activity
2714 wxString path;
2715 int response = g_Platform->DoFileSelectorDialog(
2716 parent, &path, _("Export GPX file"), g_gpx_path, suggestedName + ".gpx",
2717 "*.gpx");
2718
2719 if (path.IsEmpty()) // relocation handled by SAF logic in Java
2720 return true;
2721
2722 wxCopyFile(fns, path); // known to be safe paths, since SAF is not involved.
2723 return true;
2724
2725#endif
2726
2727 return false;
2728}
2729
2730bool ExportGPXTracks(wxWindow *parent, std::vector<Track *> *pTracks,
2731 const wxString suggestedName) {
2732#ifndef __ANDROID__
2733 wxFileName fn = exportFileName(parent, suggestedName);
2734 if (fn.IsOk()) {
2736 pgpx->AddGPXTracksList(pTracks);
2737 pgpx->SaveFile(fn.GetFullPath());
2738 delete pgpx;
2739 return true;
2740 }
2741#else
2742 // Create the .GPX file, saving it in the OCPN Android cache directory
2743 wxString fns = androidGetCacheDir() + wxFileName::GetPathSeparator() +
2744 suggestedName + ".gpx";
2746 pgpx->AddGPXTracksList(pTracks);
2747 pgpx->SaveFile(fns);
2748 delete pgpx;
2749
2750 // Kick off the Android file chooser activity
2751 wxString path;
2752 int response = g_Platform->DoFileSelectorDialog(
2753 parent, &path, _("Export GPX file"), g_gpx_path, suggestedName + ".gpx",
2754 "*.gpx");
2755
2756 if (path.IsEmpty()) // relocation handled by SAF logic in Java
2757 return true;
2758
2759 wxCopyFile(fns, path); // known to be safe paths, since SAF is not involved.
2760 return true;
2761#endif
2762
2763 return false;
2764}
2765
2766bool ExportGPXWaypoints(wxWindow *parent, RoutePointList *pRoutePoints,
2767 const wxString suggestedName) {
2768#ifndef __ANDROID__
2769 wxFileName fn = exportFileName(parent, suggestedName);
2770 if (fn.IsOk()) {
2772 pgpx->AddGPXPointsList(pRoutePoints);
2773 pgpx->SaveFile(fn.GetFullPath());
2774 delete pgpx;
2775 return true;
2776 }
2777#else
2778 // Create the .GPX file, saving it in the OCPN Android cache directory
2779 wxString fns = androidGetCacheDir() + wxFileName::GetPathSeparator() +
2780 suggestedName + ".gpx";
2782 pgpx->AddGPXPointsList(pRoutePoints);
2783 pgpx->SaveFile(fns);
2784 delete pgpx;
2785
2786 // Kick off the Android file chooser activity
2787 wxString path;
2788 int response = g_Platform->DoFileSelectorDialog(
2789 parent, &path, _("Export GPX file"), g_gpx_path, suggestedName + ".gpx",
2790 "*.gpx");
2791
2792 if (path.IsEmpty()) // relocation handled by SAF logic in Java
2793 return true;
2794
2795 wxCopyFile(fns, path); // known to be safe paths, since SAF is not involved.
2796 return true;
2797
2798#endif
2799
2800 return false;
2801}
2802
2803void ExportGPX(wxWindow *parent, bool bviz_only, bool blayer) {
2805 wxString fns;
2806
2807#ifndef __ANDROID__
2808 wxFileName fn = exportFileName(parent, "userobjects.gpx");
2809 if (!fn.IsOk()) return;
2810 fns = fn.GetFullPath();
2811#else
2812 // Create the .GPX file, saving it in the OCPN Android cache directory
2813 fns =
2814 androidGetCacheDir() + wxFileName::GetPathSeparator() + "userobjects.gpx";
2815
2816#endif
2817 ::wxBeginBusyCursor();
2818
2819 wxGenericProgressDialog *pprog = nullptr;
2820 int count = pWayPointMan->GetWaypointList()->GetCount();
2821 int progStep = count / 32;
2822 if (count > 200) {
2823 pprog = new wxGenericProgressDialog(
2824 _("Export GPX file"), "0/0", count, NULL,
2825 wxPD_APP_MODAL | wxPD_SMOOTH | wxPD_ELAPSED_TIME | wxPD_ESTIMATED_TIME |
2826 wxPD_REMAINING_TIME);
2827 pprog->SetSize(400, wxDefaultCoord);
2828 pprog->Centre();
2829 }
2830
2831 // WPTs
2832 int ic = 1;
2833
2834 wxRoutePointListNode *node = pWayPointMan->GetWaypointList()->GetFirst();
2835 RoutePoint *pr;
2836 while (node) {
2837 if (pprog && !(ic % progStep)) {
2838 wxString msg;
2839 msg.Printf("%d/%d", ic, count);
2840 pprog->Update(ic, msg);
2841 }
2842 ic++;
2843
2844 pr = node->GetData();
2845
2846 bool b_add = true;
2847
2848 if (bviz_only && !pr->m_bIsVisible) b_add = false;
2849
2850 if (pr->m_bIsInLayer && !blayer) b_add = false;
2851 if (b_add) {
2852 if (pr->IsShared() || !WptIsInRouteList(pr)) pgpx->AddGPXWaypoint(pr);
2853 }
2854
2855 node = node->GetNext();
2856 }
2857 // RTEs and TRKs
2858 wxRouteListNode *node1 = pRouteList->GetFirst();
2859 while (node1) {
2860 Route *pRoute = node1->GetData();
2861
2862 bool b_add = true;
2863
2864 if (bviz_only && !pRoute->IsVisible()) b_add = false;
2865
2866 if (pRoute->m_bIsInLayer && !blayer) b_add = false;
2867
2868 if (b_add) pgpx->AddGPXRoute(pRoute);
2869
2870 node1 = node1->GetNext();
2871 }
2872
2873 for (Track *pTrack : g_TrackList) {
2874 bool b_add = true;
2875
2876 if (bviz_only && !pTrack->IsVisible()) b_add = false;
2877
2878 if (pTrack->m_bIsInLayer && !blayer) b_add = false;
2879
2880 if (b_add) pgpx->AddGPXTrack(pTrack);
2881 }
2882
2883 pgpx->SaveFile(fns);
2884
2885#ifdef __ANDROID__
2886 // Kick off the Android file chooser activity
2887 wxString path;
2888 int response =
2889 g_Platform->DoFileSelectorDialog(parent, &path, _("Export GPX file"),
2890 g_gpx_path, "userobjects.gpx", "*.gpx");
2891 if (path.IsEmpty()) // relocation handled by SAF logic in Java
2892 return;
2893
2894 wxCopyFile(fns, path); // known to be safe paths, since SAF is not involved.
2895 return;
2896#endif
2897 delete pgpx;
2898 ::wxEndBusyCursor();
2899 delete pprog;
2900}
2901
2902void UI_ImportGPX(wxWindow *parent, bool islayer, wxString dirpath,
2903 bool isdirectory, bool isPersistent) {
2904 int response = wxID_CANCEL;
2905 wxArrayString file_array;
2906
2907 if (!islayer || dirpath.IsSameAs("")) {
2908 // Platform DoFileSelectorDialog method does not properly handle multiple
2909 // selections So use native method if not Android, which means Android gets
2910 // single selection only.
2911#ifndef __ANDROID__
2912 wxFileDialog *popenDialog =
2913 new wxFileDialog(NULL, _("Import GPX file"), g_gpx_path, "",
2914 "GPX files (*.gpx)|*.gpx|All files (*.*)|*.*",
2915 wxFD_OPEN | wxFD_MULTIPLE);
2916
2917 if (g_bresponsive && parent)
2918 popenDialog = g_Platform->AdjustFileDialogFont(parent, popenDialog);
2919
2920 popenDialog->Centre();
2921
2922#ifdef __WXOSX__
2923 if (parent) parent->HideWithEffect(wxSHOW_EFFECT_BLEND);
2924#endif
2925
2926 response = popenDialog->ShowModal();
2927
2928#ifdef __WXOSX__
2929 if (parent) parent->ShowWithEffect(wxSHOW_EFFECT_BLEND);
2930#endif
2931
2932 if (response == wxID_OK) {
2933 popenDialog->GetPaths(file_array);
2934
2935 // Record the currently selected directory for later use
2936 if (file_array.GetCount()) {
2937 wxFileName fn(file_array[0]);
2938 g_gpx_path = fn.GetPath();
2939 }
2940 }
2941 delete popenDialog;
2942#else // Android
2943 wxString path;
2944 response = g_Platform->DoFileSelectorDialog(
2945 NULL, &path, _("Import GPX file"), g_gpx_path, "", "*.gpx");
2946
2947 wxFileName fn(path);
2948 g_gpx_path = fn.GetPath();
2949 if (path.IsEmpty()) { // Return from SAF processing, expecting callback
2950 PrepareImportAndroid(islayer, isPersistent);
2951 return;
2952 } else
2953 file_array.Add(path); // Return from safe app arena access
2954
2955#endif
2956 } else {
2957 if (isdirectory) {
2958 if (wxDir::GetAllFiles(dirpath, &file_array, "*.gpx")) response = wxID_OK;
2959 } else {
2960 file_array.Add(dirpath);
2961 response = wxID_OK;
2962 }
2963 }
2964
2965 if (response == wxID_OK) {
2966 ImportFileArray(file_array, islayer, isPersistent, dirpath);
2967 }
2968}
2969
2970void ImportFileArray(const wxArrayString &file_array, bool islayer,
2971 bool isPersistent, wxString dirpath) {
2972 Layer *l = NULL;
2973
2974 if (islayer) {
2975 l = new Layer();
2976 l->m_LayerID = ++g_LayerIdx;
2977 l->m_LayerFileName = file_array[0];
2978 if (file_array.GetCount() <= 1)
2979 wxFileName::SplitPath(file_array[0], NULL, NULL, &(l->m_LayerName), NULL,
2980 NULL);
2981 else {
2982 if (dirpath.IsSameAs(""))
2983 wxFileName::SplitPath(g_gpx_path, NULL, NULL, &(l->m_LayerName), NULL,
2984 NULL);
2985 else
2986 wxFileName::SplitPath(dirpath, NULL, NULL, &(l->m_LayerName), NULL,
2987 NULL);
2988 }
2989
2990 bool bLayerViz = g_bShowLayers;
2991 if (g_VisibleLayers.Contains(l->m_LayerName)) bLayerViz = true;
2992 if (g_InvisibleLayers.Contains(l->m_LayerName)) bLayerViz = false;
2993 l->m_bIsVisibleOnChart = bLayerViz;
2994
2995 // Default for new layers is "Names visible"
2996 l->m_bHasVisibleNames = wxCHK_CHECKED;
2997
2998 wxString laymsg;
2999 laymsg.Printf("New layer %d: %s", l->m_LayerID, l->m_LayerName.c_str());
3000 wxLogMessage(laymsg);
3001
3002 pLayerList->insert(pLayerList->begin(), l);
3003 }
3004
3005 for (unsigned int i = 0; i < file_array.GetCount(); i++) {
3006 wxString path = file_array[i];
3007
3008 if (::wxFileExists(path)) {
3010 if (pSet->load_file(path.fn_str()).status !=
3011 pugi::xml_parse_status::status_ok) {
3012 wxLogMessage("Error loading GPX file " + path);
3013 pSet->reset();
3014 delete pSet;
3015 continue;
3016 }
3017
3018 if (islayer) {
3019 l->m_NoOfItems = pSet->LoadAllGPXObjectsAsLayer(
3020 l->m_LayerID, l->m_bIsVisibleOnChart, l->m_bHasVisibleNames);
3021 l->m_LayerType = isPersistent ? _("Persistent") : _("Temporary");
3022
3023 if (isPersistent) {
3024 // If this is a persistent layer also copy the file to config file
3025 // dir /layers
3026 wxString destf, f, name, ext;
3027 f = l->m_LayerFileName;
3028 wxFileName::SplitPath(f, NULL, NULL, &name, &ext);
3029 destf = g_Platform->GetPrivateDataDir();
3030 appendOSDirSlash(&destf);
3031 destf.Append("layers");
3032 appendOSDirSlash(&destf);
3033 if (!wxDirExists(destf)) {
3034 if (!wxMkdir(destf, wxS_DIR_DEFAULT))
3035 wxLogMessage("Error creating layer directory");
3036 }
3037
3038 destf << name << "." << ext;
3039 wxString msg;
3040 if (wxCopyFile(f, destf, true))
3041 msg.Printf("File: %s.%s also added to persistent layers", name,
3042 ext);
3043 else
3044 msg.Printf("Failed adding %s.%s to persistent layers", name, ext);
3045 wxLogMessage(msg);
3046 }
3047 } else {
3048 int wpt_dups;
3049 pSet->LoadAllGPXObjects(
3050 !pSet->IsOpenCPN(),
3051 wpt_dups); // Import with full visibility of names and objects
3052#ifndef __ANDROID__
3053 if (wpt_dups > 0) {
3054 OCPNMessageBox(
3055 NULL,
3056 wxString::Format("%d " + _("duplicate waypoints detected "
3057 "during import and ignored."),
3058 wpt_dups),
3059 _("OpenCPN Info"), wxICON_INFORMATION | wxOK, 10);
3060 }
3061#endif
3062 }
3063 delete pSet;
3064 }
3065 }
3066}
3067
3068//-------------------------------------------------------------------------
3069// Static Routine Switch to Inland Ecdis Mode
3070//-------------------------------------------------------------------------
3071void SwitchInlandEcdisMode(bool Switch) {
3072 if (Switch) {
3073 wxLogMessage("Switch InlandEcdis mode On");
3074 LoadS57();
3075 // Overule some sewttings to comply with InlandEcdis
3076 // g_toolbarConfig = _T ( ".....XXXX.X...XX.XXXXXXXXXXXX" );
3077 g_iDistanceFormat = 2; // 0 = "Nautical miles"), 1 = "Statute miles", 2 =
3078 // "Kilometers", 3 = "Meters"
3079 g_iSpeedFormat = 2; // 0 = "kts"), 1 = "mph", 2 = "km/h", 3 = "m/s"
3080 if (ps52plib) ps52plib->SetDisplayCategory(STANDARD);
3081 g_bDrawAISSize = false;
3082 if (gFrame) gFrame->RequestNewToolbars(true);
3083 } else {
3084 wxLogMessage("Switch InlandEcdis mode Off");
3085 // reread the settings overruled by inlandEcdis
3086 if (pConfig) {
3087 pConfig->SetPath(_T ( "/Settings" ));
3088 pConfig->Read(_T ( "GlobalToolbarConfig" ), &g_toolbarConfig);
3089 pConfig->Read(_T ( "DistanceFormat" ), &g_iDistanceFormat);
3090 pConfig->Read(_T ( "SpeedFormat" ), &g_iSpeedFormat);
3091 pConfig->Read(_T ( "ShowDepthUnits" ), &g_bShowDepthUnits, 1);
3092 int read_int;
3093 pConfig->Read(_T ( "nDisplayCategory" ), &read_int,
3094 (enum _DisCat)STANDARD);
3095 if (ps52plib) ps52plib->SetDisplayCategory((enum _DisCat)read_int);
3096 pConfig->SetPath(_T ( "/Settings/AIS" ));
3097 pConfig->Read(_T ( "bDrawAISSize" ), &g_bDrawAISSize);
3098 pConfig->Read(_T ( "bDrawAISRealtime" ), &g_bDrawAISRealtime);
3099 }
3100 if (gFrame) gFrame->RequestNewToolbars(true);
3101 }
3102}
3103
3104//-------------------------------------------------------------------------
3105//
3106// Static GPX Support Routines
3107//
3108//-------------------------------------------------------------------------
3109// This function formats the input date/time into a valid GPX ISO 8601
3110// time string specified in the UTC time zone.
3111
3112wxString FormatGPXDateTime(wxDateTime dt) {
3113 // return dt.Format("%Y-%m-%dT%TZ", wxDateTime::GMT0);
3114 return dt.Format("%Y-%m-%dT%H:%M:%SZ");
3115}
3116
3117/**************************************************************************/
3118/* LogMessageOnce */
3119/**************************************************************************/
3120
3121bool LogMessageOnce(const wxString &msg) {
3122 // Search the array for a match
3123
3124 for (unsigned int i = 0; i < pMessageOnceArray->GetCount(); i++) {
3125 if (msg.IsSameAs(pMessageOnceArray->Item(i))) return false;
3126 }
3127
3128 // Not found, so add to the array
3129 pMessageOnceArray->Add(msg);
3130
3131 // And print it
3132 wxLogMessage(msg);
3133 return true;
3134}
3135
3136/**************************************************************************/
3137/* Some assorted utilities */
3138/**************************************************************************/
3139
3140wxDateTime toUsrDateTime(const wxDateTime ts, const int format,
3141 const double lon) {
3142 if (!ts.IsValid()) {
3143 return ts;
3144 }
3145 int effective_format = format;
3146 if (effective_format == GLOBAL_SETTINGS_INPUT) {
3147 if (::g_datetime_format == "UTC") {
3148 effective_format = UTCINPUT;
3149 } else if (::g_datetime_format == "LMT") {
3150 effective_format = LMTINPUT;
3151 } else if (::g_datetime_format == "Local Time") {
3152 effective_format = LTINPUT;
3153 } else {
3154 // Default to UTC
3155 effective_format = UTCINPUT;
3156 }
3157 }
3158 wxDateTime dt;
3159 switch (effective_format) {
3160 case LMTINPUT: // LMT@Location
3161 if (std::isnan(lon)) {
3162 dt = wxInvalidDateTime;
3163 } else {
3164 dt =
3165 ts.Add(wxTimeSpan(wxTimeSpan(0, 0, wxLongLong(lon * 3600. / 15.))));
3166 }
3167 break;
3168 case LTINPUT: // Local@PC
3169 // Convert date/time from UTC to local time.
3170 dt = ts.FromUTC();
3171 break;
3172 case UTCINPUT: // UTC
3173 // The date/time is already in UTC.
3174 dt = ts;
3175 break;
3176 }
3177 return dt;
3178}
3179
3180wxDateTime fromUsrDateTime(const wxDateTime ts, const int format,
3181 const double lon) {
3182 if (!ts.IsValid()) {
3183 return ts;
3184 }
3185 int effective_format = format;
3186 if (effective_format == GLOBAL_SETTINGS_INPUT) {
3187 if (::g_datetime_format == "UTC") {
3188 effective_format = UTCINPUT;
3189 } else if (::g_datetime_format == "LMT") {
3190 effective_format = LMTINPUT;
3191 } else if (::g_datetime_format == "Local Time") {
3192 effective_format = LTINPUT;
3193 } else {
3194 // Default to UTC
3195 effective_format = UTCINPUT;
3196 }
3197 }
3198 wxDateTime dt;
3199 switch (effective_format) {
3200 case LMTINPUT: // LMT@Location
3201 if (std::isnan(lon)) {
3202 dt = wxInvalidDateTime;
3203 } else {
3204 dt = ts.Subtract(wxTimeSpan(0, 0, wxLongLong(lon * 3600. / 15.)));
3205 }
3206 break;
3207 case LTINPUT: // Local@PC
3208 // The input date/time is in local time, so convert it to UTC.
3209 dt = ts.ToUTC();
3210 break;
3211 case UTCINPUT: // UTC
3212 dt = ts;
3213 break;
3214 }
3215 return dt;
3216}
3217
3218/**************************************************************************/
3219/* Converts the distance from the units selected by user to NMi */
3220/**************************************************************************/
3221double fromUsrDistance(double usr_distance, int unit) {
3222 double ret = NAN;
3223 if (unit == -1) unit = g_iDistanceFormat;
3224 switch (unit) {
3225 case DISTANCE_NMI: // Nautical miles
3226 ret = usr_distance;
3227 break;
3228 case DISTANCE_MI: // Statute miles
3229 ret = usr_distance / 1.15078;
3230 break;
3231 case DISTANCE_KM:
3232 ret = usr_distance / 1.852;
3233 break;
3234 case DISTANCE_M:
3235 ret = usr_distance / 1852;
3236 break;
3237 case DISTANCE_FT:
3238 ret = usr_distance / 6076.12;
3239 break;
3240 }
3241 return ret;
3242}
3243/**************************************************************************/
3244/* Converts the speed from the units selected by user to knots */
3245/**************************************************************************/
3246double fromUsrSpeed(double usr_speed, int unit) {
3247 double ret = NAN;
3248 if (unit == -1) unit = g_iSpeedFormat;
3249 switch (unit) {
3250 case SPEED_KTS: // kts
3251 ret = usr_speed;
3252 break;
3253 case SPEED_MPH: // mph
3254 ret = usr_speed / 1.15078;
3255 break;
3256 case SPEED_KMH: // km/h
3257 ret = usr_speed / 1.852;
3258 break;
3259 case SPEED_MS: // m/s
3260 ret = usr_speed / 0.514444444;
3261 break;
3262 }
3263 return ret;
3264}
3265/**************************************************************************/
3266/* Converts the wind speed from the units selected by user to knots */
3267/**************************************************************************/
3268double fromUsrWindSpeed(double usr_wspeed, int unit) {
3269 double ret = NAN;
3270 if (unit == -1) unit = g_iWindSpeedFormat;
3271 switch (unit) {
3272 case WSPEED_KTS: // kts
3273 ret = usr_wspeed;
3274 break;
3275 case WSPEED_MS: // m/s
3276 ret = usr_wspeed / 0.514444444;
3277 break;
3278 case WSPEED_MPH: // mph
3279 ret = usr_wspeed / 1.15078;
3280 break;
3281 case WSPEED_KMH: // km/h
3282 ret = usr_wspeed / 1.852;
3283 break;
3284 }
3285 return ret;
3286}
3287
3288/**************************************************************************/
3289/* Converts the temperature from the units selected by user to Celsius */
3290/**************************************************************************/
3291double fromUsrTemp(double usr_temp, int unit) {
3292 double ret = NAN;
3293 if (unit == -1) unit = g_iTempFormat;
3294 switch (unit) {
3295 case TEMPERATURE_C: // C
3296 ret = usr_temp;
3297 break;
3298 case TEMPERATURE_F: // F
3299 ret = (usr_temp - 32) * 5.0 / 9.0;
3300 break;
3301 case TEMPERATURE_K: // K
3302 ret = usr_temp - 273.15;
3303 break;
3304 }
3305 return ret;
3306}
3307
3308wxString formatAngle(double angle) {
3309 wxString out;
3310 if (g_bShowMag && g_bShowTrue) {
3311 out.Printf("%03.0f %cT (%.0f %cM)", angle, 0x00B0, toMagnetic(angle),
3312 0x00B0);
3313 } else if (g_bShowTrue) {
3314 out.Printf("%03.0f %cT", angle, 0x00B0);
3315 } else {
3316 out.Printf("%03.0f %cM", toMagnetic(angle), 0x00B0);
3317 }
3318 return out;
3319}
3320
3321/* render a rectangle at a given color and transparency */
3322void AlphaBlending(ocpnDC &dc, int x, int y, int size_x, int size_y,
3323 float radius, wxColour color, unsigned char transparency) {
3324 wxDC *pdc = dc.GetDC();
3325 if (pdc) {
3326 // Get wxImage of area of interest
3327 wxBitmap obm(size_x, size_y);
3328 wxMemoryDC mdc1;
3329 mdc1.SelectObject(obm);
3330 mdc1.Blit(0, 0, size_x, size_y, pdc, x, y);
3331 mdc1.SelectObject(wxNullBitmap);
3332 wxImage oim = obm.ConvertToImage();
3333
3334 // Create destination image
3335 wxBitmap olbm(size_x, size_y);
3336 wxMemoryDC oldc(olbm);
3337 if (!oldc.IsOk()) return;
3338
3339 oldc.SetBackground(*wxBLACK_BRUSH);
3340 oldc.SetBrush(*wxWHITE_BRUSH);
3341 oldc.Clear();
3342
3343 if (radius > 0.0) oldc.DrawRoundedRectangle(0, 0, size_x, size_y, radius);
3344
3345 wxImage dest = olbm.ConvertToImage();
3346 unsigned char *dest_data =
3347 (unsigned char *)malloc(size_x * size_y * 3 * sizeof(unsigned char));
3348 unsigned char *bg = oim.GetData();
3349 unsigned char *box = dest.GetData();
3350 unsigned char *d = dest_data;
3351
3352 // Sometimes, on Windows, the destination image is corrupt...
3353 if (NULL == box) {
3354 free(d);
3355 return;
3356 }
3357 float alpha = 1.0 - (float)transparency / 255.0;
3358 int sb = size_x * size_y;
3359 for (int i = 0; i < sb; i++) {
3360 float a = alpha;
3361 if (*box == 0 && radius > 0.0) a = 1.0;
3362 int r = ((*bg++) * a) + (1.0 - a) * color.Red();
3363 *d++ = r;
3364 box++;
3365 int g = ((*bg++) * a) + (1.0 - a) * color.Green();
3366 *d++ = g;
3367 box++;
3368 int b = ((*bg++) * a) + (1.0 - a) * color.Blue();
3369 *d++ = b;
3370 box++;
3371 }
3372
3373 dest.SetData(dest_data);
3374
3375 // Convert destination to bitmap and draw it
3376 wxBitmap dbm(dest);
3377 dc.DrawBitmap(dbm, x, y, false);
3378
3379 // on MSW, the dc Bounding box is not updated on DrawBitmap() method.
3380 // Do it explicitely here for all platforms.
3381 dc.CalcBoundingBox(x, y);
3382 dc.CalcBoundingBox(x + size_x, y + size_y);
3383 } else {
3384#ifdef ocpnUSE_GL
3385 glEnable(GL_BLEND);
3386
3387 float radMod = wxMax(radius, 2.0);
3388 wxColour c(color.Red(), color.Green(), color.Blue(), transparency);
3389 dc.SetBrush(wxBrush(c));
3390 dc.SetPen(wxPen(c, 1));
3391 dc.DrawRoundedRectangle(x, y, size_x, size_y, radMod);
3392
3393 glDisable(GL_BLEND);
3394
3395#endif
3396 }
3397}
3398
3399void DimeControl(wxWindow *ctrl) {
3400#ifdef __WXOSX__
3401 // On macOS 10.14+, we use the native colours in both light mode and dark
3402 // mode, and do not need to do anything else. Dark mode is toggled at the
3403 // application level in `SetAndApplyColorScheme`, and is also respected if it
3404 // is enabled system-wide.
3405 if (wxPlatformInfo::Get().CheckOSVersion(10, 14)) {
3406 return;
3407 }
3408#endif
3409#ifdef __WXQT__
3410 return; // this is seriously broken on wxqt
3411#endif
3412
3413 if (wxSystemSettings::GetColour(wxSystemColour::wxSYS_COLOUR_WINDOW).Red() <
3414 128) {
3415 // Dark system color themes usually do better job than we do on diming UI
3416 // controls, do not fight with them
3417 return;
3418 }
3419
3420 if (NULL == ctrl) return;
3421
3422 wxColour col, window_back_color, gridline, uitext, udkrd, ctrl_back_color,
3423 text_color;
3424 col = GetGlobalColor("DILG0"); // Dialog Background white
3425 window_back_color = GetGlobalColor("DILG1"); // Dialog Background
3426 ctrl_back_color = GetGlobalColor("DILG1"); // Control Background
3427 text_color = GetGlobalColor("DILG3"); // Text
3428 uitext = GetGlobalColor("UITX1"); // Menu Text, derived from UINFF
3429 udkrd = GetGlobalColor("UDKRD");
3430 gridline = GetGlobalColor("GREY2");
3431
3432 DimeControl(ctrl, col, window_back_color, ctrl_back_color, text_color, uitext,
3433 udkrd, gridline);
3434}
3435
3436void DimeControl(wxWindow *ctrl, wxColour col, wxColour window_back_color,
3437 wxColour ctrl_back_color, wxColour text_color, wxColour uitext,
3438 wxColour udkrd, wxColour gridline) {
3439#ifdef __WXOSX__
3440 // On macOS 10.14+, we use the native colours in both light mode and dark
3441 // mode, and do not need to do anything else. Dark mode is toggled at the
3442 // application level in `SetAndApplyColorScheme`, and is also respected if it
3443 // is enabled system-wide.
3444 if (wxPlatformInfo::Get().CheckOSVersion(10, 14)) {
3445 return;
3446 }
3447#endif
3448
3449 ColorScheme cs = global_color_scheme;
3450
3451 // Are we in dusk or night mode? (Used below in several places.)
3452 bool darkMode =
3453 (cs == GLOBAL_COLOR_SCHEME_DUSK || cs == GLOBAL_COLOR_SCHEME_NIGHT);
3454
3455 static int depth = 0; // recursion count
3456 if (depth == 0) { // only for the window root, not for every child
3457 // If the color scheme is DAY or RGB, use the default platform native colour
3458 // for backgrounds
3459 if (!darkMode) {
3460#ifdef _WIN32
3461 window_back_color = wxNullColour;
3462#else
3463 window_back_color = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW);
3464#endif
3465 col = wxSystemSettings::GetColour(wxSYS_COLOUR_LISTBOX);
3466 uitext = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT);
3467 }
3468
3469 ctrl->SetBackgroundColour(window_back_color);
3470 if (darkMode) ctrl->SetForegroundColour(text_color);
3471 }
3472
3473 wxWindowList kids = ctrl->GetChildren();
3474 for (unsigned int i = 0; i < kids.GetCount(); i++) {
3475 wxWindowListNode *node = kids.Item(i);
3476 wxWindow *win = node->GetData();
3477
3478 if (dynamic_cast<wxListBox *>(win) || dynamic_cast<wxListCtrl *>(win) ||
3479 dynamic_cast<wxTextCtrl *>(win) ||
3480 dynamic_cast<wxTimePickerCtrl *>(win)) {
3481 win->SetBackgroundColour(col);
3482 } else if (dynamic_cast<wxStaticText *>(win) ||
3483 dynamic_cast<wxCheckBox *>(win) ||
3484 dynamic_cast<wxRadioButton *>(win)) {
3485 win->SetForegroundColour(uitext);
3486 }
3487#ifndef __WXOSX__
3488 // On macOS most controls can't be styled, and trying to do so only creates
3489 // weird coloured boxes around them. Fortunately, however, many of them
3490 // inherit a colour or tint from the background of their parent.
3491
3492 else if (dynamic_cast<wxBitmapComboBox *>(win) ||
3493 dynamic_cast<wxChoice *>(win) || dynamic_cast<wxComboBox *>(win) ||
3494 dynamic_cast<wxTreeCtrl *>(win)) {
3495 win->SetBackgroundColour(col);
3496 }
3497
3498 else if (dynamic_cast<wxScrolledWindow *>(win) ||
3499 dynamic_cast<wxGenericDirCtrl *>(win) ||
3500 dynamic_cast<wxListbook *>(win) || dynamic_cast<wxButton *>(win) ||
3501 dynamic_cast<wxToggleButton *>(win)) {
3502 win->SetBackgroundColour(window_back_color);
3503 }
3504
3505 else if (dynamic_cast<wxNotebook *>(win)) {
3506 win->SetBackgroundColour(window_back_color);
3507 win->SetForegroundColour(text_color);
3508 }
3509#endif
3510
3511 else if (dynamic_cast<wxHtmlWindow *>(win)) {
3512 if (cs != GLOBAL_COLOR_SCHEME_DAY && cs != GLOBAL_COLOR_SCHEME_RGB)
3513 win->SetBackgroundColour(ctrl_back_color);
3514 else
3515 win->SetBackgroundColour(wxNullColour);
3516 }
3517
3518 else if (dynamic_cast<wxGrid *>(win)) {
3519 dynamic_cast<wxGrid *>(win)->SetDefaultCellBackgroundColour(
3520 window_back_color);
3521 dynamic_cast<wxGrid *>(win)->SetDefaultCellTextColour(uitext);
3522 dynamic_cast<wxGrid *>(win)->SetLabelBackgroundColour(col);
3523 dynamic_cast<wxGrid *>(win)->SetLabelTextColour(uitext);
3524 dynamic_cast<wxGrid *>(win)->SetGridLineColour(gridline);
3525 }
3526
3527 if (win->GetChildren().GetCount() > 0) {
3528 depth++;
3529 wxWindow *w = win;
3530 DimeControl(w, col, window_back_color, ctrl_back_color, text_color,
3531 uitext, udkrd, gridline);
3532 depth--;
3533 }
3534 }
3535}
3536
3537#define LUMIMOSITY_NIGHT (-0.8)
3538#define LUMIMOSITY_DUSK (-0.5)
3539
3540wxColor GetDimedColor(const wxColor &c) {
3541 switch (global_color_scheme) {
3542 case ColorScheme::GLOBAL_COLOR_SCHEME_NIGHT:
3543 return (wxColor(
3544 wxMax(0, wxMin(c.Red() + c.Red() * LUMIMOSITY_NIGHT, 255)),
3545 wxMax(0, wxMin(c.Green() + c.Green() * LUMIMOSITY_NIGHT, 255)),
3546 wxMax(0, wxMin(c.Blue() + c.Blue() * LUMIMOSITY_NIGHT, 255))));
3547 case ColorScheme::GLOBAL_COLOR_SCHEME_DUSK:
3548 return (
3549 wxColor(wxMax(0, wxMin(c.Red() + c.Red() * LUMIMOSITY_DUSK, 255)),
3550 wxMax(0, wxMin(c.Green() + c.Green() * LUMIMOSITY_DUSK, 255)),
3551 wxMax(0, wxMin(c.Blue() + c.Blue() * LUMIMOSITY_DUSK, 255))));
3552 default:
3553 return c;
3554 }
3555}
Class AisDecoder and helpers.
Global state for AIS decoder.
Chart canvas configuration state
General chart base definitions.
Charts database management
ChartGroupArray * g_pGroupArray
Global instance.
Definition chartdbs.cpp:54
Generic Chart canvas base.
wxString & GetPrivateDataDir()
Return dir path for opencpn.log, etc., respecting -c cli option.
Represents an individual component within a ChartGroup.
Definition chartdbs.h:447
Represents a user-defined collection of logically related charts.
Definition chartdbs.h:467
wxString GetFullConfigDesc(int i) const
Gets description of font at index i.
Definition FontMgr.cpp:367
bool AddAuxKey(wxString key)
Adds new plugin-defined font configuration key.
Definition FontMgr.cpp:660
void LoadFontNative(wxString *pConfigString, wxString *pNativeDesc)
Loads font settings from a string descriptor.
Definition FontMgr.cpp:394
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:329
wxArrayString & GetAuxKeyArray()
Gets array of plugin-defined font configuration keys.
Definition FontMgr.h:183
Represents a layer of chart objects in OpenCPN.
Definition Layer.h:40
Process incoming AIS messages.
Definition ais_decoder.h:73
static int config_to_ui(double value)
Convert configuration 1.02..3.0 value to slider scale 1..100.
Definition navutil.h:171
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:166
Main application frame.
Definition ocpn_frame.h:138
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:114
ViewPort - Core geographic projection and coordinate transformation engine.
Definition viewport.h:84
double view_scale_ppm
Requested view scale in physical pixels per meter (ppm), before applying projections.
Definition viewport.h:232
double rotation
Rotation angle of the viewport in radians.
Definition viewport.h:242
double clon
Center longitude of the viewport in degrees.
Definition viewport.h:227
double clat
Center latitude of the viewport in degrees.
Definition viewport.h:225
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:60
Class cm93chart and helpers – CM93 chart state.
Global variables reflecting command line options and arguments.
Config file user configuration interface.
wxString g_datetime_format
Date/time format to use when formatting date/time strings.
bool g_always_send_rmb_rmc
Always send RMB and RMC n0183 messages even if there is no active route.
bool g_bsmoothpanzoom
Controls how the chart panning and zooming smoothing is done during user interactions.
wxString g_winPluginDir
Base plugin directory on Windows.
bool g_bRollover
enable/disable mouse rollover GUI effects
int g_COGAvgSec
COG average period for Course Up Mode (sec)
std::vector< size_t > g_config_display_size_mm
g_config_display_size_mm: Size of pysical screen in millimeters.
bool g_bDisplayGrid
Should lat/lon grid be displayed ?
double g_display_size_mm
Physical display width (mm)
Global variables stored in configuration file.
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.
double vLat
Virtual lat from chcanv popup.
Definition gui_vars.cpp:55
double vLon
Virtual lon from chcanv popup.
Definition gui_vars.cpp:56
Multiplexer class and helpers.
Class NavObj_dB.
Global variables Listen()/Notify() wrapper.
PlugIn Object Definition/API.
Tools to send data to plugins.