diff options
-rw-r--r-- | dive.h | 4 | ||||
-rw-r--r-- | gtk-gui.c | 137 | ||||
-rw-r--r-- | main.c | 10 | ||||
-rw-r--r-- | parse-xml.c | 2 | ||||
-rw-r--r-- | profile.c | 5 | ||||
-rw-r--r-- | save-xml.c | 2 |
6 files changed, 158 insertions, 2 deletions
@@ -266,6 +266,7 @@ struct event { struct divecomputer { timestamp_t when; const char *model; + const char *nickname; uint32_t deviceid, diveid; int samples, alloc_samples; struct sample *sample; @@ -524,6 +525,9 @@ extern int edit_multi_dive_info(struct dive *single_dive); extern void dive_list_update_dives(void); extern void flush_divelist(struct dive *dive); +extern void set_dc_nickname(struct dive *dive); +extern void remember_dc(uint32_t deviceid, const char *nickname, gboolean change_conf); + #define DIVE_ERROR_PARSE 1 const char *weekday(int wday); @@ -39,6 +39,14 @@ struct preferences prefs = { FALSE }; +struct dcnicknamelist { + const char *nickname; + uint32_t deviceid; + struct dcnicknamelist *next; +}; +static struct dcnicknamelist *nicknamelist; +char *nicknamestring; + static GtkWidget *dive_profile; static const char *default_dive_computer_vendor; static const char *default_dive_computer_product; @@ -1178,6 +1186,33 @@ void init_ui(int *argcp, char ***argvp) default_dive_computer_vendor = subsurface_get_conf("dive_computer_vendor", PREF_STRING); default_dive_computer_product = subsurface_get_conf("dive_computer_product", PREF_STRING); default_dive_computer_device = subsurface_get_conf("dive_computer_device", PREF_STRING); + conf_value = subsurface_get_conf("dc_nicknames", PREF_STRING); + nicknamestring = strdup(""); + if (conf_value) { + char *next_token, *nickname; + uint32_t deviceid; + int len; + next_token = strdup(conf_value); + len = strlen(next_token); + while ((next_token = g_utf8_strchr(next_token, len, '{')) != NULL) { + /* replace the '{' so we keep looking in case any test fails */ + *next_token = '('; + /* the next 8 chars are the deviceid, after that we have the utf8 nickname */ + if (sscanf(next_token, "(%8x,", &deviceid) > 0) { + char *namestart, *nameend; + namestart = g_utf8_strchr(next_token, len, ','); + nameend = g_utf8_strchr(next_token, len, '}'); + if (!namestart || !nameend) + continue; + *nameend = '\0'; + nickname = strdup(namestart + 1); + remember_dc(deviceid, nickname, FALSE); + next_token = nameend + 1; + }; + } + free((void *)conf_value); + free(next_token); + } error_info_bar = NULL; win = gtk_window_new(GTK_WINDOW_TOPLEVEL); g_set_application_name ("subsurface"); @@ -1966,3 +2001,105 @@ void set_filename(const char *filename, gboolean force) else existing_filename = NULL; } + +static const char *get_dc_nickname(uint32_t deviceid) +{ + struct dcnicknamelist *known = nicknamelist; + while (known) { + if (known->deviceid == deviceid) + return known->nickname; + known = known->next; + } + return NULL; +} + +/* no curly braces or commas, please */ +static char *cleanedup_nickname(const char *nickname, int len) +{ + char *clean; + if (nickname) { + char *brace; + + if (!g_utf8_validate(nickname, -1, NULL)) + return strdup(""); + brace = clean = strdup(nickname); + while (*brace) { + if (*brace == '{') + *brace = '('; + else if (*brace == '}') + *brace = ')'; + else if (*brace == ',') + *brace = '.'; + brace = g_utf8_next_char(brace); + if (*brace && g_utf8_next_char(brace) - clean >= len) + *brace = '\0'; + } + } else { + clean = strdup(""); + } + return clean; +} + +void remember_dc(uint32_t deviceid, const char *nickname, gboolean change_conf) +{ + if (!get_dc_nickname(deviceid)) { + char buffer[80]; + struct dcnicknamelist *nn_entry = malloc(sizeof(struct dcnicknamelist)); + nn_entry->deviceid = deviceid; + /* make sure there are no curly braces or commas in the string and that + * it will fit in the buffer */ + nn_entry->nickname = cleanedup_nickname(nickname, sizeof(buffer) - 12); + nn_entry->next = nicknamelist; + nicknamelist = nn_entry; + snprintf(buffer, 80, "{%08x,%s}", deviceid, nn_entry->nickname); + nicknamestring = realloc(nicknamestring, strlen(nicknamestring) + strlen(buffer) + 1); + strcat(nicknamestring, buffer); + if (change_conf) + subsurface_set_conf("dc_nicknames", PREF_STRING, nicknamestring); + } +} + +void set_dc_nickname(struct dive *dive) +{ + GtkWidget *dialog, *vbox, *entry, *frame, *label; + char nickname[68]; + const char *name; + + if (!dive) + return; + + if ((name = get_dc_nickname(dive->dc.deviceid)) != NULL) { + dive->dc.nickname = strdup(name); + } else { + dialog = gtk_dialog_new_with_buttons( + _("Dive Computer Nickname"), + GTK_WINDOW(main_window), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + NULL); + vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog)); + label = gtk_label_new(_("Subsurface can use a nickname for your dive computer.\n" + "The default is the model and device ID as shown below.\n" + "If you don't want to name this dive computer click " + "'Cancel' and Subsurface will simply display its model " + "as nickname.")); + gtk_label_set_line_wrap(GTK_LABEL(label), TRUE); + gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, TRUE, 3); + frame = gtk_frame_new(_("Nickname")); + gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, TRUE, 3); + entry = gtk_entry_new(); + gtk_container_add(GTK_CONTAINER(frame), entry); + gtk_entry_set_max_length(GTK_ENTRY(entry), 68); + snprintf(nickname, 69, "%s (%08x)", dive->dc.model, dive->dc.deviceid); + gtk_entry_set_text(GTK_ENTRY(entry), nickname); + gtk_widget_show_all(dialog); + if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) { + if (strcmp(dive->dc.model, gtk_entry_get_text(GTK_ENTRY(entry)))) + dive->dc.nickname = cleanedup_nickname(gtk_entry_get_text(GTK_ENTRY(entry)), + sizeof(nickname)); + } + gtk_widget_destroy(dialog); + remember_dc(dive->dc.deviceid, dive->dc.nickname, TRUE); + } +} @@ -124,6 +124,16 @@ void report_dives(gboolean is_imported, gboolean prefer_imported) int preexisting = dive_table.preexisting; struct dive *last; + /* set the nickname for the divecomputer for newly downloaded dives */ + for (i = dive_table.preexisting; i < dive_table.nr; i++) + if (dive_table.dives[i]->downloaded) { + set_dc_nickname(dive_table.dives[i]); + } else { + struct divecomputer *dc = &dive_table.dives[i]->dc; + if (dc->nickname && *dc->nickname) + remember_dc(dc->deviceid, dc->nickname, TRUE); + } + /* This does the right thing for -1: NULL */ last = get_dive(preexisting-1); diff --git a/parse-xml.c b/parse-xml.c index 376860e6b..dd35379fb 100644 --- a/parse-xml.c +++ b/parse-xml.c @@ -625,6 +625,8 @@ static void try_to_fill_dc(struct divecomputer *dc, const char *name, char *buf) return; if (MATCH(".model", utf8_string, &dc->model)) return; + if (MATCH(".nickname", utf8_string, &dc->nickname)) + return; if (MATCH(".deviceid", hex_value, &dc->deviceid)) return; if (MATCH(".diveid", hex_value, &dc->diveid)) @@ -1857,9 +1857,10 @@ void plot(struct graphics_context *gc, struct dive *dive, scale_mode_t scale) cairo_stroke(gc->cr); /* Put the dive computer name in the lower left corner */ - if (dc->model) { + if (dc->nickname || dc->model) { static const text_render_options_t computer = {10, TIME_TEXT, LEFT, MIDDLE}; - plot_text(gc, &computer, 0, 1, "%s", dc->model); + plot_text(gc, &computer, 0, 1, "%s", + dc->nickname && *dc->nickname ? dc->nickname : dc->model); } if (PP_GRAPHS_ENABLED) { diff --git a/save-xml.c b/save-xml.c index fb9eb413a..0ec6f27d0 100644 --- a/save-xml.c +++ b/save-xml.c @@ -400,6 +400,8 @@ static void save_dc(FILE *f, struct dive *dive, struct divecomputer *dc) fprintf(f, " <divecomputer"); if (dc->model) show_utf8(f, dc->model, " model='", "'", 1); + if (dc->nickname && *dc->nickname) + show_utf8(f, dc->nickname, " nickname='", "'", 1); if (dc->deviceid) fprintf(f, " deviceid='%08x'", dc->deviceid); if (dc->diveid) |