summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
authorGravatar Berthold Stoeger <bstoeger@mail.tuwien.ac.at>2019-03-31 10:20:13 +0200
committerGravatar Dirk Hohndel <dirk@hohndel.org>2019-04-04 09:38:12 -0700
commit145f70aab59a5ebd1b4ca82432caf38b4821b055 (patch)
tree2527f595c552559ffe74e6cce39f3c52283762d9 /core
parent8c9e5becb20d2d8c8aa1f7108775cc520b08fae1 (diff)
downloadsubsurface-145f70aab59a5ebd1b4ca82432caf38b4821b055.tar.gz
Undo: implement split-out of dive computer
Allow splitting out a dive computer into a distinct dive. This is realized by generating a base class from SplitDive. This turned out to be more cumbersome than expected: we don't know a-priori which of the split dives will come first. Since the undo-command saves the indices where the dives will be insert, these have to be calculated. This is an premature optimization, which makes more pain than necessary. Let's remove it and simply determine the insertion index when executing the command. Original code by Linus Torvalds <torvalds@linux-foundation.org>. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at> Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Diffstat (limited to 'core')
-rw-r--r--core/dive.c85
-rw-r--r--core/dive.h1
2 files changed, 73 insertions, 13 deletions
diff --git a/core/dive.c b/core/dive.c
index c73453a04..3ee8e5e2c 100644
--- a/core/dive.c
+++ b/core/dive.c
@@ -596,7 +596,7 @@ void clear_dive(struct dive *d)
/* make a true copy that is independent of the source dive;
* all data structures are duplicated, so the copy can be modified without
* any impact on the source */
-void copy_dive(const struct dive *s, struct dive *d)
+static void copy_dive_nodc(const struct dive *s, struct dive *d)
{
clear_dive(d);
/* simply copy things over, but then make actual copies of the
@@ -614,12 +614,24 @@ void copy_dive(const struct dive *s, struct dive *d)
d->weightsystem[i].description = copy_string(s->weightsystem[i].description);
STRUCTURED_LIST_COPY(struct picture, s->picture_list, d->picture_list, copy_pl);
STRUCTURED_LIST_COPY(struct tag_entry, s->tag_list, d->tag_list, copy_tl);
+}
+
+void copy_dive(const struct dive *s, struct dive *d)
+{
+ copy_dive_nodc(s, d);
// Copy the first dc explicitly, then the list of subsequent dc's
copy_dc(&s->dc, &d->dc);
STRUCTURED_LIST_COPY(struct divecomputer, s->dc.next, d->dc.next, copy_dc);
}
+static void copy_dive_onedc(const struct dive *s, const struct divecomputer *sdc, struct dive *d)
+{
+ copy_dive_nodc(s, d);
+ copy_dc(sdc, &d->dc);
+ d->dc.next = NULL;
+}
+
/* make a clone of the source dive and clean out the source dive;
* this is specifically so we can create a dive in the displayed_dive and then
* add it to the divelist.
@@ -3497,6 +3509,7 @@ static void force_fixup_dive(struct dive *d)
* Split a dive that has a surface interval from samples 'a' to 'b'
* into two dives, but don't add them to the log yet.
* Returns the nr of the old dive or <0 on failure.
+ * Moreover, on failure both output dives are set to NULL.
* On success, the newly allocated dives are returned in out1 and out2.
*/
static int split_dive_at(const struct dive *dive, int a, int b, struct dive **out1, struct dive **out2)
@@ -3507,6 +3520,8 @@ static int split_dive_at(const struct dive *dive, int a, int b, struct dive **ou
struct divecomputer *dc1, *dc2;
struct event *event, **evp;
+ *out1 = *out2 = NULL;
+
/* if we can't find the dive in the dive list, don't bother */
if ((nr = get_divenr(dive)) < 0)
return -1;
@@ -4076,30 +4091,74 @@ unsigned int count_divecomputers(void)
return ret;
}
-/* always acts on the current dive */
-void delete_current_divecomputer(void)
+static void delete_divecomputer(struct dive *d, int num)
{
- struct divecomputer *dc = current_dc;
+ int i;
+
+ /* Refuse to delete the last dive computer */
+ if (!d->dc.next)
+ return;
- if (dc == &current_dive->dc) {
+ if (num == 0) {
/* remove the first one, so copy the second one in place of the first and free the second one
* be careful about freeing the no longer needed structures - since we copy things around we can't use free_dc()*/
- struct divecomputer *fdc = dc->next;
- free_dc_contents(dc);
- memcpy(dc, fdc, sizeof(struct divecomputer));
+ struct divecomputer *fdc = d->dc.next;
+ free_dc_contents(&d->dc);
+ memcpy(&d->dc, fdc, sizeof(struct divecomputer));
free(fdc);
} else {
- struct divecomputer *pdc = &current_dive->dc;
- while (pdc->next != dc && pdc->next)
+ struct divecomputer *pdc = &d->dc;
+ for (i = 0; i < num - 1 && pdc; i++)
pdc = pdc->next;
- if (pdc->next == dc) {
+ if (pdc->next) {
+ struct divecomputer *dc = pdc->next;
pdc->next = dc->next;
free_dc(dc);
}
}
- if (dc_number == count_divecomputers())
+
+ /* If this is the currently displayed dive, we might have to adjust
+ * the currently displayed dive computer. */
+ if (d == current_dive && dc_number >= count_divecomputers())
dc_number--;
- invalidate_dive_cache(current_dive);
+ invalidate_dive_cache(d);
+}
+
+/* always acts on the current dive */
+void delete_current_divecomputer(void)
+{
+ delete_divecomputer(current_dive, dc_number);
+}
+
+/*
+ * This splits the dive src by dive computer. The first output dive has all
+ * dive computers except num, the second only dive computer num.
+ * The dives will not be associated with a trip.
+ * On error, both output parameters are set to NULL.
+ */
+void split_divecomputer(const struct dive *src, int num, struct dive **out1, struct dive **out2)
+{
+ struct divecomputer *srcdc = get_dive_dc(current_dive, dc_number);
+
+ if (src && srcdc) {
+ // Copy the dive, but only using the selected dive computer
+ *out2 = alloc_dive();
+ copy_dive_onedc(src, srcdc, *out2);
+
+ // This will also make fixup_dive() to allocate a new dive id...
+ (*out2)->id = 0;
+ fixup_dive(*out2);
+
+ // Copy the dive with all dive computers
+ *out1 = create_new_copy(src);
+
+ // .. and then delete the split-out dive computer
+ delete_divecomputer(*out1, num);
+
+ (*out1)->divetrip = (*out2)->divetrip = NULL;
+ } else {
+ *out1 = *out2 = NULL;
+ }
}
/* helper function to make it easier to work with our structures
diff --git a/core/dive.h b/core/dive.h
index 4773d3157..874f724c7 100644
--- a/core/dive.h
+++ b/core/dive.h
@@ -440,6 +440,7 @@ extern timestamp_t dive_endtime(const struct dive *dive);
extern void make_first_dc(void);
extern unsigned int count_divecomputers(void);
extern void delete_current_divecomputer(void);
+void split_divecomputer(const struct dive *src, int num, struct dive **out1, struct dive **out2);
/*
* Iterate over each dive, with the first parameter being the index