summaryrefslogtreecommitdiffstats
path: root/gtk-gui.c
diff options
context:
space:
mode:
authorGravatar Dirk Hohndel <dirk@hohndel.org>2012-12-22 21:37:13 -0800
committerGravatar Dirk Hohndel <dirk@hohndel.org>2012-12-22 21:38:07 -0800
commit06cd494a2f1906de3d56100fe5b883d9a5093329 (patch)
tree31109590d4c1736333d28d2f030f7b6ee39b77e9 /gtk-gui.c
parent267476e3fe4d9b48ee990eb4a0ba2db45072fc5d (diff)
downloadsubsurface-06cd494a2f1906de3d56100fe5b883d9a5093329.tar.gz
Next improvement of the nickname code
Now it is able to replace nicknames for existing entries (which will be needed by the yet to be written UI). This commit fixes a couple issues with the previous code: - a potential SIGSEGV with malformed config entries - missing closing parenthesis in the dialog box text Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Diffstat (limited to 'gtk-gui.c')
-rw-r--r--gtk-gui.c74
1 files changed, 64 insertions, 10 deletions
diff --git a/gtk-gui.c b/gtk-gui.c
index 773098e71..07d94bae9 100644
--- a/gtk-gui.c
+++ b/gtk-gui.c
@@ -1226,7 +1226,7 @@ void init_ui(int *argcp, char ***argvp)
len = strlen(namestart + 1);
nameend = g_utf8_strchr(namestart + 1, len, ',');
tupleend = g_utf8_strchr(namestart + 1, len, '}');
- if (!nameend && !tupleend)
+ if (!tupleend)
/* the config entry is messed up - bail */
break;
if (!nameend || tupleend < nameend)
@@ -2063,16 +2063,16 @@ const char *get_dc_nickname(uint32_t deviceid)
}
/* do we have a DIFFERENT divecomputer of the same model? */
-static gboolean dc_model_exists(struct divecomputer *dc)
+static struct dcnicknamelist *get_dc_nicknameentry(const char *model, int deviceid)
{
struct dcnicknamelist *known = nicknamelist;
while (known) {
- if (known->model && dc->model && !strcmp(known->model, dc->model) &&
- known->deviceid != dc->deviceid)
- return TRUE;
+ if (known->model && model && !strcmp(known->model, model) &&
+ known->deviceid != deviceid)
+ return known;
known = known->next;
}
- return FALSE;
+ return NULL;
}
/* no curly braces or commas, please */
@@ -2102,6 +2102,50 @@ static char *cleanedup_nickname(const char *nickname, int len)
return clean;
}
+void replace_nickname_nicknamestring(int deviceid, const char *nickname)
+{
+ char buf[11];
+ char *entry, *comma1, *comma2, *brace, *new_nn;
+ int len;
+
+ snprintf(buf, sizeof(buf), "{%08x,", deviceid);
+ entry = strstr(nicknamestring, buf);
+ if (!entry)
+ /* this cannot happen as we know have an entry for this deviceid */
+ goto bail;
+ len = strlen(entry);
+ comma1 = g_utf8_strchr(entry, len, ',');
+ if (!comma1)
+ goto bail;
+ len = strlen(comma1);
+ comma2 = g_utf8_strchr(comma1, len, ',');
+ brace = g_utf8_strchr(comma1, len, '}');
+ if (!brace)
+ goto bail;
+ if (!comma2 || brace < comma2) {
+ /* didn't have a nickname, so add one */
+ len = strlen(nicknamestring) + strlen(nickname) + 2;
+ *brace = '\0';
+ } else {
+ /* replace the nickname */
+ len = strlen(nicknamestring) + strlen(nickname) - (brace - comma2) + 1;
+ *comma2 = '\0';
+ }
+ new_nn = malloc(len);
+ if (strlen(nickname))
+ snprintf(new_nn, len, "%s,%s}%s", entry, nickname, brace + 1);
+ else
+ snprintf(new_nn, len, "%s}%s", entry, brace + 1);
+ free(nicknamestring);
+ nicknamestring = new_nn;
+ return;
+
+bail:
+ printf("invalid nicknamestring %s (while looking at deviceid %08x\n", nicknamestring, deviceid);
+ return;
+
+}
+
void remember_dc(uint32_t deviceid, const char *model, const char *nickname, gboolean change_conf)
{
if (!get_dc_nickname(deviceid)) {
@@ -2122,6 +2166,13 @@ void remember_dc(uint32_t deviceid, const char *model, const char *nickname, gbo
strcat(nicknamestring, buffer);
if (change_conf)
subsurface_set_conf("dc_nicknames", PREF_STRING, nicknamestring);
+ } else {
+ /* modify existing entry */
+ struct dcnicknamelist *nn_entry = get_dc_nicknameentry(model, deviceid);
+ if (!nn_entry->model || !*nn_entry->model)
+ nn_entry->model = model;
+ nn_entry->nickname = nickname;
+ replace_nickname_nicknamestring(deviceid, nickname);
}
#if defined(NICKNAME_DEBUG)
struct dcnicknamelist *nn_entry = nicknamelist;
@@ -2150,7 +2201,8 @@ void set_dc_nickname(struct dive *dive)
fprintf(debugfile, "set_dc_nickname for model %s deviceid %8x\n", dc->model ? : "", dc->deviceid);
#endif
if (get_dc_nickname(dc->deviceid) == NULL) {
- if (!dc_model_exists(dc)) {
+ struct dcnicknamelist *nn_entry = get_dc_nicknameentry(dc->model, dc->deviceid);
+ if (!nn_entry) {
/* just remember the dive computer without setting a nickname */
if (dc->model)
remember_dc(dc->deviceid, dc->model, "", TRUE);
@@ -2164,15 +2216,17 @@ void set_dc_nickname(struct dive *dive)
NULL);
vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
snprintf(dialogtext, sizeof(dialogtext),
- _("You already have a dive computer of model %s\n"
+ _("You already have a dive computer of this model\n"
+ "named %s\n"
"Subsurface can maintain a nickname for this device to "
"distinguish it from the existing one. "
"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 its name (which may mean that you cannot tell the two "
- "dive computers apart in the logs."),
- dc->model ? dc->model : "(unset)");
+ "dive computers apart in the logs)."),
+ nn_entry->nickname && *nn_entry->nickname ? nn_entry->nickname :
+ (nn_entry->model && *nn_entry->model ? nn_entry->model : _("(nothing)")));
label = gtk_label_new(dialogtext);
gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, TRUE, 3);