From 22fcef2ec7fd1efd3d1df2aba2b7b3af5d463288 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Thu, 1 Sep 2011 19:56:04 -0700 Subject: [PATCH] Save and parse notes and locations It's pretty rough, but it seems to work. Signed-off-by: Linus Torvalds --- dive.h | 5 ++++- info.c | 64 ++++++++++++++++++++++++++++++++++++++++++++--------- parse-xml.c | 9 ++++++++ save-xml.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 130 insertions(+), 11 deletions(-) diff --git a/dive.h b/dive.h index 15a357f..c1b95e3 100644 --- a/dive.h +++ b/dive.h @@ -104,6 +104,8 @@ struct sample { struct dive { const char *name; time_t when; + char *location; + char *notes; depth_t maxdepth, meandepth; duration_t duration, surfacetime; depth_t visibility; @@ -133,6 +135,7 @@ static inline struct dive *get_dive(unsigned int nr) extern void parse_xml_init(void); extern void parse_xml_file(const char *filename); -void save_dives(const char *filename); +extern void flush_dive_info_changes(void); +extern void save_dives(const char *filename); #endif /* DIVE_H */ diff --git a/info.c b/info.c index 547b5d1..3adbe15 100644 --- a/info.c +++ b/info.c @@ -6,7 +6,9 @@ #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) { @@ -16,10 +18,42 @@ 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"); @@ -50,6 +84,11 @@ void update_dive_info(struct dive *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) @@ -80,14 +119,20 @@ GtkWidget *dive_info_frame(void) 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) @@ -101,9 +146,8 @@ 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); diff --git a/parse-xml.c b/parse-xml.c index 6c93ad1..86ef31a 100644 --- a/parse-xml.c +++ b/parse-xml.c @@ -349,6 +349,11 @@ static void gasmix_nitrogen(char *buffer, void *_gasmix) /* 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) @@ -423,6 +428,10 @@ static void try_to_fill_dive(struct dive *dive, const char *name, char *buf) 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; diff --git a/save-xml.c b/save-xml.c index efff300..cd7bad2 100644 --- a/save-xml.c +++ b/save-xml.c @@ -40,6 +40,63 @@ static void show_pressure(FILE *f, pressure_t pressure, const char *pre, const c 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, " ", "\n"); @@ -50,6 +107,8 @@ static void save_overview(FILE *f, struct dive *dive) show_duration(f, dive->surfacetime, " ", "\n"); show_pressure(f, dive->beginning_pressure, " ", "\n"); show_pressure(f, dive->end_pressure, " ", "\n"); + show_utf8(f, dive->location, " ","\n"); + show_utf8(f, dive->notes, " ","\n"); } static void save_gasmix(FILE *f, struct dive *dive) @@ -106,6 +165,10 @@ void save_dives(const char *filename) if (!f) return; + + /* Flush any edits of current dives back to the dives! */ + flush_dive_info_changes(); + fprintf(f, "\n\n", VERSION); for (i = 0; i < dive_table.nr; i++) save_dive(f, get_dive(i)); -- 2.45.2