summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/dive.h10
-rw-r--r--core/divelist.c134
-rw-r--r--core/save-git.c4
-rw-r--r--core/save-html.c4
-rw-r--r--core/save-xml.c4
-rw-r--r--desktop-widgets/command_divelist.cpp10
-rw-r--r--mobile-widgets/qmlmanager.cpp1
7 files changed, 89 insertions, 78 deletions
diff --git a/core/dive.h b/core/dive.h
index a6210810d..d0666f724 100644
--- a/core/dive.h
+++ b/core/dive.h
@@ -286,11 +286,13 @@ typedef struct dive_trip
/* Used by the io-routines to mark trips that have already been written. */
bool saved;
bool autogen;
- struct dive_trip *next;
} dive_trip_t;
-/* List of dive trips (sorted by date) */
-extern dive_trip_t *dive_trip_list;
+struct trip_table {
+ int nr, allocated;
+ struct dive_trip **trips;
+};
+
struct picture;
struct dive {
int number;
@@ -420,6 +422,7 @@ extern const struct units *get_units(void);
extern int run_survey, verbose, quit, force_root;
extern struct dive_table dive_table;
+extern struct trip_table trip_table;
extern struct dive displayed_dive;
extern unsigned int dc_number;
extern struct dive *current_dive;
@@ -543,6 +546,7 @@ extern bool dive_less_than(const struct dive *a, const struct dive *b);
extern bool trip_less_than(const struct dive_trip *a, const struct dive_trip *b);
extern bool dive_or_trip_less_than(struct dive_or_trip a, struct dive_or_trip b);
extern void sort_dive_table(struct dive_table *table);
+extern void sort_trip_table(struct trip_table *table);
extern struct dive *fixup_dive(struct dive *dive);
extern void fixup_dc_duration(struct divecomputer *dc);
extern int dive_getUniqID();
diff --git a/core/divelist.c b/core/divelist.c
index 100266eb1..fbad84981 100644
--- a/core/divelist.c
+++ b/core/divelist.c
@@ -3,10 +3,10 @@
/* core logic for the dive list -
* accessed through the following interfaces:
*
- * void process_loaded_dives();
- * void process_imported_dives(bool prefer_imported);
- * dive_trip_t *dive_trip_list;
- * unsigned int amount_selected;
+ * struct trip_table trip_table
+ * void process_loaded_dives()
+ * void process_imported_dives(bool prefer_imported)
+ * unsigned int amount_selected
* void dump_selection(void)
* void get_dive_gas(const struct dive *dive, int *o2_p, int *he_p, int *o2low_p)
* char *get_dive_gas_string(const struct dive *dive)
@@ -38,6 +38,7 @@
* bool trip_less_than(const struct dive_trip *a, const struct dive_trip *b)
* bool dive_or_trip_less_than(struct dive_or_trip a, struct dive_or_trip b)
* void sort_dive_table(struct dive_table *table)
+ * void sort_trip_table(struct trip_table *table)
* bool is_trip_before_after(const struct dive *dive, bool before)
* void delete_dive_from_table(struct dive_table *table, int idx)
* int find_next_visible_dive(timestamp_t when);
@@ -69,7 +70,7 @@ static bool dive_list_changed = false;
bool autogroup = false;
-dive_trip_t *dive_trip_list;
+struct trip_table trip_table;
unsigned int amount_selected;
@@ -748,14 +749,15 @@ void dump_trip_list(void)
int i = 0;
timestamp_t last_time = 0;
- for (trip = dive_trip_list; trip; trip = trip->next) {
+ for (i = 0; i < trip_table.nr; ++i) {
struct tm tm;
+ trip = trip_table.trips[i];
utc_mkdate(trip_date(trip), &tm);
if (trip_date(trip) < last_time)
- printf("\n\ndive_trip_list OUT OF ORDER!!!\n\n\n");
+ printf("\n\ntrip_table OUT OF ORDER!!!\n\n\n");
printf("%s trip %d to \"%s\" on %04u-%02u-%02u %02u:%02u:%02u (%d dives - %p)\n",
trip->autogen ? "autogen " : "",
- ++i, trip->location,
+ i + 1, trip->location,
tm.tm_year, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec,
trip->dives.nr, trip);
last_time = trip_date(trip);
@@ -764,23 +766,6 @@ void dump_trip_list(void)
}
#endif
-/* insert the trip into the dive_trip_list */
-void insert_trip(dive_trip_t *dive_trip)
-{
- dive_trip_t **p = &dive_trip_list;
- dive_trip_t *trip;
-
- /* Walk the dive trip list looking for the right location.. */
- while ((trip = *p) != NULL && trip_less_than(trip, dive_trip))
- p = &trip->next;
-
- dive_trip->next = trip;
- *p = dive_trip;
-#ifdef DEBUG_TRIP
- dump_trip_list();
-#endif
-}
-
/* free resources associated with a trip structure */
void free_trip(dive_trip_t *trip)
{
@@ -791,32 +776,6 @@ void free_trip(dive_trip_t *trip)
}
}
-/* remove trip from the trip-list, but don't free its memory.
- * caller takes ownership of the trip. */
-void unregister_trip(dive_trip_t *trip)
-{
- dive_trip_t **p, *tmp;
-
- assert(!trip->dives.nr);
-
- /* Remove the trip from the list of trips */
- p = &dive_trip_list;
- while ((tmp = *p) != NULL) {
- if (tmp == trip) {
- *p = trip->next;
- break;
- }
- p = &tmp->next;
- }
-}
-
-static void delete_trip(dive_trip_t *trip)
-{
- unregister_trip(trip);
- free_trip(trip);
-}
-
-
timestamp_t trip_date(const struct dive_trip *trip)
{
if (!trip || trip->dives.nr == 0)
@@ -902,6 +861,18 @@ static int comp_dives(const struct dive *a, const struct dive *b)
return 0; /* this should not happen for a != b */
}
+/* Trips are compared according to the first dive in the trip. */
+static int comp_trips(const struct dive_trip *a, const struct dive_trip *b)
+{
+ /* This should never happen, nevertheless don't crash on trips
+ * with no (or worse a negative number of) dives. */
+ if (a->dives.nr <= 0)
+ return b->dives.nr <= 0 ? 0 : -1;
+ if (b->dives.nr <= 0)
+ return 1;
+ return comp_dives(a->dives.dives[0], b->dives.dives[0]);
+}
+
#define MAKE_GROW_TABLE(table_type, item_type, array_name) \
item_type *grow_##table_type(struct table_type *table) \
{ \
@@ -920,6 +891,7 @@ static int comp_dives(const struct dive *a, const struct dive *b)
}
MAKE_GROW_TABLE(dive_table, struct dive *, dives)
+static MAKE_GROW_TABLE(trip_table, struct dive_trip *, trips)
/* get the index where we want to insert an object so that everything stays
* ordered according to a comparison function() */
@@ -935,6 +907,7 @@ MAKE_GROW_TABLE(dive_table, struct dive *, dives)
}
MAKE_GET_INSERTION_INDEX(dive_table, struct dive *, dives, dive_less_than)
+static MAKE_GET_INSERTION_INDEX(trip_table, struct dive_trip *, trips, trip_less_than)
/* add object at the given index to a table. */
#define MAKE_ADD_TO(table_type, item_type, array_name) \
@@ -952,6 +925,7 @@ MAKE_GET_INSERTION_INDEX(dive_table, struct dive *, dives, dive_less_than)
}
static MAKE_ADD_TO(dive_table, struct dive *, dives)
+static MAKE_ADD_TO(trip_table, struct dive_trip *, trips)
#define MAKE_REMOVE_FROM(table_type, array_name) \
void remove_from_##table_type(struct table_type *table, int idx) \
@@ -963,6 +937,7 @@ static MAKE_ADD_TO(dive_table, struct dive *, dives)
}
static MAKE_REMOVE_FROM(dive_table, dives)
+static MAKE_REMOVE_FROM(trip_table, trips)
#define MAKE_GET_IDX(table_type, item_type, array_name) \
int get_idx_in_##table_type(const struct table_type *table, const item_type item) \
@@ -975,6 +950,7 @@ static MAKE_REMOVE_FROM(dive_table, dives)
}
static MAKE_GET_IDX(dive_table, struct dive *, dives)
+static MAKE_GET_IDX(trip_table, struct dive_trip *, trips)
#define MAKE_SORT(table_type, item_type, array_name, fun) \
static int sortfn_##table_type(const void *_a, const void *_b) \
@@ -990,6 +966,7 @@ static MAKE_GET_IDX(dive_table, struct dive *, dives)
}
MAKE_SORT(dive_table, struct dive *, dives, comp_dives)
+MAKE_SORT(trip_table, struct dive_trip *, trips, comp_trips)
/* remove a dive from the trip it's associated to, but don't delete the
* trip if this was the last dive in the trip. the caller is responsible
@@ -1010,6 +987,12 @@ struct dive_trip *unregister_dive_from_trip(struct dive *dive)
return trip;
}
+static void delete_trip(dive_trip_t *trip)
+{
+ unregister_trip(trip);
+ free_trip(trip);
+}
+
void remove_dive_from_trip(struct dive *dive)
{
struct dive_trip *trip = unregister_dive_from_trip(dive);
@@ -1036,6 +1019,16 @@ dive_trip_t *alloc_trip(void)
return calloc(1, sizeof(dive_trip_t));
}
+/* insert the trip into the trip table */
+void insert_trip(dive_trip_t *dive_trip)
+{
+ int idx = trip_table_get_insertion_index(&trip_table, dive_trip);
+ add_to_trip_table(&trip_table, idx, dive_trip);
+#ifdef DEBUG_TRIP
+ dump_trip_list();
+#endif
+}
+
dive_trip_t *create_trip_from_dive(struct dive *dive)
{
dive_trip_t *trip;
@@ -1051,12 +1044,22 @@ dive_trip_t *create_and_hookup_trip_from_dive(struct dive *dive)
dive_trip_t *dive_trip = alloc_trip();
dive_trip = create_trip_from_dive(dive);
- insert_trip(dive_trip);
add_dive_to_trip(dive, dive_trip);
+ insert_trip(dive_trip);
return dive_trip;
}
+/* remove trip from the trip-list, but don't free its memory.
+ * caller takes ownership of the trip. */
+void unregister_trip(dive_trip_t *trip)
+{
+ int idx = get_idx_in_trip_table(&trip_table, trip);
+ assert(!trip->dives.nr);
+ if (idx >= 0)
+ remove_from_trip_table(&trip_table, idx);
+}
+
/*
* Find a trip a new dive should be autogrouped with. If no such trips
* exist, allocate a new trip. The bool "*allocated" is set to true
@@ -1153,7 +1156,7 @@ dive_trip_t *get_dives_to_autogroup(struct dive_table *table, int start, int *fr
}
/*
- * Walk the dives from the oldest dive in the given tabe, and see if we
+ * Walk the dives from the oldest dive in the given table, and see if we
* can autogroup them. But only do this when the user selected autogrouping.
*/
static void autogroup_dives(struct dive_table *table)
@@ -1167,12 +1170,13 @@ static void autogroup_dives(struct dive_table *table)
return;
for (i = 0; (trip = get_dives_to_autogroup(&dive_table, i, &from, &to, &alloc)) != NULL; i = to) {
+ for (j = from; j < to; ++j)
+ add_dive_to_trip(get_dive(j), trip);
/* 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);
}
+ sort_trip_table(&trip_table);
#ifdef DEBUG_TRIP
dump_trip_list();
#endif
@@ -1423,6 +1427,7 @@ void process_loaded_dives()
set_dc_nickname(dive);
sort_dive_table(&dive_table);
+ sort_trip_table(&trip_table);
/* Autogroup dives if desired by user. */
autogroup_dives(&dive_table);
@@ -1577,6 +1582,9 @@ void process_imported_dives(struct dive_table *import_table, bool prefer_importe
/* Autogroup dives if desired by user. */
autogroup_dives(&dive_table);
+ /* Trips may have changed - make sure that they are still ordered */
+ sort_trip_table(&trip_table);
+
/* We might have deleted the old selected dive.
* Choose the newest dive as selected (if any) */
current_dive = dive_table.nr > 0 ? dive_table.dives[dive_table.nr - 1] : NULL;
@@ -1660,6 +1668,10 @@ void clear_dive_file_data()
delete_single_dive(0);
while (dive_site_table.nr)
delete_dive_site(get_dive_site(0));
+ if (trip_table.nr != 0) {
+ fprintf(stderr, "Warning: trip table not empty in clear_dive_file_data()!\n");
+ trip_table.nr = 0;
+ }
clear_dive(&displayed_dive);
@@ -1682,18 +1694,6 @@ bool dive_less_than(const struct dive *a, const struct dive *b)
return comp_dives(a, b) < 0;
}
-/* Trips are compared according to the first dive in the trip. */
-static int comp_trips(const struct dive_trip *a, const struct dive_trip *b)
-{
- /* This should never happen, nevertheless don't crash on trips
- * with no (or worse a negative number of) dives. */
- if (a->dives.nr <= 0)
- return b->dives.nr <= 0 ? 0 : -1;
- if (b->dives.nr <= 0)
- return 1;
- return comp_dives(a->dives.dives[0], b->dives.dives[0]);
-}
-
bool trip_less_than(const struct dive_trip *a, const struct dive_trip *b)
{
return comp_trips(a, b) < 0;
diff --git a/core/save-git.c b/core/save-git.c
index cdc0ca980..33c01ab83 100644
--- a/core/save-git.c
+++ b/core/save-git.c
@@ -930,8 +930,8 @@ static int create_git_tree(git_repository *repo, struct dir *root, bool select_o
save_divesites(repo, root);
- for (trip = dive_trip_list; trip != NULL; trip = trip->next)
- trip->saved = 0;
+ for (i = 0; i < trip_table.nr; ++i)
+ trip_table.trips[i]->saved = 0;
/* save the dives */
git_storage_update_progress(translate("gettextFromC", "Start saving dives"));
diff --git a/core/save-html.c b/core/save-html.c
index ec5751453..aeb74bf95 100644
--- a/core/save-html.c
+++ b/core/save-html.c
@@ -439,8 +439,8 @@ void write_trips(struct membuffer *b, const char *photos_dir, bool selected_only
char sep_ = ' ';
char *sep = &sep_;
- for (trip = dive_trip_list; trip != NULL; trip = trip->next)
- trip->saved = 0;
+ for (i = 0; i < trip_table.nr; ++i)
+ trip_table.trips[i]->saved = 0;
for_each_dive (i, dive) {
trip = dive->divetrip;
diff --git a/core/save-xml.c b/core/save-xml.c
index e49e186f4..cae18f8c7 100644
--- a/core/save-xml.c
+++ b/core/save-xml.c
@@ -637,8 +637,8 @@ void save_dives_buffer(struct membuffer *b, const bool select_only, bool anonymi
put_format(b, "</site>\n");
}
put_format(b, "</divesites>\n<dives>\n");
- for (trip = dive_trip_list; trip != NULL; trip = trip->next)
- trip->saved = 0;
+ for (i = 0; i < trip_table.nr; ++i)
+ trip_table.trips[i]->saved = 0;
/* save the dives */
for_each_dive(i, dive) {
diff --git a/desktop-widgets/command_divelist.cpp b/desktop-widgets/command_divelist.cpp
index 5e3f30ce2..b3c4f24e3 100644
--- a/desktop-widgets/command_divelist.cpp
+++ b/desktop-widgets/command_divelist.cpp
@@ -81,10 +81,10 @@ DiveToAdd DiveListBase::removeDive(struct dive *d)
// Returns pointer to added dive (which is owned by the backend!)
dive *DiveListBase::addDive(DiveToAdd &d)
{
- if (d.tripToAdd)
- insert_trip(d.tripToAdd.release()); // Return ownership to backend
if (d.trip)
add_dive_to_trip(d.dive.get(), d.trip);
+ if (d.tripToAdd)
+ insert_trip(d.tripToAdd.release()); // Return ownership to backend
dive *res = d.dive.release(); // Give up ownership of dive
// Set the filter flag according to current filter settings
@@ -530,6 +530,7 @@ void AddDive::redoit()
currentDive = current_dive;
divesToRemove = addDives(divesToAdd);
+ sort_trip_table(&trip_table); // Though unlikely, adding a dive may reorder trips
mark_divelist_changed(true);
// Select the newly added dive
@@ -544,6 +545,7 @@ void AddDive::undoit()
{
// Simply remove the dive that was previously added...
divesToAdd = removeDives(divesToRemove);
+ sort_trip_table(&trip_table); // Though unlikely, removing a dive may reorder trips
// ...and restore the selection
restoreSelection(selection, currentDive);
@@ -566,6 +568,7 @@ bool DeleteDive::workToBeDone()
void DeleteDive::undoit()
{
divesToDelete = addDives(divesToAdd);
+ sort_trip_table(&trip_table); // Though unlikely, removing a dive may reorder trips
mark_divelist_changed(true);
// Select all re-added dives and make the first one current
@@ -576,6 +579,7 @@ void DeleteDive::undoit()
void DeleteDive::redoit()
{
divesToAdd = removeDives(divesToDelete);
+ sort_trip_table(&trip_table); // Though unlikely, adding a dive may reorder trips
mark_divelist_changed(true);
// Deselect all dives and select dive that was close to the first deleted dive
@@ -604,6 +608,7 @@ void ShiftTime::redoit()
// Changing times may have unsorted the dive table
sort_dive_table(&dive_table);
+ sort_trip_table(&trip_table);
// We send one time changed signal per trip (see comments in DiveListNotifier.h).
// Therefore, collect all dives in an array and sort by trip.
@@ -667,6 +672,7 @@ bool TripBase::workToBeDone()
void TripBase::redoit()
{
moveDivesBetweenTrips(divesToMove);
+ sort_trip_table(&trip_table); // Though unlikely, moving dives may reorder trips
mark_divelist_changed(true);
}
diff --git a/mobile-widgets/qmlmanager.cpp b/mobile-widgets/qmlmanager.cpp
index cdcbedecf..75d44deb1 100644
--- a/mobile-widgets/qmlmanager.cpp
+++ b/mobile-widgets/qmlmanager.cpp
@@ -1131,6 +1131,7 @@ void QMLManager::commitChanges(QString diveId, QString date, QString location, Q
// we know that the only thing that might happen in a resort is that
// this one dive moves to a different spot in the dive list
sort_dive_table(&dive_table);
+ sort_trip_table(&trip_table);
int newIdx = get_idx_by_uniq_id(d->id);
if (newIdx != oldIdx) {
DiveListModel::instance()->removeDive(modelIdx);