diff -r adc06e9e8470 -r aece0899b1d3 bookloupe/counters.c --- a/bookloupe/counters.c Mon Sep 23 21:18:27 2013 +0100 +++ b/bookloupe/counters.c Wed Oct 30 17:21:21 2013 +0000 @@ -8,6 +8,14 @@ int open,close; }; +GQuark counters_error_quark(void) +{ + static GQuark quark; + if (!quark) + quark=g_quark_from_static_string("counters_error"); + return quark; +} + static struct matching_counter *matching_counter_new(void) { return g_slice_new0(struct matching_counter); @@ -45,11 +53,64 @@ return GINT_TO_POINTER((gint)CHAR_SQUOTE); else if (ch==CHAR_LS_QUOTE || ch==CHAR_RS_QUOTE) return GINT_TO_POINTER((gint)CHAR_LS_QUOTE); + else if (ch==CHAR_LD_QUOTE || ch==CHAR_RD_QUOTE) + return GINT_TO_POINTER((gint)CHAR_LD_QUOTE); + else if (ch==CHAR_DQUOTE) + return GINT_TO_POINTER((gint)ch); else if (ch<0x4000 || ch-0x4000>=NO_SPECIAL_COUNTERS) + g_warning("Matching pair not found for U+%04" G_GINT32_MODIFIER "X",ch); + return GINT_TO_POINTER((gint)ch); +} + +gboolean innermost_quote_matches(struct counters *counters,gunichar ch) +{ + gpointer head; + if (counters->open_quotes) + head=counters->open_quotes->data; + else + head=NULL; + return head==matching_key(ch); +} + +gboolean count_quote(struct counters *counters,gunichar ch,QuoteClass klass, + GError **err) +{ + gboolean retval=TRUE; + gpointer head; + if (counters->open_quotes) + head=counters->open_quotes->data; + else + head=NULL; + switch(klass) { - g_warning("Matching pair not found for U+%04" G_GINT32_MODIFIER "X",ch); - return GINT_TO_POINTER((gint)ch); + case NEUTRAL_QUOTE: + if (head!=matching_key(ch)) + goto opening; + /* else fall through */ + case CLOSING_QUOTE: + if (head!=matching_key(ch)) + { + g_set_error(err,COUNTERS_ERROR,COUNTERS_ERROR_FAILED, + "Closing quotation mark with no matching open?"); + retval=FALSE; + } + else + counters->open_quotes=g_slist_delete_link(counters->open_quotes, + counters->open_quotes); + break; + case OPENING_QUOTE: + if (head==matching_key(ch)) + { + g_set_error(err,COUNTERS_ERROR,COUNTERS_ERROR_FAILED, + "Directly nested quotation marks of same type?"); + retval=FALSE; + } +opening: + head=matching_key(ch); + counters->open_quotes=g_slist_prepend(counters->open_quotes,head); + break; } + return retval; } void increment_matching(struct counters *counters,gunichar ch,gboolean open)