summaryrefslogtreecommitdiffstats
path: root/core/divelist.c
diff options
context:
space:
mode:
Diffstat (limited to 'core/divelist.c')
-rw-r--r--core/divelist.c109
1 files changed, 94 insertions, 15 deletions
diff --git a/core/divelist.c b/core/divelist.c
index 63bb7aa07..f6453e04c 100644
--- a/core/divelist.c
+++ b/core/divelist.c
@@ -22,7 +22,10 @@
* void remove_dive_from_trip(struct dive *dive, bool was_autogen)
* void add_dive_to_trip(struct dive *dive, dive_trip_t *trip)
* dive_trip_t *create_and_hookup_trip_from_dive(struct dive *dive)
+ * dive_trip_t *get_dives_to_autogroup(int start, int *from, int *to, bool *allocated)
* void autogroup_dives(void)
+ * void combine_trips(struct dive_trip *trip_a, struct dive_trip *trip_b)
+ * dive_trip_t *combine_trips_create(struct dive_trip *trip_a, struct dive_trip *trip_b)
* struct dive *unregister_dive(int idx)
* void delete_single_dive(int idx)
* void add_single_dive(int idx, struct dive *dive)
@@ -877,12 +880,27 @@ void add_dive_to_trip(struct dive *dive, dive_trip_t *trip)
trip->when = dive->when;
}
+dive_trip_t *alloc_trip(void)
+{
+ return calloc(1, sizeof(dive_trip_t));
+}
+
+dive_trip_t *create_trip_from_dive(struct dive *dive)
+{
+ dive_trip_t *trip;
+
+ trip = alloc_trip();
+ trip->when = dive->when;
+ trip->location = copy_string(get_dive_location(dive));
+
+ return trip;
+}
+
dive_trip_t *create_and_hookup_trip_from_dive(struct dive *dive)
{
- dive_trip_t *dive_trip = calloc(1, sizeof(dive_trip_t));
+ dive_trip_t *dive_trip = alloc_trip();
- dive_trip->when = dive->when;
- dive_trip->location = copy_string(get_dive_location(dive));
+ dive_trip = create_trip_from_dive(dive);
insert_trip(&dive_trip);
dive->tripflag = IN_TRIP;
@@ -891,14 +909,23 @@ dive_trip_t *create_and_hookup_trip_from_dive(struct dive *dive)
}
/*
- * Walk the dives from the oldest dive, and see if we can autogroup them
+ * Collect dives for auto-grouping. Pass in first dive which should be checked.
+ * Returns range of dives that should be autogrouped and trip it should be
+ * associated to. If the returned trip was newly allocated, the last bool
+ * is set to true. Caller still has to register it in the system. Note
+ * whereas this looks complicated - it is needed by the undo-system, which
+ * manually injects the new trips. If there are no dives to be autogrouped,
+ * return NULL.
*/
-void autogroup_dives(void)
+dive_trip_t *get_dives_to_autogroup(int start, int *from, int *to, bool *allocated)
{
int i;
struct dive *dive, *lastdive = NULL;
- for_each_dive(i, dive) {
+ /* Find first dive that should be merged and remember any previous
+ * dive that could be merged into.
+ */
+ for (i = start; (dive = get_dive(i)) != NULL; i++) {
dive_trip_t *trip;
if (dive->divetrip) {
@@ -911,21 +938,53 @@ void autogroup_dives(void)
continue;
}
- /* Do we have a trip we can combine this into? */
- if (lastdive && dive->when < lastdive->when + TRIP_THRESHOLD) {
- dive_trip_t *trip = lastdive->divetrip;
- add_dive_to_trip(dive, trip);
+ /* We found a dive, let's see if we have to allocate a new trip */
+ if (!lastdive || dive->when >= lastdive->when + TRIP_THRESHOLD) {
+ /* allocate new trip */
+ trip = create_trip_from_dive(dive);
+ trip->autogen = true;
+ *allocated = true;
+ } else {
+ /* use trip of previous dive */
+ trip = lastdive->divetrip;
+ *allocated = false;
+ }
+
+ // Now, find all dives that will be added to this trip
+ lastdive = dive;
+ *from = i;
+ for (*to = *from + 1; (dive = get_dive(*to)) != NULL; (*to)++) {
+ if (dive->divetrip || !DIVE_NEEDS_TRIP(dive) ||
+ dive->when >= lastdive->when + TRIP_THRESHOLD)
+ break;
if (get_dive_location(dive) && !trip->location)
trip->location = copy_string(get_dive_location(dive));
lastdive = dive;
- continue;
}
-
- lastdive = dive;
- trip = create_and_hookup_trip_from_dive(dive);
- trip->autogen = 1;
+ return trip;
}
+ /* Did not find anyhting - mark as end */
+ return NULL;
+}
+
+/*
+ * Walk the dives from the oldest dive, and see if we can autogroup them
+ */
+void autogroup_dives(void)
+{
+ int from, to;
+ dive_trip_t *trip;
+ int i, j;
+ bool alloc;
+
+ for(i = 0; (trip = get_dives_to_autogroup(i, &from, &to, &alloc)) != NULL; i = to) {
+ /* If this was newly allocated, add trip to list */
+ if (alloc)
+ insert_trip(&trip);
+ for (j = from; j < to; ++j)
+ add_dive_to_trip(get_dive(j), trip);
+ }
#ifdef DEBUG_TRIP
dump_trip_list();
#endif
@@ -1209,6 +1268,26 @@ void combine_trips(struct dive_trip *trip_a, struct dive_trip *trip_b)
add_dive_to_trip(trip_b->dives, trip_a);
}
+/* Out of two strings, copy the string that is not empty (if any). */
+static char *copy_non_empty_string(const char *a, const char *b)
+{
+ return copy_string(empty_string(b) ? a : b);
+}
+
+/* Combine trips new. This combines two trips, generating a
+ * new trip. To support undo, we have to preserve the old trips. */
+dive_trip_t *combine_trips_create(struct dive_trip *trip_a, struct dive_trip *trip_b)
+{
+ dive_trip_t *trip;
+
+ trip = alloc_trip();
+ trip->when = trip_a->when;
+ trip->location = copy_non_empty_string(trip_a->location, trip_b->location);
+ trip->notes = copy_non_empty_string(trip_a->notes, trip_b->notes);
+
+ return trip;
+}
+
void mark_divelist_changed(bool changed)
{
if (dive_list_changed == changed)