summaryrefslogtreecommitdiffstats
path: root/core/dive.c
diff options
context:
space:
mode:
authorGravatar Berthold Stoeger <bstoeger@mail.tuwien.ac.at>2018-07-20 20:26:06 +0200
committerGravatar Dirk Hohndel <dirk@hohndel.org>2018-10-11 16:22:27 -0700
commit302f6adb79681da3fe53336f1e4c7525f46fd47d (patch)
treece752cf002ec01cd9c26a804e49b2ee5b516d6ac /core/dive.c
parent12df9faaa2037b5155ebb84a7f6f6102491a0091 (diff)
downloadsubsurface-302f6adb79681da3fe53336f1e4c7525f46fd47d.tar.gz
Undo: implement rudimentary support for undo of dive-splitting
For this, the core functionality of the split_dive() and split_dive_at_time() functions were split out into new split_dive_dont_insert() and split_dive_at_time_dont_insert(), which do not add the new dives to the log. Thus, the undo-command can take ownership of these dives, without having to remove them first. The split-dive functionality is temporarily made desktop-only until mobile also supports "UndoObjects". Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Diffstat (limited to 'core/dive.c')
-rw-r--r--core/dive.c76
1 files changed, 50 insertions, 26 deletions
diff --git a/core/dive.c b/core/dive.c
index d7a2f11a8..1e8f23623 100644
--- a/core/dive.c
+++ b/core/dive.c
@@ -3388,7 +3388,7 @@ struct dive *merge_dives(struct dive *a, struct dive *b, int offset, bool prefer
}
// copy_dive(), but retaining the new ID for the copied dive
-static struct dive *create_new_copy(struct dive *from)
+static struct dive *create_new_copy(const struct dive *from)
{
struct dive *to = alloc_dive();
int id;
@@ -3450,9 +3450,11 @@ static void force_fixup_dive(struct dive *d)
/*
* Split a dive that has a surface interval from samples 'a' to 'b'
- * into two dives.
+ * into two dives, but don't add them to the log yet.
+ * Returns the nr of the old dive or <0 on failure.
+ * On success, the newly allocated dives are returned in out1 and out2.
*/
-static int split_dive_at(struct dive *dive, int a, int b)
+static int split_dive_at(const struct dive *dive, int a, int b, struct dive **out1, struct dive **out2)
{
int i, nr;
uint32_t t;
@@ -3462,15 +3464,16 @@ static int split_dive_at(struct dive *dive, int a, int b)
/* if we can't find the dive in the dive list, don't bother */
if ((nr = get_divenr(dive)) < 0)
- return 0;
+ return -1;
/* Splitting should leave at least 3 samples per dive */
if (a < 3 || b > dive->dc.samples - 4)
- return 0;
+ return -1;
/* We're not trying to be efficient here.. */
d1 = create_new_copy(dive);
d2 = create_new_copy(dive);
+ d1->divetrip = d2->divetrip = 0;
/* now unselect the first first segment so we don't keep all
* dives selected by mistake. But do keep the second one selected
@@ -3544,15 +3547,6 @@ static int split_dive_at(struct dive *dive, int a, int b)
force_fixup_dive(d1);
force_fixup_dive(d2);
- if (dive->divetrip) {
- d1->divetrip = d2->divetrip = 0;
- add_dive_to_trip(d1, dive->divetrip);
- add_dive_to_trip(d2, dive->divetrip);
- }
-
- delete_single_dive(nr);
- add_single_dive(nr, d1);
-
/*
* Was the dive numbered? If it was the last dive, then we'll
* increment the dive number for the tail part that we split off.
@@ -3564,16 +3558,28 @@ static int split_dive_at(struct dive *dive, int a, int b)
else
d2->number = 0;
}
- add_single_dive(nr + 1, d2);
mark_divelist_changed(true);
- return 1;
+ *out1 = d1;
+ *out2 = d2;
+ return nr;
+}
+
+static void finish_split(int nr, struct dive *old, struct dive *d1, struct dive *d2)
+{
+ if (old->divetrip) {
+ add_dive_to_trip(d1, old->divetrip);
+ add_dive_to_trip(d2, old->divetrip);
+ }
+ delete_single_dive(nr);
+ add_single_dive(nr, d1);
+ add_single_dive(nr + 1, d2);
}
/* in freedive mode we split for as little as 10 seconds on the surface,
* otherwise we use a minute */
-static bool should_split(struct divecomputer *dc, int t1, int t2)
+static bool should_split(const struct divecomputer *dc, int t1, int t2)
{
int threshold = dc->divemode == FREEDIVE ? 10 : 60;
@@ -3590,14 +3596,14 @@ static bool should_split(struct divecomputer *dc, int t1, int t2)
*
* In other words, this is a (simplified) reversal of the dive merging.
*/
-int split_dive(struct dive *dive)
+int split_dive_dont_insert(const struct dive *dive, struct dive **new1, struct dive **new2)
{
int i;
int at_surface, surface_start;
- struct divecomputer *dc;
+ const struct divecomputer *dc;
if (!dive)
- return 0;
+ return -1;
dc = &dive->dc;
surface_start = 0;
@@ -3627,25 +3633,43 @@ int split_dive(struct dive *dive)
if (!should_split(dc, dc->sample[surface_start].time.seconds, sample[-1].time.seconds))
continue;
- return split_dive_at(dive, surface_start, i-1);
+ return split_dive_at(dive, surface_start, i-1, new1, new2);
}
- return 0;
+ return -1;
}
-void split_dive_at_time(struct dive *dive, duration_t time)
+void split_dive(struct dive *dive)
+{
+ int nr;
+ struct dive *new1, *new2;
+
+ if ((nr = split_dive_dont_insert(dive, &new1, &new2)) >= 0)
+ finish_split(nr, dive, new1, new2);
+}
+
+int split_dive_at_time_dont_insert(const struct dive *dive, duration_t time, struct dive **new1, struct dive **new2)
{
int i = 0;
struct sample *sample = dive->dc.sample;
if (!dive)
- return;
+ return -1;
while(sample->time.seconds < time.seconds) {
++sample;
++i;
if (dive->dc.samples == i)
- return;
+ return -1;
}
- split_dive_at(dive, i, i - 1);
+ return split_dive_at(dive, i, i - 1, new1, new2);
+}
+
+void split_dive_at_time(struct dive *dive, duration_t time)
+{
+ int nr;
+ struct dive *new1, *new2;
+
+ if ((nr = split_dive_at_time_dont_insert(dive, time, &new1, &new2)) >= 0)
+ finish_split(nr, dive, new1, new2);
}
/*