diff options
Diffstat (limited to 'core')
-rw-r--r-- | core/divelist.c | 109 | ||||
-rw-r--r-- | core/divelist.h | 4 | ||||
-rw-r--r-- | core/load-git.c | 2 | ||||
-rw-r--r-- | core/parse.c | 2 |
4 files changed, 100 insertions, 17 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) diff --git a/core/divelist.h b/core/divelist.h index 2b2ee07a5..8bcf9f55c 100644 --- a/core/divelist.h +++ b/core/divelist.h @@ -28,7 +28,10 @@ extern int get_divenr(const struct dive *dive); extern int get_divesite_idx(const struct dive_site *ds); extern struct dive_trip *unregister_dive_from_trip(struct dive *dive, short was_autogen); extern void remove_dive_from_trip(struct dive *dive, short was_autogen); +extern dive_trip_t *alloc_trip(void); +extern dive_trip_t *create_trip_from_dive(struct dive *dive); extern dive_trip_t *create_and_hookup_trip_from_dive(struct dive *dive); +extern dive_trip_t *get_dives_to_autogroup(int start, int *from, int *to, bool *allocated); extern void autogroup_dives(void); extern struct dive *merge_two_dives(struct dive *a, struct dive *b); extern bool consecutive_selected(); @@ -38,6 +41,7 @@ extern void select_dives_in_trip(struct dive_trip *trip); extern void deselect_dives_in_trip(struct dive_trip *trip); extern void filter_dive(struct dive *d, bool shown); extern void combine_trips(struct dive_trip *trip_a, struct dive_trip *trip_b); +extern dive_trip_t *combine_trips_create(struct dive_trip *trip_a, struct dive_trip *trip_b); extern void find_new_trip_start_time(dive_trip_t *trip); extern struct dive *first_selected_dive(); extern struct dive *last_selected_dive(); diff --git a/core/load-git.c b/core/load-git.c index 66f4fd531..0abae4239 100644 --- a/core/load-git.c +++ b/core/load-git.c @@ -1208,7 +1208,7 @@ static struct dive *create_new_dive(timestamp_t when) static dive_trip_t *create_new_trip(int yyyy, int mm, int dd) { - dive_trip_t *trip = calloc(1, sizeof(dive_trip_t)); + dive_trip_t *trip = alloc_trip(); struct tm tm = { 0 }; /* We'll fill in the real data from the trip descriptor file */ diff --git a/core/parse.c b/core/parse.c index 46c041925..c8f3ae89a 100644 --- a/core/parse.c +++ b/core/parse.c @@ -282,7 +282,7 @@ void trip_start(void) if (cur_trip) return; dive_end(); - cur_trip = calloc(1, sizeof(dive_trip_t)); + cur_trip = alloc_trip(); memset(&cur_tm, 0, sizeof(cur_tm)); } |