#include "display.h"
static GtkWidget *divedate, *divetime, *depth, *duration;
-static GtkWidget *location, *notes;
+static GtkTextBuffer *location, *notes;
+static int location_changed = 1, notes_changed = 1;
+static struct dive *buffered_dive;
static const char *weekday(int wday)
{
return wday_array[wday];
}
+static char *get_text(GtkTextBuffer *buffer)
+{
+ GtkTextIter start;
+ GtkTextIter end;
+
+ gtk_text_buffer_get_start_iter(buffer, &start);
+ gtk_text_buffer_get_end_iter(buffer, &end);
+ return gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
+}
+
+void flush_dive_info_changes(void)
+{
+ struct dive *dive = buffered_dive;
+
+ if (!dive)
+ return;
+
+ if (location_changed) {
+ g_free(dive->location);
+ dive->location = get_text(location);
+ }
+
+ if (notes_changed) {
+ g_free(dive->notes);
+ dive->notes = get_text(notes);
+ }
+}
+
void update_dive_info(struct dive *dive)
{
struct tm *tm;
char buffer[80];
+ char *text;
+
+ flush_dive_info_changes();
+ buffered_dive = dive;
if (!dive) {
gtk_label_set_text(GTK_LABEL(divedate), "no dive");
"%d min",
dive->duration.seconds / 60);
gtk_label_set_text(GTK_LABEL(duration), buffer);
+
+ text = dive->location ? : "";
+ gtk_text_buffer_set_text(location, text, -1);
+ text = dive->notes ? : "";
+ gtk_text_buffer_set_text(notes, text, -1);
}
static GtkWidget *info_label(GtkWidget *box, const char *str)
return frame;
}
-static GtkWidget *text_entry(GtkWidget *box, const char *label)
+static GtkTextBuffer *text_entry(GtkWidget *box, const char *label, gboolean expand)
{
- GtkWidget *entry;
+ GtkWidget *view;
+ GtkTextBuffer *buffer;
+
GtkWidget *frame = gtk_frame_new(label);
- gtk_box_pack_start(GTK_BOX(box), frame, FALSE, FALSE, 0);
- entry = gtk_entry_new();
- gtk_container_add(GTK_CONTAINER(frame), entry);
- return entry;
+
+ gtk_box_pack_start(GTK_BOX(box), frame, expand, expand, 0);
+
+ view = gtk_text_view_new ();
+ buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
+
+ gtk_container_add(GTK_CONTAINER(frame), view);
+ return buffer;
}
GtkWidget *extended_dive_info_frame(void)
vbox = gtk_vbox_new(FALSE, 5);
gtk_container_add(GTK_CONTAINER(frame), vbox);
- location = text_entry(vbox, "Location");
- notes = text_entry(vbox, "Notes");
- location = gtk_entry_new();
+ location = text_entry(vbox, "Location", FALSE);
+ notes = text_entry(vbox, "Notes", TRUE);
/* Add extended info here: name, description, yadda yadda */
update_dive_info(current_dive);
/* Ignore n2 percentages. There's no value in them. */
}
+static void utf8_string(char *buffer, void *_res)
+{
+ *(char **)_res = buffer;
+}
+
#define MATCH(pattern, fn, dest) \
match(pattern, strlen(pattern), name, len, fn, buf, dest)
return;
if (MATCH(".cylinderendpressure", pressure, &dive->end_pressure))
return;
+ if (MATCH(".location", utf8_string, &dive->location))
+ return;
+ if (MATCH(".notes", utf8_string, &dive->notes))
+ return;
if (MATCH(".o2", gasmix, &dive->gasmix[gasmix_index].o2))
return;
fprintf(f, "%s%u.%03u bar%s", pre, FRACTION(pressure.mbar, 1000), post);
}
+/*
+ * We're outputting utf8 in xml.
+ * We need to quote the characters <, >, &.
+ *
+ * Nothing else (and if we ever do this using attributes, we'd need to
+ * quote the quotes we use too).
+ */
+static void quote(FILE *f, const char *text)
+{
+ const char *p = text;
+
+ for (;;) {
+ const char *escape;
+
+ switch (*p++) {
+ default:
+ continue;
+ case 0:
+ escape = NULL;
+ break;
+ case '<':
+ escape = "<";
+ break;
+ case '>':
+ escape = ">";
+ break;
+ case '&':
+ escape = "&";
+ break;
+ }
+ fwrite(text, (p - text - 1), 1, f);
+ if (!escape)
+ break;
+ fputs(escape, f);
+ text = p;
+ }
+}
+
+static void show_utf8(FILE *f, const char *text, const char *pre, const char *post)
+{
+ int len;
+
+ if (!text)
+ return;
+ while (isspace(*text))
+ text++;
+ len = strlen(text);
+ if (!len)
+ return;
+ while (len && isspace(text[len-1]))
+ len--;
+ /* FIXME! Quoting! */
+ fputs(pre, f);
+ quote(f, text);
+ fputs(post, f);
+}
+
static void save_overview(FILE *f, struct dive *dive)
{
show_depth(f, dive->maxdepth, " <maxdepth>", "</maxdepth>\n");
show_duration(f, dive->surfacetime, " <surfacetime>", "</surfacetime>\n");
show_pressure(f, dive->beginning_pressure, " <cylinderstartpressure>", "</cylinderstartpressure>\n");
show_pressure(f, dive->end_pressure, " <cylinderendpressure>", "</cylinderendpressure>\n");
+ show_utf8(f, dive->location, " <location>","</location>\n");
+ show_utf8(f, dive->notes, " <notes>","</notes>\n");
}
static void save_gasmix(FILE *f, struct dive *dive)
if (!f)
return;
+
+ /* Flush any edits of current dives back to the dives! */
+ flush_dive_info_changes();
+
fprintf(f, "<dives>\n<program name='diveclog' version='%d'></program>\n", VERSION);
for (i = 0; i < dive_table.nr; i++)
save_dive(f, get_dive(i));