diff options
Diffstat (limited to 'subsurface-core')
41 files changed, 421 insertions, 137 deletions
diff --git a/subsurface-core/cochran.c b/subsurface-core/cochran.c index 40149d577..b42ed8233 100644 --- a/subsurface-core/cochran.c +++ b/subsurface-core/cochran.c @@ -1,3 +1,6 @@ +// Clang has a bug on zero-initialization of C structs. +#pragma clang diagnostic ignored "-Wmissing-field-initializers" + #include <stdlib.h> #include <stdio.h> #include <string.h> @@ -431,7 +434,7 @@ static void cochran_dive_event(struct divecomputer *dc, const unsigned char *s, * Parse sample data, extract events and build a dive */ static void cochran_parse_samples(struct dive *dive, const unsigned char *log, - const unsigned char *samples, int size, + const unsigned char *samples, unsigned int size, unsigned int *duration, double *max_depth, double *avg_depth, double *min_temp) { diff --git a/subsurface-core/compressibility.r b/subsurface-core/compressibility.r new file mode 100644 index 000000000..66310f3aa --- /dev/null +++ b/subsurface-core/compressibility.r @@ -0,0 +1,115 @@ +# Compressibility data gathered by Lubomir I Ivanov: +# +# "Data obtained by finding two books online: +# +# [1] +# PERRY’S CHEMICAL ENGINEERS’ HANDBOOK SEVENTH EDITION +# pretty serious book, from which the wiki AIR values come from! +# +# http://www.unhas.ac.id/rhiza/arsip/kuliah/Sistem-dan-Tekn-Kendali-Proses/PDF_Collections/REFERENSI/Perrys_Chemical_Engineering_Handbook.pdf +# page 2-165 +# +# [*](Computed from pressure-volume-temperature tables in Vasserman monographs) +# ^ i have no idea idea what this means, but the values might not be exactly +# experimental?! +# +# the only thing this book is missing is helium, thus [2]! +# +# [2] +# VOLUMETRIC BEHAVIOR OF HELIUM-ARGON MIXTURES AT HIGH PRESSURE AND MODERATE TEMPERATURE. +# +# https://shareok.org/bitstream/handle/11244/2062/6614196.PDF?sequence=1 +# page 108 +# +# +# the book has some tables with pressure values in atmosphere units. i'm +# converting them bars. one of the relevant tables is for 323K and one for 273K +# (both almost equal distance from 300K). +# +# this again is a linear mix operation between isotherms, which is probably not +# the most accurate solution but it works. +# +# all data sets contain Z values at 300k, while the pressures are in bars in +# the 1 to 500 range +# +# + +x = c(1, 5, 10, 20, 40, 60, 80, 100, 200, 300, 400, 500) +o2 = c(0.9994, 0.9968, 0.9941, 0.9884, 0.9771, 0.9676, 0.9597, 0.9542, 0.9560, 0.9972, 1.0689, 1.1572) +n2 = c(0.9998, 0.9990, 0.9983, 0.9971, 0.9964, 0.9973, 1.0000, 1.0052, 1.0559, 1.1422, 1.2480, 1.3629) +he = c(1.0005, 1.0024, 1.0048, 1.0096, 1.0191, 1.0286, 1.0381, 1.0476, 1.0943, 1.1402, 1.1854, 1.2297) + +options(digits=15) + +# +# Get the O2 virial coefficients +# +plot(x,o2) +o2fit = nls(o2 ~ 1.0 + p1*x + p2 *x^2 + p3*x^3, start=list(p1=0,p2=0,p3=0)) +summary(o2fit) + +new = data.frame(x = seq(min(x),max(x),len=200)) +lines(new$x,predict(o2fit,newdata=new)) + +# +# Get the N2 virial coefficients +# +plot(x,n2) +n2fit = nls(n2 ~ 1.0 + p1*x + p2 *x^2 + p3*x^3, start=list(p1=0,p2=0,p3=0)) +summary(n2fit) + +new = data.frame(x = seq(min(x),max(x),len=200)) +lines(new$x,predict(n2fit,newdata=new)) + +# +# Get the He virial coefficients +# +# NOTE! This will not confirm convergence, thus the warnOnly. +# That may be a sign that the data is possibly artificial. +# +plot(x,he) +hefit = nls(he ~ 1.0 + p1*x + p2 *x^2 + p3*x^3, + start=list(p1=0,p2=0,p3=0), + control=nls.control(warnOnly=TRUE)) +summary(hefit) + +new = data.frame(x = seq(min(x),max(x),len=200)) +lines(new$x,predict(hefit,newdata=new)) + +# +# Raw data from VOLUMETRIC BEHAVIOR OF HELIUM-ARGON MIXTURES [..] +# T=323.15K (50 C) +p323atm = c(674.837, 393.223, 237.310, 146.294, 91.4027, 57.5799, 36.4620, 23.1654, 14.7478, 9.4017, 5.9987, 3.8300, + 540.204, 319.943, 195.008, 120.951, 75.8599, 47.9005, 30.3791, 19.3193, 12.3080, 7.8495, 5.0100, 3.1992) + +Hez323 = c(1.28067, 1.16782, 1.10289, 1.06407, 1.04028, 1.02548, 1.01617, 1.01029, 1.00656, 1.00418, 1.00267, 1.00171, + 1.22738, 1.13754, 1.08493, 1.05312, 1.03349, 1.02122, 1.01349, 1.00859, 1.00548, 1.00349, 1.00223, 1.00143) + + +# T=273.15 (0 C) +p273atm = c(683.599, 391.213, 233.607, 143.091, 89.0521, 55.9640, 35.3851, 22.4593, 14.2908, 9.1072, 5.8095, 3.7083, + 534.047, 312.144, 188.741, 116.508, 72.8529, 45.9194, 29.0883, 18.4851, 11.7702, 7.5040, 4.7881, 3.0570) + +Hez273 = c(1.33969, 1.19985, 1.12121, 1.07494, 1.04689, 1.02957, 1.01874, 1.01191, 1.00758, 1.00484, 1.00309, 1.00197, + 1.26914, 1.16070, 1.09837, 1.06118, 1.03843, 1.02429, 1.01541, 1.00980, 1.00625, 1.00398, 1.00254, 1.00162) + +p323 = p323atm * 1.01325 +p273 = p273atm * 1.01325 + +x2=append(p323,p273) +he2=append(Hez323,Hez273) + +plot(x2,he2) + +hefit2 = nls(he2 ~ 1.0 + p1*x2 + p2*x2^2 + p3*x2^3, + start=list(p1=0,p2=0,p3=0)) +summary(hefit2) + +he3 = function(bar) +{ + 1.0 +0.00047961098687979363 * bar -0.00000004077670019935 * bar^2 +0.00000000000077707035 * bar^3 +} + +new = data.frame(x2 = seq(min(x2),max(x2),len=200)) +lines(new$x2,predict(hefit2,newdata=new)) +curve(he3, min(x2),max(x2),add=TRUE) diff --git a/subsurface-core/datatrak.c b/subsurface-core/datatrak.c index fb05c1701..204ebd9b3 100644 --- a/subsurface-core/datatrak.c +++ b/subsurface-core/datatrak.c @@ -1,3 +1,6 @@ +// Clang has a bug on zero-initialization of C structs. +#pragma clang diagnostic ignored "-Wmissing-field-initializers" + #include <stdlib.h> #include <stdio.h> #include <string.h> diff --git a/subsurface-core/deco.c b/subsurface-core/deco.c index dff88d338..3cd8c4a16 100644 --- a/subsurface-core/deco.c +++ b/subsurface-core/deco.c @@ -34,13 +34,13 @@ extern pressure_t first_ceiling_pressure; //! Option structure for Buehlmann decompression. struct buehlmann_config { - double satmult; //! safety at inert gas accumulation as percentage of effect (more than 100). - double desatmult; //! safety at inert gas depletion as percentage of effect (less than 100). - unsigned int last_deco_stop_in_mtr; //! depth of last_deco_stop. - double gf_high; //! gradient factor high (at surface). - double gf_low; //! gradient factor low (at bottom/start of deco calculation). - double gf_low_position_min; //! gf_low_position below surface_min_shallow. - bool gf_low_at_maxdepth; //! if true, gf_low applies at max depth instead of at deepest ceiling. + double satmult; //! safety at inert gas accumulation as percentage of effect (more than 100). + double desatmult; //! safety at inert gas depletion as percentage of effect (less than 100). + int last_deco_stop_in_mtr; //! depth of last_deco_stop. + double gf_high; //! gradient factor high (at surface). + double gf_low; //! gradient factor low (at bottom/start of deco calculation). + double gf_low_position_min; //! gf_low_position below surface_min_shallow. + bool gf_low_at_maxdepth; //! if true, gf_low applies at max depth instead of at deepest ceiling. }; struct buehlmann_config buehlmann_config = { @@ -572,9 +572,9 @@ void restore_deco_state(char *data) memcpy(&ci_pointing_to_guiding_tissue, data, sizeof(int)); } -unsigned int deco_allowed_depth(double tissues_tolerance, double surface_pressure, struct dive *dive, bool smooth) +int deco_allowed_depth(double tissues_tolerance, double surface_pressure, struct dive *dive, bool smooth) { - unsigned int depth; + int depth; double pressure_delta; /* Avoid negative depths */ diff --git a/subsurface-core/deco.h b/subsurface-core/deco.h index 08ff93422..fd3b94a9f 100644 --- a/subsurface-core/deco.h +++ b/subsurface-core/deco.h @@ -11,6 +11,7 @@ extern double tissue_inertgas_saturation[16]; extern double buehlmann_inertgas_a[16], buehlmann_inertgas_b[16]; extern double gf_low_pressure_this_dive; +extern int deco_allowed_depth(double tissues_tolerance, double surface_pressure, struct dive *dive, bool smooth); #ifdef __cplusplus } diff --git a/subsurface-core/dive.c b/subsurface-core/dive.c index 083767582..8fc9e993b 100644 --- a/subsurface-core/dive.c +++ b/subsurface-core/dive.c @@ -58,7 +58,7 @@ int event_gasmix_redundant(struct event *ev) he == ev->gas.mix.he.permille; } -struct event *add_event(struct divecomputer *dc, int time, int type, int flags, int value, const char *name) +struct event *add_event(struct divecomputer *dc, unsigned int time, int type, int flags, int value, const char *name) { int gas_index = -1; struct event *ev, **p; @@ -738,7 +738,8 @@ void per_cylinder_mean_depth(struct dive *dive, struct divecomputer *dc, int *me { int i; int depthtime[MAX_CYLINDERS] = { 0, }; - int lasttime = 0, lastdepth = 0; + uint32_t lasttime = 0; + int lastdepth = 0; int idx = 0; for (i = 0; i < MAX_CYLINDERS; i++) @@ -765,7 +766,7 @@ void per_cylinder_mean_depth(struct dive *dive, struct divecomputer *dc, int *me dc = fake_dc(dc, false); for (i = 0; i < dc->samples; i++) { struct sample *sample = dc->sample + i; - int time = sample->time.seconds; + uint32_t time = sample->time.seconds; int depth = sample->depth.mm; /* Make sure to move the event past 'lasttime' */ @@ -2619,7 +2620,8 @@ static struct divetag *taglist_add_divetag(struct tag_entry **tag_list, struct d struct divetag *taglist_add_tag(struct tag_entry **tag_list, const char *tag) { - int i = 0, is_default_tag = 0; + size_t i = 0; + int is_default_tag = 0; struct divetag *ret_tag, *new_tag; const char *translation; new_tag = malloc(sizeof(struct divetag)); @@ -2675,7 +2677,7 @@ static void taglist_merge(struct tag_entry **dst, struct tag_entry *src1, struct void taglist_init_global() { - int i; + size_t i; for (i = 0; i < sizeof(default_tags) / sizeof(char *); i++) taglist_add_tag(&g_tag_list, default_tags[i]); @@ -2846,7 +2848,7 @@ struct dive *merge_dives(struct dive *a, struct dive *b, int offset, bool prefer MERGE_TXT(res, a, b, divemaster); MERGE_MAX(res, a, b, rating); MERGE_TXT(res, a, b, suit); - MERGE_MIN(res, a, b, number); + MERGE_MAX(res, a, b, number); MERGE_NONZERO(res, a, b, cns); MERGE_NONZERO(res, a, b, visibility); MERGE_NONZERO(res, a, b, picture_list); @@ -2920,7 +2922,8 @@ static void force_fixup_dive(struct dive *d) */ static int split_dive_at(struct dive *dive, int a, int b) { - int i, t, nr; + int i, nr; + uint32_t t; struct dive *d1, *d2; struct divecomputer *dc1, *dc2; struct event *event, **evp; @@ -3371,7 +3374,7 @@ void dive_set_geodata_from_picture(struct dive *dive, struct picture *picture) } } -static void picture_free(struct picture *picture) +void picture_free(struct picture *picture) { if (!picture) return; @@ -3380,6 +3383,18 @@ static void picture_free(struct picture *picture) free(picture); } +// When handling pictures in different threads, we need to copy them so we don't +// run into problems when the main thread frees the picture. + +struct picture *clone_picture(struct picture *src) +{ + struct picture *dst; + + dst = alloc_picture(); + copy_pl(src, dst); + return dst; +} + void dive_remove_picture(char *filename) { struct picture **picture = ¤t_dive->picture_list; @@ -3415,7 +3430,7 @@ void make_first_dc() } /* always acts on the current dive */ -int count_divecomputers(void) +unsigned int count_divecomputers(void) { int ret = 1; struct divecomputer *dc = current_dive->dc.next; @@ -3455,7 +3470,7 @@ void delete_current_divecomputer(void) /* helper function to make it easier to work with our structures * we don't interpolate here, just use the value from the last sample up to that time */ -int get_depth_at_time(struct divecomputer *dc, int time) +int get_depth_at_time(struct divecomputer *dc, unsigned int time) { int depth = 0; if (dc && dc->sample) diff --git a/subsurface-core/dive.h b/subsurface-core/dive.h index f8970b237..204d34819 100644 --- a/subsurface-core/dive.h +++ b/subsurface-core/dive.h @@ -376,6 +376,7 @@ struct picture { for (struct picture *picture = (_divestruct).picture_list; picture; picture = picture->next) extern struct picture *alloc_picture(); +extern struct picture *clone_picture(struct picture *src); extern bool dive_check_picture_time(struct dive *d, int shift_time, timestamp_t timestamp); extern void dive_create_picture(struct dive *d, char *filename, int shift_time, bool match_all); extern void dive_add_picture(struct dive *d, struct picture *newpic); @@ -385,9 +386,10 @@ extern bool picture_check_valid(char *filename, int shift_time); extern void picture_load_exif_data(struct picture *p); extern timestamp_t picture_get_timestamp(char *filename); extern void dive_set_geodata_from_picture(struct dive *d, struct picture *pic); +extern void picture_free(struct picture *picture); extern int explicit_first_cylinder(struct dive *dive, struct divecomputer *dc); -extern int get_depth_at_time(struct divecomputer *dc, int time); +extern int get_depth_at_time(struct divecomputer *dc, unsigned int time); static inline int get_surface_pressure_in_mbar(const struct dive *dive, bool non_null) { @@ -493,7 +495,7 @@ extern const struct units SI_units, IMPERIAL_units; extern struct units xml_parsing_units; extern struct units *get_units(void); -extern int run_survey, verbose, quit; +extern int run_survey, verbose, quit, force_root; struct dive_table { int nr, allocated, preexisting; @@ -567,7 +569,7 @@ static inline struct divecomputer *get_dive_dc(struct dive *dive, int nr) extern timestamp_t dive_endtime(const struct dive *dive); extern void make_first_dc(void); -extern int count_divecomputers(void); +extern unsigned int count_divecomputers(void); extern void delete_current_divecomputer(void); /* @@ -695,6 +697,7 @@ extern struct zip *subsurface_zip_open_readonly(const char *path, int flags, int extern int subsurface_zip_close(struct zip *zip); extern void subsurface_console_init(bool dedicated); extern void subsurface_console_exit(void); +extern bool subsurface_user_is_root(void); extern void shift_times(const timestamp_t amount); extern timestamp_t get_times(); @@ -728,7 +731,6 @@ extern unsigned int dc_watertemp(struct divecomputer *dc); extern int split_dive(struct dive *); extern struct dive *merge_dives(struct dive *a, struct dive *b, int offset, bool prefer_downloaded); extern struct dive *try_to_merge(struct dive *a, struct dive *b, bool prefer_downloaded); -extern void renumber_dives(int start_nr, bool selected_only); extern struct event *clone_event(const struct event *src_ev); extern void copy_events(struct divecomputer *s, struct divecomputer *d); extern void free_events(struct event *ev); @@ -737,7 +739,7 @@ extern void copy_samples(struct divecomputer *s, struct divecomputer *d); extern bool is_cylinder_used(struct dive *dive, int idx); extern void fill_default_cylinder(cylinder_t *cyl); extern void add_gas_switch_event(struct dive *dive, struct divecomputer *dc, int time, int idx); -extern struct event *add_event(struct divecomputer *dc, int time, int type, int flags, int value, const char *name); +extern struct event *add_event(struct divecomputer *dc, unsigned int time, int type, int flags, int value, const char *name); extern void remove_event(struct event *event); extern void update_event_name(struct dive *d, struct event* event, char *name); extern void add_extra_data(struct divecomputer *dc, const char *key, const char *value); @@ -792,7 +794,6 @@ extern void subsurface_command_line_exit(int *, char ***); extern void add_segment(double pressure, const struct gasmix *gasmix, int period_in_seconds, int setpoint, const struct dive *dive, int sac); extern void clear_deco(double surface_pressure); extern void dump_tissues(void); -extern unsigned int deco_allowed_depth(double tissues_tolerance, double surface_pressure, struct dive *dive, bool smooth); extern void set_gf(short gflow, short gfhigh, bool gf_low_at_maxdepth); extern void cache_deco_state(char **datap); extern void restore_deco_state(char *data); @@ -804,7 +805,7 @@ extern double tissue_tolerance_calc(const struct dive *dive, double pressure); /* this should be converted to use our types */ struct divedatapoint { int time; - unsigned int depth; + int depth; struct gasmix gasmix; int setpoint; bool entered; diff --git a/subsurface-core/divelist.c b/subsurface-core/divelist.c index 1e9065d8b..543d9e17b 100644 --- a/subsurface-core/divelist.c +++ b/subsurface-core/divelist.c @@ -44,6 +44,7 @@ #include "display.h" #include "planner.h" #include "qthelperfromc.h" +#include "git-access.h" static short dive_list_changed = false; @@ -205,7 +206,8 @@ int const cns_table[][3] = { * so we calculated it "by hand" */ static int calculate_cns(struct dive *dive) { - int i, j, divenr; + int i, divenr; + size_t j; double cns = 0.0; struct divecomputer *dc = &dive->dc; struct dive *prev_dive; @@ -833,10 +835,14 @@ bool consecutive_selected() return consecutive; } +/* + * Merge two dives. 'a' is always before 'b' in the dive list + * (and thus in time). + */ struct dive *merge_two_dives(struct dive *a, struct dive *b) { struct dive *res; - int i, j, factor; + int i, j, nr, nrdiff; int id; if (!a || !b) @@ -852,7 +858,30 @@ struct dive *merge_two_dives(struct dive *a, struct dive *b) if (!res) return NULL; - factor = (a->number == 0 || b->number == 0) ? 0 : abs(b->number - a->number); + /* + * If 'a' and 'b' were numbered, and in proper order, + * then the resulting dive will get the first number, + * and the subsequent dives will be renumbered by the + * difference. + * + * So if you had a dive list 1 3 6 7 8, and you + * merge 1 and 3, the resulting numbered list will + * be 1 4 5 6, because we assume that there were + * some missing dives (originally dives 4 and 5), + * that now will still be missing (dives 2 and 3 + * in the renumbered world). + * + * Obviously the normal case is that everything is + * consecutive, and the difference will be 1, so the + * above example is not supposed to be normal. + */ + nrdiff = 0; + nr = a->number; + if (a->number && b->number > a->number) { + res->number = nr; + nrdiff = b->number - nr; + } + add_single_dive(i, res); delete_single_dive(i + 1); delete_single_dive(j); @@ -863,9 +892,25 @@ struct dive *merge_two_dives(struct dive *a, struct dive *b) // renumber dives from merged one in advance by difference between // merged dives numbers. Do not renumber if actual number is zero. - for (; j < dive_table.nr; j++) - if (!dive_table.dives[j]->number == 0) - dive_table.dives[j]->number -= factor; + for (; j < dive_table.nr; j++) { + struct dive *dive = dive_table.dives[j]; + int newnr; + + if (!dive->number) + continue; + newnr = dive->number - nrdiff; + + /* + * Don't renumber stuff that isn't in order! + * + * So if the new dive number isn't larger than the + * previous dive number, just stop here. + */ + if (newnr <= nr) + break; + dive->number = newnr; + nr = newnr; + } mark_divelist_changed(true); return res; @@ -1158,4 +1203,5 @@ void clear_dive_file_data() existing_filename = NULL; reset_min_datafile_version(); + saved_git_id = ""; } diff --git a/subsurface-core/equipment.c b/subsurface-core/equipment.c index 47c439735..9f3e49039 100644 --- a/subsurface-core/equipment.c +++ b/subsurface-core/equipment.c @@ -1,3 +1,6 @@ +// Clang has a bug on zero-initialization of C structs. +#pragma clang diagnostic ignored "-Wmissing-field-initializers" + /* equipment.c */ #include <stdio.h> #include <string.h> diff --git a/subsurface-core/file.c b/subsurface-core/file.c index 8286ce9f5..1337da3a2 100644 --- a/subsurface-core/file.c +++ b/subsurface-core/file.c @@ -57,7 +57,7 @@ int readfile(const char *filename, struct memblock *mem) if (ret < 0) goto free; buf[ret] = 0; - if (ret == mem->size) + if (ret == (int)mem->size) // converting to int loses a bit but size will never be that big goto out; errno = EIO; ret = -1; @@ -453,8 +453,7 @@ int check_git_sha(const char *filename) if (git && git != dummy_git_repository) { const char *sha = get_sha(git, branch); if (!same_string(sha, "") && - same_string(sha, saved_git_id) && - !unsaved_changes()) { + same_string(sha, saved_git_id)) { fprintf(stderr, "already have loaded SHA %s - don't load again\n", sha); return 0; } @@ -466,6 +465,7 @@ int parse_file(const char *filename) { struct git_repository *git; const char *branch = NULL; + char *current_sha = copy_string(saved_git_id); struct memblock mem; char *fmt; int ret; @@ -473,22 +473,25 @@ int parse_file(const char *filename) git = is_git_repository(filename, &branch, NULL, false); if (prefs.cloud_git_url && strstr(filename, prefs.cloud_git_url) - && git == dummy_git_repository) + && git == dummy_git_repository) { /* opening the cloud storage repository failed for some reason * give up here and don't send errors about git repositories */ + free(current_sha); return 0; - + } /* if this is a git repository, do we already have this exact state loaded ? * get the SHA and compare with what we currently have */ if (git && git != dummy_git_repository) { const char *sha = get_sha(git, branch); if (!same_string(sha, "") && - same_string(sha, saved_git_id) && + same_string(sha, current_sha) && !unsaved_changes()) { fprintf(stderr, "already have loaded SHA %s - don't load again\n", sha); + free(current_sha); return 0; } } + free(current_sha); if (git) return git_load_dives(git, branch); diff --git a/subsurface-core/gas-model.c b/subsurface-core/gas-model.c index 81765e003..ad1160f3b 100644 --- a/subsurface-core/gas-model.c +++ b/subsurface-core/gas-model.c @@ -26,36 +26,39 @@ double gas_compressibility_factor(struct gasmix *gas, double bar) { static const double o2_coefficients[3] = { - -0.00071809207370164567, - +0.00000281852572807643, - -0.00000000150290620491 + -7.18092073703e-04, + +2.81852572808e-06, + -1.50290620492e-09 }; static const double n2_coefficients[3] = { - -0.00021926035329221337, - +0.00000292844845531647, - -0.00000000207613482075 + -2.19260353292e-04, + +2.92844845532e-06, + -2.07613482075e-09 }; static const double he_coefficients[3] = { - +0.00047961098687979363, - -0.00000004077670019935, - +0.00000000000077707035 + +4.87320026468e-04, + -8.83632921053e-08, + +5.33304543646e-11 }; - double o2, he; + int o2, he; double x1, x2, x3; double Z; - o2 = get_o2(gas) / 1000.0; - he = get_he(gas) / 1000.0; + o2 = get_o2(gas); + he = get_he(gas); x1 = bar; x2 = x1*x1; x3 = x2*x1; Z = virial_m1(o2_coefficients, x1, x2, x3) * o2 + virial_m1(he_coefficients, x1, x2, x3) * he + - virial_m1(n2_coefficients, x1, x2, x3) * (1.0 - o2 - he); + virial_m1(n2_coefficients, x1, x2, x3) * (1000 - o2 - he); /* * We add the 1.0 at the very end - the linear mixing of the * three 1.0 terms is still 1.0 regardless of the gas mix. + * + * The * 0.001 is because we did the linear mixing using the + * raw permille gas values. */ - return Z + 1.0; + return Z * 0.001 + 1.0; } diff --git a/subsurface-core/gaspressures.c b/subsurface-core/gaspressures.c index 3cbb36773..5d3fc9791 100644 --- a/subsurface-core/gaspressures.c +++ b/subsurface-core/gaspressures.c @@ -200,7 +200,7 @@ static void fill_missing_tank_pressures(struct dive *dive, struct plot_info *pi, { int cyl, i; struct plot_data *entry; - pr_interpolate_t interpolate = { 0 }; + pr_interpolate_t interpolate = { 0, 0, 0, 0 }; pr_track_t *last_segment = NULL; int cur_pr[MAX_CYLINDERS]; // cur_pr[MAX_CYLINDERS] is the CCR diluent cylinder @@ -347,6 +347,7 @@ static void debug_print_pressures(struct plot_info *pi) */ void populate_pressure_information(struct dive *dive, struct divecomputer *dc, struct plot_info *pi, int o2_flag) { + (void) dc; int i, cylinderid, cylinderindex = -1; pr_track_t *track_pr[MAX_CYLINDERS] = { NULL, }; pr_track_t *current = NULL; diff --git a/subsurface-core/git-access.c b/subsurface-core/git-access.c index e986607ab..c902bf60b 100644 --- a/subsurface-core/git-access.c +++ b/subsurface-core/git-access.c @@ -1,3 +1,6 @@ +// Clang has a bug on zero-initialization of C structs. +#pragma clang diagnostic ignored "-Wmissing-field-initializers" + #include <stdio.h> #include <ctype.h> #include <string.h> @@ -664,7 +667,7 @@ static git_repository *create_local_repo(const char *localdir, const char *remot * to our cloud storage and the branch doesn't exist. * So we need to create the branch and push it to the remote */ cloned_repo = create_and_push_remote(localdir, remote, branch); -#if !defined(DEBUG) +#if !defined(DEBUG) && !defined(SUBSURFACE_MOBILE) } else if (is_subsurface_cloud) { report_error(translate("gettextFromC", "Error connecting to Subsurface cloud storage")); #endif diff --git a/subsurface-core/gpslocation.cpp b/subsurface-core/gpslocation.cpp index 9f1961cbf..075b1c046 100644 --- a/subsurface-core/gpslocation.cpp +++ b/subsurface-core/gpslocation.cpp @@ -33,7 +33,7 @@ GpsLocation::GpsLocation(void (*showMsgCB)(const char *), QObject *parent) : QOb QString("org.subsurfacedivelog"), QString("subsurfacelocation"), this); #ifdef SUBSURFACE_MOBILE if (hasLocationsSource()) - status("Found GPS"); + status(QString("Found GPS with positioning methods %1").arg(QString::number(m_GpsSource->supportedPositioningMethods(), 16))); #endif userAgent = getUserAgent(); loadFromStorage(); @@ -59,8 +59,7 @@ QGeoPositionInfoSource *GpsLocation::getGpsSource() #ifndef SUBSURFACE_MOBILE if (verbose) #endif - status("created GPS source"); - QString msg = QString("have position source %1").arg(m_GpsSource->sourceName()); + status(QString("Created position source %1").arg(m_GpsSource->sourceName())); connect(m_GpsSource, SIGNAL(positionUpdated(QGeoPositionInfo)), this, SLOT(newPosition(QGeoPositionInfo))); connect(m_GpsSource, SIGNAL(updateTimeout()), this, SLOT(updateTimeout())); m_GpsSource->setUpdateInterval(5 * 60 * 1000); // 5 minutes so the device doesn't drain the battery @@ -89,7 +88,7 @@ void GpsLocation::serviceEnable(bool toggle) } if (toggle) { gpsSource->startUpdates(); - status("Starting Subsurface GPS service"); + status(QString("Starting Subsurface GPS service with update interval %1").arg(gpsSource->updateInterval())); } else { gpsSource->stopUpdates(); status("Stopping Subsurface GPS service"); @@ -117,10 +116,8 @@ QString GpsLocation::currentPosition() void GpsLocation::newPosition(QGeoPositionInfo pos) { - int64_t lastTime; + int64_t lastTime = 0; QGeoCoordinate lastCoord; - QString msg("received new position %1"); - status(qPrintable(msg.arg(pos.coordinate().toString()))); int nr = m_trackers.count(); if (nr) { gpsTracker gt = m_trackers.last(); @@ -131,9 +128,11 @@ void GpsLocation::newPosition(QGeoPositionInfo pos) // if we are waiting for a position update or // if we have no record stored or if at least the configured minimum // time has passed or we moved at least the configured minimum distance - if (!nr || waitingForPosition || - (int64_t)pos.timestamp().toTime_t() > lastTime + prefs.time_threshold || + int64_t delta = (int64_t)pos.timestamp().toTime_t() + gettimezoneoffset() - lastTime; + if (!nr || waitingForPosition || delta > prefs.time_threshold || lastCoord.distanceTo(pos.coordinate()) > prefs.distance_threshold) { + QString msg("received new position %1 after delta %2 threshold %3"); + status(qPrintable(msg.arg(pos.coordinate().toString()).arg(delta).arg(prefs.time_threshold))); waitingForPosition = false; gpsTracker gt; gt.when = pos.timestamp().toTime_t(); diff --git a/subsurface-core/imagedownloader.cpp b/subsurface-core/imagedownloader.cpp index 9451f8a1b..daa49eadf 100644 --- a/subsurface-core/imagedownloader.cpp +++ b/subsurface-core/imagedownloader.cpp @@ -17,8 +17,14 @@ ImageDownloader::ImageDownloader(struct picture *pic) picture = pic; } +ImageDownloader::~ImageDownloader() +{ + picture_free(picture); +} + void ImageDownloader::load(bool fromHash){ QUrl url; + loadFromHash = fromHash; if(fromHash) url = cloudImageURL(picture->hash); else @@ -40,8 +46,11 @@ void ImageDownloader::saveImage(QNetworkReply *reply) QByteArray imageData = reply->readAll(); QImage image = QImage(); image.loadFromData(imageData); - if (image.isNull()) + if (image.isNull()) { + if (loadFromHash) + load(false); return; + } QCryptographicHash hash(QCryptographicHash::Sha1); hash.addData(imageData); QString path = QStandardPaths::standardLocations(QStandardPaths::CacheLocation).first(); @@ -59,6 +68,11 @@ void ImageDownloader::saveImage(QNetworkReply *reply) } reply->manager()->deleteLater(); reply->deleteLater(); + // This should be called to make the picture actually show. + // Problem is DivePictureModel is not in subsurface-core. + // Nevertheless, the image shows when the dive is selected the next time. + // DivePictureModel::instance()->updateDivePictures(); + } void loadPicture(struct picture *picture, bool fromHash) @@ -69,7 +83,7 @@ void loadPicture(struct picture *picture, bool fromHash) SHashedImage::SHashedImage(struct picture *picture) : QImage() { - QUrl url = QUrl::fromUserInput(QString(picture->filename)); + QUrl url = QUrl::fromUserInput(localFilePath(QString(picture->filename))); if(url.isLocalFile()) load(url.toLocalFile()); if (isNull()) { @@ -79,21 +93,21 @@ SHashedImage::SHashedImage(struct picture *picture) : QImage() if (filename.isNull()) { // That didn't produce a local filename. // Try the cloud server - QtConcurrent::run(loadPicture, picture, true); + QtConcurrent::run(loadPicture, clone_picture(picture), true); } else { // Load locally from translated file name load(filename); if (!isNull()) { // Make sure the hash still matches the image file - QtConcurrent::run(updateHash, picture); + QtConcurrent::run(updateHash, clone_picture(picture)); } else { // Interpret filename as URL - QtConcurrent::run(loadPicture, picture, false); + QtConcurrent::run(loadPicture, clone_picture(picture), false); } } } else { // We loaded successfully. Now, make sure hash is up to date. - QtConcurrent::run(hashPicture, picture); + QtConcurrent::run(hashPicture, clone_picture(picture)); } } diff --git a/subsurface-core/imagedownloader.h b/subsurface-core/imagedownloader.h index cd85c9509..f4e3df875 100644 --- a/subsurface-core/imagedownloader.h +++ b/subsurface-core/imagedownloader.h @@ -14,11 +14,13 @@ class ImageDownloader : public QObject { Q_OBJECT; public: ImageDownloader(struct picture *picture); + ~ImageDownloader(); void load(bool fromHash); private: struct picture *picture; QNetworkAccessManager manager; + bool loadFromHash; private slots: void saveImage(QNetworkReply *reply); diff --git a/subsurface-core/libdivecomputer.c b/subsurface-core/libdivecomputer.c index 0d0b397dc..549b894ce 100644 --- a/subsurface-core/libdivecomputer.c +++ b/subsurface-core/libdivecomputer.c @@ -1,3 +1,6 @@ +// Clang has a bug on zero-initialization of C structs. +#pragma clang diagnostic ignored "-Wmissing-field-initializers" + #include <stdio.h> #include <unistd.h> #include <inttypes.h> @@ -68,13 +71,14 @@ static dc_status_t create_parser(device_data_t *devdata, dc_parser_t **parser) return dc_parser_new(parser, devdata->device); } -static int parse_gasmixes(device_data_t *devdata, struct dive *dive, dc_parser_t *parser, int ngases) +static int parse_gasmixes(device_data_t *devdata, struct dive *dive, dc_parser_t *parser, unsigned int ngases) { static bool shown_warning = false; - int i, rc; + unsigned int i; + int rc; #if DC_VERSION_CHECK(0, 5, 0) && defined(DC_GASMIX_UNKNOWN) - int ntanks = 0; + unsigned int ntanks = 0; rc = dc_parser_get_field(parser, DC_FIELD_TANK_COUNT, 0, &ntanks); if (rc == DC_STATUS_SUCCESS) { if (ntanks && ntanks != ngases) { diff --git a/subsurface-core/linux.c b/subsurface-core/linux.c index d4131c7ea..b81f6bf53 100644 --- a/subsurface-core/linux.c +++ b/subsurface-core/linux.c @@ -25,6 +25,7 @@ void subsurface_OS_pref_setup(void) bool subsurface_ignore_font(const char *font) { // there are no old default fonts to ignore + (void)font; return false; } @@ -41,7 +42,7 @@ void subsurface_user_info(struct user_info *user) } if (username && *username) { char hostname[64]; - struct membuffer mb = { 0 }; + struct membuffer mb = {}; gethostname(hostname, sizeof(hostname)); put_format(&mb, "%s@%s", username, hostname); user->email = mb_cstring(&mb); @@ -126,7 +127,7 @@ int enumerate_devices(device_callback_t callback, void *userdata, int dc_type) if (fnmatch(patterns[i], ep->d_name, 0) == 0) { char filename[1024]; int n = snprintf(filename, sizeof(filename), "%s/%s", dirname, ep->d_name); - if (n >= sizeof(filename)) { + if (n >= (int)sizeof(filename)) { closedir(dp); return -1; } @@ -216,6 +217,7 @@ int subsurface_zip_close(struct zip *zip) /* win32 console */ void subsurface_console_init(bool dedicated) { + (void)dedicated; /* NOP */ } @@ -223,3 +225,8 @@ void subsurface_console_exit(void) { /* NOP */ } + +bool subsurface_user_is_root() +{ + return (geteuid() == 0); +} diff --git a/subsurface-core/load-git.c b/subsurface-core/load-git.c index cc702f6ae..a78082c07 100644 --- a/subsurface-core/load-git.c +++ b/subsurface-core/load-git.c @@ -1,3 +1,6 @@ +// Clang has a bug on zero-initialization of C structs. +#pragma clang diagnostic ignored "-Wmissing-field-initializers" + #include <stdio.h> #include <ctype.h> #include <string.h> diff --git a/subsurface-core/macos.c b/subsurface-core/macos.c index 8ca2c1c6f..500412cd8 100644 --- a/subsurface-core/macos.c +++ b/subsurface-core/macos.c @@ -119,7 +119,7 @@ int enumerate_devices(device_callback_t callback, void *userdata, int dc_type) if (fnmatch(patterns[i], ep->d_name, 0) == 0) { char filename[1024]; int n = snprintf(filename, sizeof(filename), "%s/%s", dirname, ep->d_name); - if (n >= sizeof(filename)) { + if (n >= (int)sizeof(filename)) { closedir(dp); return -1; } @@ -145,7 +145,7 @@ int enumerate_devices(device_callback_t callback, void *userdata, int dc_type) if (fnmatch("UEMISSDA", ep->d_name, 0) == 0) { char filename[1024]; int n = snprintf(filename, sizeof(filename), "%s/%s", dirname, ep->d_name); - if (n >= sizeof(filename)) { + if (n >= (int)sizeof(filename)) { closedir(dp); return -1; } @@ -211,3 +211,8 @@ void subsurface_console_exit(void) { /* NOP */ } + +bool subsurface_user_is_root() +{ + return (geteuid() == 0); +} diff --git a/subsurface-core/membuffer.c b/subsurface-core/membuffer.c index 2889a0cdc..053edb8f0 100644 --- a/subsurface-core/membuffer.c +++ b/subsurface-core/membuffer.c @@ -1,3 +1,6 @@ +// Clang has a bug on zero-initialization of C structs. +#pragma clang diagnostic ignored "-Wmissing-field-initializers" + #include <stdarg.h> #include <stdlib.h> #include <string.h> diff --git a/subsurface-core/metrics.cpp b/subsurface-core/metrics.cpp index db636794d..3c66528b8 100644 --- a/subsurface-core/metrics.cpp +++ b/subsurface-core/metrics.cpp @@ -15,7 +15,8 @@ IconMetrics::IconMetrics() : sz_med(-1), sz_big(-1), sz_pic(-1), - spacing(-1) + spacing(-1), + dpr(1.0) { } @@ -57,3 +58,8 @@ const IconMetrics & defaultIconMetrics() return dfltIconMetrics; } + +void updateDevicePixelRatio(double dpr) +{ + dfltIconMetrics.dpr = dpr; +} diff --git a/subsurface-core/metrics.h b/subsurface-core/metrics.h index 03d6b22e2..ca281b3b1 100644 --- a/subsurface-core/metrics.h +++ b/subsurface-core/metrics.h @@ -25,9 +25,12 @@ struct IconMetrics { int sz_pic; // ex 128px // icon spacing int spacing; // ex 2px + // devicePixelRatio + double dpr; // 1.0 for traditional screens, HiDPI screens up to 3.0 IconMetrics(); }; const IconMetrics & defaultIconMetrics(); +void updateDevicePixelRatio(double dpr); #endif // METRICS_H diff --git a/subsurface-core/parse-xml.c b/subsurface-core/parse-xml.c index a617648fb..e8782251e 100644 --- a/subsurface-core/parse-xml.c +++ b/subsurface-core/parse-xml.c @@ -1,3 +1,6 @@ +// Clang has a bug on zero-initialization of C structs. +#pragma clang diagnostic ignored "-Wmissing-field-initializers" + #include <stdio.h> #include <ctype.h> #include <string.h> @@ -20,7 +23,7 @@ #include "device.h" #include "membuffer.h" -int verbose, quit; +int verbose, quit, force_root; int metric = 1; int last_xml_version = -1; int diveid = -1; @@ -2010,7 +2013,7 @@ const char *preprocess_divelog_de(const char *buffer) if (ret) { xmlParserCtxtPtr ctx; char buf[] = ""; - int i; + size_t i; for (i = 0; i < strlen(ret); ++i) if (!isascii(ret[i])) @@ -2257,7 +2260,8 @@ extern int dm4_dive(void *param, int columns, char **data, char **column) { (void) columns; (void) column; - int i, interval, retval = 0; + unsigned int i; + int interval, retval = 0; sqlite3 *handle = (sqlite3 *)param; float *profileBlob; unsigned char *tempBlob; @@ -2385,7 +2389,8 @@ extern int dm5_dive(void *param, int columns, char **data, char **column) { (void) columns; (void) column; - int i, interval, retval = 0, block_size; + unsigned int i; + int interval, retval = 0, block_size; sqlite3 *handle = (sqlite3 *)param; unsigned const char *sampleBlob; char *err = NULL; diff --git a/subsurface-core/planner.c b/subsurface-core/planner.c index 1828d5a11..705aad1cb 100644 --- a/subsurface-core/planner.c +++ b/subsurface-core/planner.c @@ -9,6 +9,7 @@ #include <ctype.h> #include <string.h> #include "dive.h" +#include "deco.h" #include "divelist.h" #include "planner.h" #include "gettext.h" @@ -103,7 +104,7 @@ int get_gasidx(struct dive *dive, struct gasmix *mix) void interpolate_transition(struct dive *dive, duration_t t0, duration_t t1, depth_t d0, depth_t d1, const struct gasmix *gasmix, o2pressure_t po2) { - int j; + uint32_t j; for (j = t0.seconds; j < t1.seconds; j++) { int depth = interpolate(d0.mm, d1.mm, j - t0.seconds, t1.seconds - t0.seconds); @@ -476,11 +477,11 @@ static struct gaschanges *analyze_gaslist(struct diveplan *diveplan, int *gascha } /* sort all the stops into one ordered list */ -static unsigned int *sort_stops(int *dstops, int dnr, struct gaschanges *gstops, int gnr) +static int *sort_stops(int *dstops, int dnr, struct gaschanges *gstops, int gnr) { int i, gi, di; int total = dnr + gnr; - unsigned int *stoplevels = malloc(total * sizeof(int)); + int *stoplevels = malloc(total * sizeof(int)); /* no gaschanges */ if (gnr == 0) { @@ -534,7 +535,7 @@ static void add_plan_to_notes(struct diveplan *diveplan, struct dive *dive, bool const unsigned int sz_temp = 100000; char *buffer = (char *)malloc(sz_buffer); char *temp = (char *)malloc(sz_temp); - char *deco; + char *deco, *segmentsymbol; static char buf[1000]; int len, lastdepth = 0, lasttime = 0, lastsetpoint = -1, newdepth = 0, lastprintdepth = 0, lastprintsetpoint = -1; struct gasmix lastprintgasmix = {{ -1 }, { -1 }}; @@ -596,7 +597,7 @@ static void add_plan_to_notes(struct diveplan *diveplan, struct dive *dive, bool translate("gettextFromC", "Subsurface dive plan"), temp); if (!plan_verbatim) { - len += snprintf(buffer + len, sz_buffer - len, "<div><table><thead><tr><th>%s</th>", + len += snprintf(buffer + len, sz_buffer - len, "<div><table><thead><tr><th></th><th>%s</th>", translate("gettextFromC", "depth")); if (plan_display_duration) len += snprintf(buffer + len, sz_buffer - len, "<th style='padding-left: 10px;'>%s</th>", @@ -710,8 +711,20 @@ static void add_plan_to_notes(struct diveplan *diveplan, struct dive *dive, bool (!isascent && gaschange_before && nextdp && dp->depth != nextdp->depth) || (gaschange_after && lastentered) || (gaschange_after && !isascent) || (isascent && gaschange_after && nextdp && dp->depth != nextdp->depth )) { + // Print a symbol to indicate whether segment is an ascent, descent, constant depth (user entered) or deco stop + if (isascent) + segmentsymbol = "➚"; // up-right arrow for ascent + else if (dp->depth > lastdepth) + segmentsymbol = "➘"; // down-right arrow for descent + else if (dp->entered) + segmentsymbol = "➙"; // right arrow for entered entered segment at constant depth + else + segmentsymbol = "➖"; // heavey minus sign for deco stop + + len += snprintf(buffer + len, sz_buffer - len, "<tr><td style='padding-left: 10px; float: right;'>%s</td>", segmentsymbol); + snprintf(temp, sz_temp, translate("gettextFromC", "%3.0f%s"), depthvalue, depth_unit); - len += snprintf(buffer + len, sz_buffer - len, "<tr><td style='padding-left: 10px; float: right;'>%s</td>", temp); + len += snprintf(buffer + len, sz_buffer - len, "<td style='padding-left: 10px; float: right;'>%s</td>", temp); if (plan_display_duration) { snprintf(temp, sz_temp, translate("gettextFromC", "%3dmin"), (dp->time - lasttime + 30) / 60); len += snprintf(buffer + len, sz_buffer - len, "<td style='padding-left: 10px; float: right;'>%s</td>", temp); @@ -969,13 +982,13 @@ bool plan(struct diveplan *diveplan, char **cached_datap, bool is_planner, bool int po2; int transitiontime, gi; int current_cylinder; - unsigned int stopidx; + int stopidx; int depth; struct gaschanges *gaschanges = NULL; int gaschangenr; int *decostoplevels; int decostoplevelcount; - unsigned int *stoplevels = NULL; + int *stoplevels = NULL; bool stopping = false; bool pendinggaschange = false; int clock, previous_point_time; diff --git a/subsurface-core/profile.c b/subsurface-core/profile.c index 4d9a8444f..6576f6453 100644 --- a/subsurface-core/profile.c +++ b/subsurface-core/profile.c @@ -377,7 +377,7 @@ static int count_events(struct divecomputer *dc) return result; } -static int set_cylinder_index(struct plot_info *pi, int i, int cylinderindex, unsigned int end) +static int set_cylinder_index(struct plot_info *pi, int i, int cylinderindex, int end) { while (i < pi->nr) { struct plot_data *entry = pi->entry + i; @@ -392,7 +392,7 @@ static int set_cylinder_index(struct plot_info *pi, int i, int cylinderindex, un return i; } -static int set_setpoint(struct plot_info *pi, int i, int setpoint, unsigned int end) +static int set_setpoint(struct plot_info *pi, int i, int setpoint, int end) { while (i < pi->nr) { struct plot_data *entry = pi->entry + i; @@ -405,7 +405,7 @@ static int set_setpoint(struct plot_info *pi, int i, int setpoint, unsigned int } /* normally the first cylinder has index 0... if not, we need to fix this up here */ -static int set_first_cylinder_index(struct plot_info *pi, int i, int cylinderindex, unsigned int end) +static int set_first_cylinder_index(struct plot_info *pi, int i, int cylinderindex, int end) { while (i < pi->nr) { struct plot_data *entry = pi->entry + i; @@ -425,7 +425,7 @@ static void check_gas_change_events(struct dive *dive, struct divecomputer *dc, // for dive computers that tell us their first gas as an event on the first sample // we need to make sure things are setup correctly cylinderindex = explicit_first_cylinder(dive, dc); - set_first_cylinder_index(pi, 0, cylinderindex, ~0u); + set_first_cylinder_index(pi, 0, cylinderindex, INT_MAX); if (!ev) return; @@ -435,7 +435,7 @@ static void check_gas_change_events(struct dive *dive, struct divecomputer *dc, cylinderindex = get_cylinder_index(dive, ev); ev = get_next_event(ev->next, "gaschange"); } while (ev); - set_cylinder_index(pi, i, cylinderindex, ~0u); + set_cylinder_index(pi, i, cylinderindex, INT_MAX); } static void check_setpoint_events(struct dive *dive, struct divecomputer *dc, struct plot_info *pi) @@ -456,7 +456,7 @@ static void check_setpoint_events(struct dive *dive, struct divecomputer *dc, st dc->divemode = CCR; ev = get_next_event(ev->next, "SP change"); } while (ev); - set_setpoint(pi, i, setpoint.mbar, ~0u); + set_setpoint(pi, i, setpoint.mbar, INT_MAX); } @@ -466,7 +466,7 @@ struct plot_info calculate_max_limits_new(struct dive *dive, struct divecomputer bool seen = false; static struct plot_info pi; int maxdepth = dive->maxdepth.mm; - int maxtime = 0; + unsigned int maxtime = 0; int maxpressure = 0, minpressure = INT_MAX; int maxhr = 0, minhr = INT_MAX; int mintemp = dive->mintemp.mkelvin; @@ -606,7 +606,7 @@ struct plot_data *populate_plot_entries(struct dive *dive, struct divecomputer * break; /* Add events if they are between plot entries */ - while (ev && ev->time.seconds < lasttime + offset) { + while (ev && (int)ev->time.seconds < lasttime + offset) { INSERT_ENTRY(ev->time.seconds, interpolate(lastdepth, depth, ev->time.seconds - lasttime, delta), sac); ev = ev->next; } @@ -615,12 +615,12 @@ struct plot_data *populate_plot_entries(struct dive *dive, struct divecomputer * INSERT_ENTRY(lasttime + offset, interpolate(lastdepth, depth, offset, delta), sac); /* skip events that happened at this time */ - while (ev && ev->time.seconds == lasttime + offset) + while (ev && (int)ev->time.seconds == lasttime + offset) ev = ev->next; } /* Add events if they are between plot entries */ - while (ev && ev->time.seconds < time) { + while (ev && (int)ev->time.seconds < time) { INSERT_ENTRY(ev->time.seconds, interpolate(lastdepth, depth, ev->time.seconds - lasttime, delta), sac); ev = ev->next; } @@ -659,7 +659,7 @@ struct plot_data *populate_plot_entries(struct dive *dive, struct divecomputer * if (sample->rbt.seconds) entry->rbt = sample->rbt.seconds; /* skip events that happened at this time */ - while (ev && ev->time.seconds == time) + while (ev && (int)ev->time.seconds == time) ev = ev->next; lasttime = time; lastdepth = depth; diff --git a/subsurface-core/qthelper.cpp b/subsurface-core/qthelper.cpp index 7c67e0993..e103b44e5 100644 --- a/subsurface-core/qthelper.cpp +++ b/subsurface-core/qthelper.cpp @@ -1108,11 +1108,14 @@ QString fileFromHash(char *hash) return localFilenameOf[QByteArray::fromHex(hash)]; } +// This needs to operate on a copy of picture as it frees it after finishing! void updateHash(struct picture *picture) { QByteArray hash = hashFile(fileFromHash(picture->hash)); learnHash(picture, hash); + picture_free(picture); } +// This needs to operate on a copy of picture as it frees it after finishing! void hashPicture(struct picture *picture) { char *oldHash = copy_string(picture->hash); @@ -1120,13 +1123,14 @@ void hashPicture(struct picture *picture) if (!same_string(picture->hash, "") && !same_string(picture->hash, oldHash)) mark_divelist_changed((true)); free(oldHash); + picture_free(picture); } extern "C" void cache_picture(struct picture *picture) { QString filename = picture->filename; if (!hashOf.contains(filename)) - QtConcurrent::run(hashPicture, picture); + QtConcurrent::run(hashPicture, clone_picture(picture)); } void learnImages(const QDir dir, int max_recursions) @@ -1476,7 +1480,12 @@ void loadPreferences() s.beginGroup("CloudStorage"); GET_TXT("email", cloud_storage_email); +#ifndef SUBSURFACE_MOBILE GET_BOOL("save_password_local", save_password_local); +#else + // always save the password in Subsurface-mobile + prefs.save_password_local = true; +#endif if (prefs.save_password_local) { // GET_TEXT macro is not a single statement GET_TXT("password", cloud_storage_password); } @@ -1513,6 +1522,11 @@ void loadPreferences() GET_ENUM("cat2", taxonomy_category, geocoding.category[2]); s.endGroup(); + // GPS service time and distance thresholds + s.beginGroup("LocationService"); + GET_INT("time_threshold", time_threshold); + GET_INT("distance_threshold", distance_threshold); + s.endGroup(); } extern "C" bool isCloudUrl(const char *filename) diff --git a/subsurface-core/qtserialbluetooth.cpp b/subsurface-core/qtserialbluetooth.cpp index 025ab8c34..6b104157a 100644 --- a/subsurface-core/qtserialbluetooth.cpp +++ b/subsurface-core/qtserialbluetooth.cpp @@ -313,6 +313,7 @@ static int qt_serial_write(serial_t *device, const void* data, unsigned int size static int qt_serial_flush(serial_t *device, int queue) { + (void)queue; if (device == NULL) return DC_STATUS_INVALIDARGS; #if !defined(Q_OS_WIN) diff --git a/subsurface-core/save-git.c b/subsurface-core/save-git.c index 054c7e9b4..d089095b6 100644 --- a/subsurface-core/save-git.c +++ b/subsurface-core/save-git.c @@ -1,3 +1,6 @@ +// Clang has a bug on zero-initialization of C structs. +#pragma clang diagnostic ignored "-Wmissing-field-initializers" + #include <stdio.h> #include <ctype.h> #include <string.h> diff --git a/subsurface-core/save-html.c b/subsurface-core/save-html.c index 5fc5b000a..2d0ea9cf3 100644 --- a/subsurface-core/save-html.c +++ b/subsurface-core/save-html.c @@ -1,3 +1,6 @@ +// Clang has a bug on zero-initialization of C structs. +#pragma clang diagnostic ignored "-Wmissing-field-initializers" + #include "save-html.h" #include "qthelperfromc.h" #include "gettext.h" diff --git a/subsurface-core/save-xml.c b/subsurface-core/save-xml.c index eabcf4f26..2335637e8 100644 --- a/subsurface-core/save-xml.c +++ b/subsurface-core/save-xml.c @@ -1,3 +1,6 @@ +// Clang has a bug on zero-initialization of C structs. +#pragma clang diagnostic ignored "-Wmissing-field-initializers" + #include <stdio.h> #include <ctype.h> #include <string.h> diff --git a/subsurface-core/statistics.c b/subsurface-core/statistics.c index 373a6a0d0..6a05cffc1 100644 --- a/subsurface-core/statistics.c +++ b/subsurface-core/statistics.c @@ -48,7 +48,7 @@ static void process_temperatures(struct dive *dp, stats_t *stats) static void process_dive(struct dive *dp, stats_t *stats) { int old_tt, sac_time = 0; - int duration = dp->duration.seconds; + uint32_t duration = dp->duration.seconds; old_tt = stats->total_time.seconds; stats->total_time.seconds += duration; @@ -297,14 +297,14 @@ static void get_ranges(char *buffer, int size) } } -void get_selected_dives_text(char *buffer, int size) +void get_selected_dives_text(char *buffer, size_t size) { if (amount_selected == 1) { if (current_dive) snprintf(buffer, size, translate("gettextFromC", "for dive #%d"), current_dive->number); else snprintf(buffer, size, "%s", translate("gettextFromC", "for selected dive")); - } else if (amount_selected == dive_table.nr) { + } else if (amount_selected == (unsigned int)dive_table.nr) { snprintf(buffer, size, "%s", translate("gettextFromC", "for all dives")); } else if (amount_selected == 0) { snprintf(buffer, size, "%s", translate("gettextFromC", "(no dives)")); @@ -313,7 +313,7 @@ void get_selected_dives_text(char *buffer, int size) if (strlen(buffer) == size - 1) { /* add our own ellipse... the way Pango does this is ugly * as it will leave partial numbers there which I don't like */ - int offset = 4; + size_t offset = 4; while (offset < size && isdigit(buffer[size - offset])) offset++; strcpy(buffer + size - offset, "..."); diff --git a/subsurface-core/statistics.h b/subsurface-core/statistics.h index 890e6e53c..015c3481e 100644 --- a/subsurface-core/statistics.h +++ b/subsurface-core/statistics.h @@ -44,7 +44,7 @@ extern stats_t *stats_by_type; extern char *get_time_string_s(int seconds, int maxdays, bool freediving); extern char *get_minutes(int seconds); extern void process_all_dives(struct dive *dive, struct dive **prev_dive); -extern void get_selected_dives_text(char *buffer, int size); +extern void get_selected_dives_text(char *buffer, size_t size); extern void get_gas_used(struct dive *dive, volume_t gases[MAX_CYLINDERS]); extern void process_selected_dives(void); void selected_dives_gas_parts(volume_t *o2_tot, volume_t *he_tot); diff --git a/subsurface-core/subsurfacestartup.c b/subsurface-core/subsurfacestartup.c index 864134724..6e0dede1c 100644 --- a/subsurface-core/subsurfacestartup.c +++ b/subsurface-core/subsurfacestartup.c @@ -217,6 +217,10 @@ void parse_argument(const char *arg) run_survey = true; return; } + if (strcmp(arg, "--allow_run_as_root") == 0) { + ++force_root; + return; + } if (strcmp(arg, "--win32console") == 0) return; /* fallthrough */ @@ -233,18 +237,6 @@ void parse_argument(const char *arg) } while (*++p); } -void renumber_dives(int start_nr, bool selected_only) -{ - int i, nr = start_nr; - struct dive *dive; - - for_each_dive (i, dive) { - if (dive->selected) - dive->number = nr++; - } - mark_divelist_changed(true); -} - /* * Under a POSIX setup, the locale string should have a format * like [language[_territory][.codeset][@modifier]]. diff --git a/subsurface-core/time.c b/subsurface-core/time.c index b658954bc..0893f19d8 100644 --- a/subsurface-core/time.c +++ b/subsurface-core/time.c @@ -11,16 +11,16 @@ */ void utc_mkdate(timestamp_t timestamp, struct tm *tm) { - static const int mdays[] = { + static const unsigned int mdays[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, }; - static const int mdays_leap[] = { + static const unsigned int mdays_leap[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, }; unsigned long val; unsigned int leapyears; int m; - const int *mp; + const unsigned int *mp; memset(tm, 0, sizeof(*tm)); diff --git a/subsurface-core/uemis-downloader.c b/subsurface-core/uemis-downloader.c index 6f5c5f177..b9b532303 100644 --- a/subsurface-core/uemis-downloader.c +++ b/subsurface-core/uemis-downloader.c @@ -506,7 +506,8 @@ static bool uemis_get_answer(const char *path, char *request, int n_param_in, #if UEMIS_DEBUG & 4 fprintf(debugfile, "::w req.txt \"%s\"\n", sb); #endif - if (write(reqtxt_file, sb, strlen(sb)) != strlen(sb)) { + int written = write(reqtxt_file, sb, strlen(sb)); + if (written == -1 || (size_t)written != strlen(sb)) { *error_text = translate("gettextFromC", ERR_FS_SHORT_WRITE); return false; } @@ -784,7 +785,7 @@ static bool uemis_delete_dive(device_data_t *devdata, uint32_t diveid) * index into yet another data store that we read out later. In order to * correctly populate the location and gps data from that we need to remember * the addresses of those fields for every dive that references the divespot. */ -static bool process_raw_buffer(device_data_t *devdata, uint32_t deviceid, char *inbuf, char **max_divenr, bool keep_number, int *for_dive) +static bool process_raw_buffer(device_data_t *devdata, uint32_t deviceid, char *inbuf, char **max_divenr, int *for_dive) { char *buf = strdup(inbuf); char *tp, *bp, *tag, *type, *val; @@ -793,7 +794,7 @@ static bool process_raw_buffer(device_data_t *devdata, uint32_t deviceid, char * char *endptr = buf + inbuflen; bool is_log = false, is_dive = false; char *sections[10]; - int s, nr_sections = 0; + size_t s, nr_sections = 0; struct dive *dive = NULL; char dive_no[10]; @@ -974,7 +975,7 @@ static char *uemis_get_divenr(char *deviceidstr, int force) maxdiveid = dc->diveid; } } - if (max_deleted_seen >= 0 && maxdiveid < max_deleted_seen) { + if (max_deleted_seen >= 0 && maxdiveid < (uint32_t)max_deleted_seen) { maxdiveid = max_deleted_seen; #if UEMIS_DEBUG & 4 fprintf(debugfile, "overriding max seen with max deleted seen %d\n", max_deleted_seen); @@ -1154,7 +1155,7 @@ static bool get_matching_dive(int idx, char *newmax, int *uemis_mem_status, stru * we mark the search successful even if the dive has been deleted. */ found = true; if (strstr(mbuf, "deleted{bool{true") == NULL) { - process_raw_buffer(data, deviceidnr, mbuf, &newmax, false, NULL); + process_raw_buffer(data, deviceidnr, mbuf, &newmax, NULL); /* remember the last log file number as it is very likely that subsequent dives * have the same or higher logfile number. * UEMIS unfortunately deletes dives by deleting the dive details and not the logs. */ @@ -1223,7 +1224,7 @@ const char *do_uemis_import(device_data_t *data) char *deviceid = NULL; const char *result = NULL; char *endptr; - bool success, keep_number = false, once = true; + bool success, once = true; int match_dive_and_log = 0; int uemis_mem_status = UEMIS_MEM_OK; @@ -1231,9 +1232,6 @@ const char *do_uemis_import(device_data_t *data) home = getenv("HOME"); user = getenv("LOGNAME"); #endif - if (dive_table.nr == 0) - keep_number = true; - uemis_info(translate("gettextFromC", "Initialise communication")); if (!uemis_init(mountpath)) { free(reqtxt_path); @@ -1287,7 +1285,7 @@ const char *do_uemis_import(device_data_t *data) do_dump_buffer_to_file(realmbuf, "Divelogs"); #endif /* process the buffer we have assembled */ - if (!process_raw_buffer(data, deviceidnr, realmbuf, &newmax, keep_number, NULL)) { + if (!process_raw_buffer(data, deviceidnr, realmbuf, &newmax, NULL)) { /* if no dives were downloaded, mark end appropriately */ if (end == -2) end = start - 1; diff --git a/subsurface-core/uemis.c b/subsurface-core/uemis.c index 4135e0cfe..5635d5630 100644 --- a/subsurface-core/uemis.c +++ b/subsurface-core/uemis.c @@ -98,7 +98,7 @@ static int uemis_convert_base64(char *base64, uint8_t **data) } struct uemis_helper { - int diveid; + uint32_t diveid; int lbs; int divespot; int dive_site_uuid; @@ -106,7 +106,7 @@ struct uemis_helper { }; static struct uemis_helper *uemis_helper = NULL; -static struct uemis_helper *uemis_get_helper(int diveid) +static struct uemis_helper *uemis_get_helper(uint32_t diveid) { struct uemis_helper **php = &uemis_helper; struct uemis_helper *hp = *php; @@ -134,7 +134,7 @@ static void uemis_weight_unit(int diveid, int lbs) hp->lbs = lbs; } -int uemis_get_weight_unit(int diveid) +int uemis_get_weight_unit(uint32_t diveid) { struct uemis_helper *hp = uemis_helper; while (hp) { diff --git a/subsurface-core/uemis.h b/subsurface-core/uemis.h index 5f32fe76c..1758b4b32 100644 --- a/subsurface-core/uemis.h +++ b/subsurface-core/uemis.h @@ -13,7 +13,7 @@ extern "C" { #endif void uemis_parse_divelog_binary(char *base64, void *divep); -int uemis_get_weight_unit(int diveid); +int uemis_get_weight_unit(uint32_t diveid); void uemis_mark_divelocation(int diveid, int divespot, uint32_t dive_site_uuid); void uemis_set_divelocation(int divespot, char *text, double longitude, double latitude); int uemis_get_divespot_id_by_diveid(uint32_t diveid); diff --git a/subsurface-core/units.h b/subsurface-core/units.h index 9ad4b7282..029bb64fa 100644 --- a/subsurface-core/units.h +++ b/subsurface-core/units.h @@ -99,7 +99,7 @@ typedef struct typedef struct { - int32_t mkelvin; // up to 1750 degrees K + uint32_t mkelvin; // up to 1750 degrees K (temperatures in K are always positive) } temperature_t; typedef struct diff --git a/subsurface-core/windows.c b/subsurface-core/windows.c index a2386fd83..58d3beaad 100644 --- a/subsurface-core/windows.c +++ b/subsurface-core/windows.c @@ -446,3 +446,9 @@ void subsurface_console_exit(void) FreeConsole(); #endif } + +bool subsurface_user_is_root() +{ + /* FIXME: Detect admin rights */ + return (false); +} diff --git a/subsurface-core/worldmap-save.c b/subsurface-core/worldmap-save.c index f79978495..e7e8bcc30 100644 --- a/subsurface-core/worldmap-save.c +++ b/subsurface-core/worldmap-save.c @@ -1,3 +1,6 @@ +// Clang has a bug on zero-initialization of C structs. +#pragma clang diagnostic ignored "-Wmissing-field-initializers" + #include <stdarg.h> #include <stdlib.h> #include <string.h> |