summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--dive.c160
-rw-r--r--dive.h69
-rw-r--r--divelist.c7
-rw-r--r--main.cpp1
-rw-r--r--parse-xml.c59
-rw-r--r--save-xml.c26
-rw-r--r--statistics.c9
7 files changed, 265 insertions, 66 deletions
diff --git a/dive.c b/dive.c
index a98b10412..d2cda168d 100644
--- a/dive.c
+++ b/dive.c
@@ -6,6 +6,8 @@
#include "gettext.h"
#include "dive.h"
+struct tag_entry *g_tag_list = NULL;
+
void add_event(struct divecomputer *dc, int time, int type, int flags, int value, const char *name)
{
struct event *ev, **p;
@@ -189,6 +191,7 @@ struct dive *alloc_dive(void)
if (!dive)
exit(1);
memset(dive, 0, sizeof(*dive));
+ taglist_init(&(dive->tag_list));
return dive;
}
@@ -1813,6 +1816,161 @@ static void join_dive_computers(struct divecomputer *res, struct divecomputer *a
remove_redundant_dc(res, prefer_downloaded);
}
+int taglist_get_tagstring(struct tag_entry *tag_list, char *buffer, int len) {
+ int i = 0;
+ struct tag_entry *tmp;
+ tmp = tag_list->next;
+ memset(buffer, 0, len);
+ while(tmp != NULL) {
+ int newlength = strlen(tmp->tag->name);
+ if (i > 0)
+ newlength += 2;
+ if ((i+newlength) < len) {
+ if (i > 0) {
+ strcpy(buffer+i, ", ");
+ strcpy(buffer+i+2, tmp->tag->name);
+ } else {
+ strcpy(buffer, tmp->tag->name);
+ }
+ } else {
+ return i;
+ }
+ i += newlength;
+ tmp = tmp->next;
+ }
+ return i;
+}
+
+struct divetag *taglist_get_tag(struct tag_entry *tag_list, const char *tag)
+{
+ struct tag_entry *tmp;
+ tmp = tag_list->next;
+ while(tmp != NULL) {
+ if (tmp->tag != NULL)
+ if (strcmp(tmp->tag->name, tag) == 0)
+ return tmp->tag;
+ else
+ tmp = tmp->next;
+ }
+ return NULL;
+}
+
+static inline void taglist_free_divetag(struct divetag *tag) {
+ if (tag->name != NULL)
+ free(tag->name);
+ if (tag->source != NULL)
+ free(tag->source);
+ free(tag);
+}
+
+/* Add a tag to the tag_list, keep the list sorted */
+static struct divetag *taglist_add_divetag(struct tag_entry *tag_list, struct divetag *tag)
+{
+ struct tag_entry *tmp, *last;
+ last = tag_list;
+ tmp = tag_list->next;
+ while(1) {
+ if (tmp == NULL || strcmp(tmp->tag->name, tag->name) > 0) {
+ /* Insert in front of it */
+ last->next = malloc(sizeof(struct tag_entry));
+ last->next->next = tmp;
+ last->next->tag = tag;
+ return last->next->tag;
+ } else if (strcmp(tmp->tag->name, tag->name) == 0) {
+ /* Already in list */
+ return tmp->tag;
+ } else {
+ last = tmp;
+ tmp = tmp->next;
+ }
+ }
+}
+
+struct divetag *taglist_add_tag(struct tag_entry *tag_list, const char *tag)
+{
+ struct divetag *ret_tag, *new_tag;
+ const char *translation;
+ new_tag = malloc(sizeof(struct divetag));
+
+ translation = translate("gettextFromC", tag);
+ if (strcmp(tag, translation) == 0) {
+ new_tag->source = NULL;
+ new_tag->name = malloc(strlen(tag)+1);
+ memcpy(new_tag->name, tag, strlen(tag)+1);
+ } else {
+ new_tag->name = malloc(strlen(translation)+1);
+ memcpy(new_tag->name, translation, strlen(translation)+1);
+ new_tag->source = malloc(strlen(tag)+1);
+ memcpy(new_tag->source, tag, strlen(tag)+1);
+ }
+ /* Try to insert new_tag into g_tag_list if we are not operating on it */
+ if (tag_list != g_tag_list) {
+ ret_tag = taglist_add_divetag(g_tag_list, new_tag);
+ /* g_tag_list already contains new_tag, free the duplicate */
+ if (ret_tag != new_tag)
+ taglist_free_divetag(new_tag);
+ ret_tag = taglist_add_divetag(tag_list, ret_tag);
+ } else {
+ ret_tag = taglist_add_divetag(tag_list, new_tag);
+ if (ret_tag != new_tag)
+ taglist_free_divetag(new_tag);
+ }
+ return ret_tag;
+}
+
+void taglist_init(struct tag_entry **tag_list) {
+ *tag_list = malloc(sizeof(struct tag_entry));
+ (*tag_list)->next = NULL;
+ (*tag_list)->tag = NULL;
+}
+
+/* Clear everything but the first element */
+void taglist_clear(struct tag_entry *tag_list) {
+ struct tag_entry *current_tag_entry, *next;
+ current_tag_entry = tag_list->next;
+ while (current_tag_entry != NULL) {
+ next = current_tag_entry->next;
+ free(current_tag_entry);
+ current_tag_entry = next;
+ }
+ tag_list->next = NULL;
+}
+
+/* Merge src1 and src2, write to *dst */
+static void taglist_merge(struct tag_entry *dst, struct tag_entry *src1, struct tag_entry *src2)
+{
+ struct tag_entry *current_tag_entry;
+ current_tag_entry = src1->next;
+ while (current_tag_entry != NULL) {
+ taglist_add_divetag(dst, current_tag_entry->tag);
+ current_tag_entry = current_tag_entry->next;
+ }
+ current_tag_entry = src2->next;
+ while (current_tag_entry != NULL) {
+ taglist_add_divetag(dst, current_tag_entry->tag);
+ current_tag_entry = current_tag_entry->next;
+ }
+}
+
+void taglist_init_global()
+{
+ int i;
+ const char* default_tags[] = {
+ QT_TRANSLATE_NOOP("gettextFromC", "boat"), QT_TRANSLATE_NOOP("gettextFromC", "shore"), QT_TRANSLATE_NOOP("gettextFromC", "drift"),
+ QT_TRANSLATE_NOOP("gettextFromC", "deep"), QT_TRANSLATE_NOOP("gettextFromC", "cavern") , QT_TRANSLATE_NOOP("gettextFromC", "ice"),
+ QT_TRANSLATE_NOOP("gettextFromC", "wreck"), QT_TRANSLATE_NOOP("gettextFromC", "cave"), QT_TRANSLATE_NOOP("gettextFromC", "altitude"),
+ QT_TRANSLATE_NOOP("gettextFromC", "pool"), QT_TRANSLATE_NOOP("gettextFromC", "lake"), QT_TRANSLATE_NOOP("gettextFromC", "river"),
+ QT_TRANSLATE_NOOP("gettextFromC", "night"), QT_TRANSLATE_NOOP("gettextFromC", "fresh"), QT_TRANSLATE_NOOP("gettextFromC", "student"),
+ QT_TRANSLATE_NOOP("gettextFromC", "instructor"), QT_TRANSLATE_NOOP("gettextFromC", "photo"), QT_TRANSLATE_NOOP("gettextFromC", "video"),
+ QT_TRANSLATE_NOOP("gettextFromC", "deco")
+ };
+
+ taglist_init(&g_tag_list);
+
+ for(i=0; i<sizeof(default_tags)/sizeof(char*); i++)
+ taglist_add_tag(g_tag_list, default_tags[i]);
+}
+
struct dive *merge_dives(struct dive *a, struct dive *b, int offset, bool prefer_downloaded)
{
struct dive *res = alloc_dive();
@@ -1841,7 +1999,7 @@ struct dive *merge_dives(struct dive *a, struct dive *b, int offset, bool prefer
MERGE_MAX(res, a, b, number);
MERGE_NONZERO(res, a, b, cns);
MERGE_NONZERO(res, a, b, visibility);
- MERGE_NONZERO(res, a, b, dive_tags);
+ taglist_merge(res->tag_list, a->tag_list, b->tag_list);
merge_equipment(res, a, b);
merge_airtemps(res, a, b);
if (dl) {
diff --git a/dive.h b/dive.h
index 3724cef29..89ea73df3 100644
--- a/dive.h
+++ b/dive.h
@@ -59,34 +59,6 @@ typedef int bool;
#define SEAWATER_SALINITY 10300
#define FRESHWATER_SALINITY 10000
-/* Dive tag definitions */
-#define DTAG_INVALID (1 << 0)
-#define DTAG_BOAT (1 << 1)
-#define DTAG_SHORE (1 << 2)
-#define DTAG_DRIFT (1 << 3)
-#define DTAG_DEEP (1 << 4)
-#define DTAG_CAVERN (1 << 5)
-#define DTAG_ICE (1 << 6)
-#define DTAG_WRECK (1 << 7)
-#define DTAG_CAVE (1 << 8)
-#define DTAG_ALTITUDE (1 << 9)
-#define DTAG_POOL (1 << 10)
-#define DTAG_LAKE (1 << 11)
-#define DTAG_RIVER (1 << 12)
-#define DTAG_NIGHT (1 << 13)
-#define DTAG_FRESH (1 << 14)
-#define DTAG_FRESH_NR 14
-#define DTAG_STUDENT (1 << 15)
-#define DTAG_INSTRUCTOR (1 << 16)
-#define DTAG_PHOTO (1 << 17)
-#define DTAG_VIDEO (1 << 18)
-#define DTAG_DECO (1 << 19)
-#define DTAG_NR 20
-/* defined in statistics.c */
-extern char *dtag_names[DTAG_NR];
-extern int dtag_shown[DTAG_NR];
-extern int dive_mask;
-
/*
* Some silly typedefs to make our units very explicit.
*
@@ -309,6 +281,45 @@ struct sample {
int po2;
};
+struct divetag {
+ /*
+ * The name of the divetag. If a translation is available, name contains
+ * the translated tag
+ */
+ char *name;
+ /*
+ * If a translation is available, we write the original tag to source.
+ * This enables us to write a non-localized tag to the xml file.
+ */
+ char *source;
+};
+
+struct tag_entry {
+ struct divetag *tag;
+ struct tag_entry *next;
+};
+
+/*
+ * divetags are only stored once, each dive only contains
+ * a list of tag_entries which then point to the divetags
+ * in the global g_tag_list
+ */
+
+extern struct tag_entry *g_tag_list;
+
+struct divetag *taglist_add_tag(struct tag_entry *tag_list, const char *tag);
+
+/*
+ * Writes all divetags in tag_list to buffer, limited by the buffer's (len)gth.
+ * Returns the characters written
+ */
+int taglist_get_tagstring(struct tag_entry *tag_list, char *buffer, int len);
+
+void taglist_init(struct tag_entry **tag_list);
+void taglist_clear(struct tag_entry *tag_list);
+void taglist_init_global();
+
+
/*
* Events are currently pretty meaningless. This is
* just based on the random data that libdivecomputer
@@ -399,7 +410,7 @@ struct dive {
pressure_t surface_pressure;
duration_t duration;
int salinity; // kg per 10000 l
- int dive_tags;
+ struct tag_entry *tag_list;
struct divecomputer dc;
};
diff --git a/divelist.c b/divelist.c
index 858d61533..28d082029 100644
--- a/divelist.c
+++ b/divelist.c
@@ -735,6 +735,11 @@ void delete_single_dive(int idx)
free((void *)dive->buddy);
if (dive->suit)
free((void *)dive->suit);
+ if (dive->tag_list) {
+ taglist_clear(dive->tag_list);
+ /* Remove head of list */
+ free((void *)dive->tag_list);
+ }
free(dive);
}
@@ -800,8 +805,6 @@ void select_dive(int idx)
struct dive *dive = get_dive(idx);
if (dive) {
/* never select an invalid dive that isn't displayed */
- if (dive->dive_tags & DTAG_INVALID && !prefs.display_invalid_dives)
- return;
if (!dive->selected) {
dive->selected = 1;
amount_selected++;
diff --git a/main.cpp b/main.cpp
index 72a6cc585..dddd40d35 100644
--- a/main.cpp
+++ b/main.cpp
@@ -24,6 +24,7 @@ int main(int argc, char **argv)
init_ui(&argc, &argv);
parse_xml_init();
+ taglist_init_global();
QStringList files;
QStringList importedFiles;
diff --git a/parse-xml.c b/parse-xml.c
index 8e1a052a9..5042f9161 100644
--- a/parse-xml.c
+++ b/parse-xml.c
@@ -210,26 +210,53 @@ static void divedatetime(char *buffer, void *_when)
}
}
+enum ParseState {FINDSTART, FINDEND};
static void divetags(char *buffer, void *_tags)
{
- int *tags = _tags;
- int i;
-
- for (i = 0; i < DTAG_NR; i++) {
- if (strstr(buffer, dtag_names[i])) {
- /* stupidly we have 'cave' and 'cavern' */
- if (1 << i == DTAG_CAVE) {
- char *cave = strstr(buffer, "cave");
- while (cave && !strncmp(cave, "cavern", strlen("cavern"))) {
- cave++;
- cave = strstr(cave, "cave");
+ struct tag_entry *tags = _tags;
+ char tag[128];
+ int i = 0, start = 0, end = 0;
+ enum ParseState state = FINDEND;
+ i=0;
+ while(i < strlen(buffer)) {
+ if (buffer[i] == ',') {
+ if (state == FINDSTART) {
+ /* Detect empty tags */
+ } else if (state == FINDEND) {
+ /* Found end of tag */
+ if (i > 1) {
+ if(buffer[i-1] != '\\') {
+ strncpy(tag, buffer+start, end-start+1);
+ tag[end-start+1] = '\0';
+ state=FINDSTART;
+ taglist_add_tag(tags, tag);
+ }
+ } else {
+ state=FINDSTART;
}
- if (!cave)
- continue;
}
- *tags |= (1 << i);
+ } else if (buffer[i] == ' ') {
+ /* Handled */
+ } else {
+ /* Found start of tag */
+ if (state == FINDSTART) {
+ state = FINDEND;
+ start = i;
+ } else if (state == FINDEND) {
+ end=i;
+ }
}
- }
+ i++;
+ }
+ if (state == FINDEND) {
+ if (end < start)
+ end = strlen(buffer)-1;
+ if (strlen(buffer) > 0) {
+ strncpy(tag, buffer+start, end-start+1);
+ tag[end-start+1] = '\0';
+ taglist_add_tag(tags, tag);
+ }
+ }
}
enum number_type {
@@ -1161,7 +1188,7 @@ static void try_to_fill_dive(struct dive *dive, const char *name, char *buf)
if (MATCH(".number", get_index, &dive->number))
return;
- if (MATCH(".tags", divetags, &dive->dive_tags))
+ if (MATCH(".tags", divetags, dive->tag_list))
return;
if (MATCH(".tripflag", get_tripflag, &dive->tripflag))
return;
diff --git a/save-xml.c b/save-xml.c
index ab81c1590..5b0ef42ec 100644
--- a/save-xml.c
+++ b/save-xml.c
@@ -392,20 +392,28 @@ static void save_events(FILE *f, struct event *ev)
}
}
-static void save_tags(FILE *f, int tags)
+static void save_tags(FILE *f, struct tag_entry *tag_list)
{
- int i, more = 0;
+ int more = 0;
+ struct tag_entry *tmp = tag_list->next;
- fprintf(f, " tags='");
- for (i = 0; i < DTAG_NR; i++) {
- if (tags & (1 << i)) {
+ /* Only write tag attribute if the list contains at least one item */
+ if (tmp != NULL) {
+ fprintf(f, " tags='");
+
+ while (tmp != NULL) {
if (more)
fprintf(f, ", ");
- fprintf(f, "%s", dtag_names[i]);
+ /* If the tag has been translated, write the source to the xml file */
+ if (tmp->tag->source != NULL)
+ fprintf(f, "%s", tmp->tag->source);
+ else
+ fprintf(f, "%s", tmp->tag->name);
+ tmp = tmp->next;
more = 1;
}
+ fprintf(f, "'");
}
- fprintf(f, "'");
}
static void show_date(FILE *f, timestamp_t when)
@@ -468,8 +476,8 @@ void save_dive(FILE *f, struct dive *dive)
fprintf(f, " rating='%d'", dive->rating);
if (dive->visibility)
fprintf(f, " visibility='%d'", dive->visibility);
- if (dive->dive_tags)
- save_tags(f, dive->dive_tags);
+ if (dive->tag_list != NULL)
+ save_tags(f, dive->tag_list);
show_date(f, dive->when);
fprintf(f, " duration='%u:%02u min'>\n",
diff --git a/statistics.c b/statistics.c
index 5aecd1bfe..a151aee27 100644
--- a/statistics.c
+++ b/statistics.c
@@ -15,15 +15,6 @@
#include "divelist.h"
#include "statistics.h"
-/* mark for translation but don't translate here as these terms are used
- * in save-xml.c */
-char *dtag_names[DTAG_NR] = {
- QT_TRANSLATE_NOOP("gettextFromC","invalid"), QT_TRANSLATE_NOOP("gettextFromC","boat"), QT_TRANSLATE_NOOP("gettextFromC","shore"), QT_TRANSLATE_NOOP("gettextFromC","drift"), QT_TRANSLATE_NOOP("gettextFromC","deep"), QT_TRANSLATE_NOOP("gettextFromC","cavern"),
- QT_TRANSLATE_NOOP("gettextFromC","ice"), QT_TRANSLATE_NOOP("gettextFromC","wreck"), QT_TRANSLATE_NOOP("gettextFromC","cave"), QT_TRANSLATE_NOOP("gettextFromC","altitude"), QT_TRANSLATE_NOOP("gettextFromC","pool"), QT_TRANSLATE_NOOP("gettextFromC","lake"),
- QT_TRANSLATE_NOOP("gettextFromC","river"), QT_TRANSLATE_NOOP("gettextFromC","night"), QT_TRANSLATE_NOOP("gettextFromC","freshwater"), QT_TRANSLATE_NOOP("gettextFromC","training"), QT_TRANSLATE_NOOP("gettextFromC","teaching"),
- QT_TRANSLATE_NOOP("gettextFromC","photo"), QT_TRANSLATE_NOOP("gettextFromC","video"), QT_TRANSLATE_NOOP("gettextFromC","deco")
-};
-
static stats_t stats;
stats_t stats_selection;
stats_t *stats_monthly = NULL;