# HG changeset patch # User ali # Date 1380754278 -3600 # Node ID 466f43a12118c49fa7be39c6c7b0ddc31345b3a4 # Parent 9fb13a5dde3b18e7e14910cf062672cef8995f6d Fix bug #11: Test for balanced "slanted" UTF-8 quotation marks 8220/8221 diff -r 9fb13a5dde3b -r 466f43a12118 bl/Makefile.am --- a/bl/Makefile.am Mon Sep 23 21:18:27 2013 +0100 +++ b/bl/Makefile.am Wed Oct 02 23:51:18 2013 +0100 @@ -4,4 +4,4 @@ noinst_LTLIBRARIES=libbl.la libbl_la_SOURCES=bl.h textfileutils.c textfileutils.h spawn.c spawn.h \ - path.c path.h mkdtemp.c mkdtemp.h print.c print.h + path.c path.h mkdtemp.c mkdtemp.h print.c print.h utf8.c utf8.h diff -r 9fb13a5dde3b -r 466f43a12118 bl/bl.h --- a/bl/bl.h Mon Sep 23 21:18:27 2013 +0100 +++ b/bl/bl.h Wed Oct 02 23:51:18 2013 +0100 @@ -3,3 +3,4 @@ #include #include #include +#include diff -r 9fb13a5dde3b -r 466f43a12118 bl/utf8.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bl/utf8.c Wed Oct 02 23:51:18 2013 +0100 @@ -0,0 +1,24 @@ +#include +#include +#include +#include + +/* + * Creates a new string length bytes long filled with fill_char. + * The returned string should be freed when no longer needed. + */ +gchar *utf8_strnfill(gsize length,gunichar fill_char) +{ + int n,i; + gchar *s; + char utf8[6]; + n=g_unichar_to_utf8(fill_char,utf8); + s=g_new(gchar,length*n+1); + if (n==1) + memset(s,utf8[0],length); + else + for(i=0;ilines[j] && g_utf8_get_char(s)==CHAR_DQUOTE && - isalpha(g_utf8_get_char(g_utf8_prev_char(s)))) - results.endquote_count++; + if (s>lines[j]) + { + if (CHAR_IS_DQUOTE(g_utf8_get_char(s))) + qc=QUOTE_CLASS(g_utf8_get_char(s)); + else + qc=INVALID_QUOTE; + if ((qc==CLOSING_QUOTE || qc==NEUTRAL_QUOTE) && + isalpha(g_utf8_get_char(g_utf8_prev_char(s)))) + results.endquote_count++; + } } if (llen>2 && lastlen>2 && lastlen2 && lastblen>SHORTEST_PG_LINE && laststart!=CHAR_SPACE) @@ -788,7 +793,7 @@ * * Returns: TRUE if the line is empty. */ -gboolean analyse_quotes(const char *aline,struct counters *counters) +gboolean analyse_quotes(const char *aline,int linecnt,struct counters *counters) { int guessquote=0; /* assume the line is empty until proven otherwise */ @@ -796,23 +801,24 @@ const char *s=aline,*sprev,*snext; gunichar c; sprev=NULL; + GError *tmp_err=NULL; while (*s) { snext=g_utf8_next_char(s); c=g_utf8_get_char(s); - if (c==CHAR_DQUOTE) - counters->quot++; - if (CHAR_IS_SQUOTE(c)) + if (CHAR_IS_DQUOTE(c)) + (void)count_quote(counters,c,QUOTE_CLASS(c),&tmp_err); + else if (CHAR_IS_SQUOTE(c) && pswit[SQUOTE_SWITCH]) { if (s==aline) { /* - * At start of line, it can only be an openquote. + * At start of line, it can only be a quotation mark. * Hardcode a very common exception! */ if (!g_str_has_prefix(snext,"tis") && !g_str_has_prefix(snext,"Tis")) - increment_matching(counters,c,TRUE); + (void)count_quote(counters,c,NEUTRAL_QUOTE,&tmp_err); } else if (g_unichar_isalpha(g_utf8_get_char(sprev)) && g_unichar_isalpha(g_utf8_get_char(snext))) @@ -822,15 +828,20 @@ else if (c==CHAR_OPEN_SQUOTE || c==CHAR_LS_QUOTE || g_unichar_isalpha(g_utf8_get_char(snext))) { - /* it damwell better BE an openquote */ + /* certainly looks like a quotation mark */ if (!g_str_has_prefix(snext,"tis") && !g_str_has_prefix(snext,"Tis")) /* hardcode a very common exception! */ - increment_matching(counters,c,TRUE); + { + if (strchr(".?!,;:",g_utf8_get_char(sprev))) + (void)count_quote(counters,c,NEUTRAL_QUOTE,&tmp_err); + else + (void)count_quote(counters,c,OPENING_QUOTE,&tmp_err); + } } else { - /* now - is it a closequote? */ + /* now - is it a quotation mark? */ guessquote=0; /* accumulate clues */ if (g_unichar_isalpha(g_utf8_get_char(sprev))) { @@ -844,25 +855,31 @@ /* bonus marks! */ guessquote-=2; } + if (innermost_quote_matches(counters,c)) + /* + * Give it the benefit of some doubt, + * if a squote is already open. + */ + guessquote++; + else + guessquote--; + if (guessquote>=0) + (void)count_quote(counters,c,CLOSING_QUOTE,&tmp_err); } - /* it doesn't have a letter either side */ - else if (strchr(".?!,;:",g_utf8_get_char(sprev)) && - strchr(".?!,;: ",g_utf8_get_char(snext))) - guessquote+=8; /* looks like a closequote */ else - guessquote++; - if (matching_difference(counters,CHAR_SQUOTE)>0) - /* - * Give it the benefit of some doubt, - * if a squote is already open. - */ - guessquote++; - else - guessquote--; - if (guessquote>=0) - increment_matching(counters,c,FALSE); + /* no adjacent letter - it must be a quote of some kind */ + (void)count_quote(counters,c,NEUTRAL_QUOTE,&tmp_err); } } + if (tmp_err) + { + if (pswit[ECHO_SWITCH]) + g_print("\n%s\n",aline); + if (!pswit[OVERVIEW_SWITCH]) + g_print(" Line %ld column %ld - %s\n", + linecnt,g_utf8_pointer_to_offset(aline,s)+1,tmp_err->message); + g_clear_error(&tmp_err); + } if (c!=CHAR_SPACE && c!='-' && c!='.' && c!=CHAR_ASTERISK && c!='\r' && c!='\n') isemptyline=FALSE; /* ignore lines like * * * as spacers */ @@ -1779,6 +1796,7 @@ gboolean isacro,isellipsis; const char *s; gunichar c,nc,pc,n2c; + int parity; c=g_utf8_get_char(aline); nc=c?g_utf8_get_char(g_utf8_next_char(aline)):0; for (s=g_utf8_next_char(aline);nc;s=g_utf8_next_char(s)) @@ -1917,7 +1935,7 @@ c=nc; nc=g_utf8_get_char(g_utf8_next_char(s)); /* for each character in the line after the first */ - if (c==CHAR_DQUOTE) + if (CHAR_IS_DQUOTE(c)) { if (!g_utf8_strchr(" _-.'`,;:!/([{?}])",-1,pc) && !g_utf8_strchr(" _-.'`,;:!/([{?}])",-1,nc) && nc || @@ -1939,10 +1957,18 @@ { c=nc; nc=g_utf8_get_char(g_utf8_next_char(s)); - if (c==CHAR_DQUOTE) + if (CHAR_IS_DQUOTE(c)) { - parities->dquote=!parities->dquote; - if (!parities->dquote) + if (c==CHAR_DQUOTE) + { + parities->dquote=!parities->dquote; + parity=parities->dquote; + } + else if (c==CHAR_LD_QUOTE) + parity=1; + else + parity=0; + if (!parity) { /* parity even */ if (!g_utf8_strchr("_-.'`/,;:!?)]} ",-1,nc)) @@ -1975,7 +2001,8 @@ } } } - if (g_utf8_get_char(aline)==CHAR_DQUOTE) + c=g_utf8_get_char(aline); + if (CHAR_IS_DQUOTE(c)) { if (g_utf8_strchr(",;:!?)]} ",-1, g_utf8_get_char(g_utf8_next_char(aline)))) @@ -2200,7 +2227,7 @@ s=g_utf8_prev_char(aline+lbytes); c1=g_utf8_get_char(s); c2=g_utf8_get_char(g_utf8_prev_char(s)); - if ((c1==CHAR_DQUOTE || CHAR_IS_SQUOTE(c1)) && c2==CHAR_SPACE) + if ((CHAR_IS_DQUOTE(c1) || CHAR_IS_SQUOTE(c1)) && c2==CHAR_SPACE) { if (pswit[ECHO_SWITCH]) g_print("\n%s\n",aline); @@ -2285,15 +2312,17 @@ { const char *s; gunichar c,nc,pc; + QuoteClass qc; c=g_utf8_get_char(aline); nc=c?g_utf8_get_char(g_utf8_next_char(aline)):0; for (s=g_utf8_next_char(aline);nc;s=g_utf8_next_char(s)) { pc=c; c=nc; + qc=CHAR_IS_DQUOTE(c)?QUOTE_CLASS(c):INVALID_QUOTE; nc=g_utf8_get_char(g_utf8_next_char(s)); /* for each character in the line except 1st */ - if (c==CHAR_DQUOTE && isalpha(pc)) + if ((qc==CLOSING_QUOTE || qc==NEUTRAL_QUOTE) && isalpha(pc)) { if (pswit[ECHO_SWITCH]) g_print("\n%s\n",aline); @@ -2396,6 +2425,7 @@ gboolean letter_on_line=FALSE; const char *s; gunichar c; + gboolean closing_quote; for (s=prevline;*s;s=g_utf8_next_char(s)) if (g_unichar_isalpha(g_utf8_get_char(s))) { @@ -2417,7 +2447,11 @@ { s=g_utf8_prev_char(s); c=g_utf8_get_char(s); - } while (CHAR_IS_CLOSING_QUOTE(c) && c>CHAR_SPACE && s>prevline); + if (QUOTE_CLASS(c)==CLOSING_QUOTE || QUOTE_CLASS(c)==NEUTRAL_QUOTE) + closing_quote=TRUE; + else + closing_quote=FALSE; + } while (closing_quote && s>prevline); for (;s>prevline;s=g_utf8_prev_char(s)) { if (g_unichar_isalpha(g_utf8_get_char(s))) @@ -2548,7 +2582,7 @@ } checked_linecnt++; print_pending(aline,parastart,&pending); - isemptyline=analyse_quotes(aline,&counters); + isemptyline=analyse_quotes(aline,linecnt,&counters); if (isnewpara && !isemptyline) { /* This line is the start of a new paragraph. */ diff -r 9fb13a5dde3b -r 466f43a12118 bookloupe/bookloupe.h --- a/bookloupe/bookloupe.h Mon Sep 23 21:18:27 2013 +0100 +++ b/bookloupe/bookloupe.h Wed Oct 02 23:51:18 2013 +0100 @@ -24,15 +24,17 @@ #define CHAR_LS_QUOTE 0x2018 #define CHAR_RS_QUOTE 0x2019 +#define CHAR_LD_QUOTE 0x201C +#define CHAR_RD_QUOTE 0x201D #define CHAR_IS_SQUOTE(c) ((c)==CHAR_SQUOTE || (c)==CHAR_OPEN_SQUOTE || \ (c)==CHAR_LS_QUOTE || (c)==CHAR_RS_QUOTE) +#define CHAR_IS_DQUOTE(c) ((c)==CHAR_DQUOTE || (c)==CHAR_LD_QUOTE || \ + (c)==CHAR_RD_QUOTE) + #define CHAR_IS_APOSTROPHE(c) ((c)==CHAR_SQUOTE || (c)==CHAR_RS_QUOTE) -#define CHAR_IS_CLOSING_QUOTE(c) \ - ((c)==CHAR_DQUOTE || (c)==CHAR_SQUOTE || (c)==CHAR_RS_QUOTE) - /* longest and shortest normal PG line lengths */ #define LONGEST_PG_LINE 75 #define WAY_TOO_LONG 80 @@ -81,8 +83,8 @@ extern gboolean pswit[SWITNO]; -extern long cnt_dquot,cnt_squot,cnt_brack,cnt_bin,cnt_odd,cnt_long,cnt_short; -extern long cnt_punct,cnt_dash,cnt_word,cnt_html,cnt_lineend,cnt_spacend; -extern long linecnt,checked_linecnt; +extern long cnt_quote,cnt_brack,cnt_bin,cnt_odd,cnt_long,cnt_short,cnt_punct; +extern long cnt_dash,cnt_word,cnt_html,cnt_lineend,cnt_spacend,linecnt; +extern long checked_linecnt; #endif /* BOOKOUPE_H */ diff -r 9fb13a5dde3b -r 466f43a12118 bookloupe/counters.c --- a/bookloupe/counters.c Mon Sep 23 21:18:27 2013 +0100 +++ b/bookloupe/counters.c Wed Oct 02 23:51:18 2013 +0100 @@ -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) diff -r 9fb13a5dde3b -r 466f43a12118 bookloupe/counters.h --- a/bookloupe/counters.h Mon Sep 23 21:18:27 2013 +0100 +++ b/bookloupe/counters.h Wed Oct 02 23:51:18 2013 +0100 @@ -3,18 +3,42 @@ #include +#define COUNTERS_ERROR counters_error_quark() + +typedef enum +{ + COUNTERS_ERROR_FAILED, /* Generic failure */ +} CountersError; + /* Special counters live in the private use area */ enum { COUNTER_ILLUSTRATION=0xE000, NO_SPECIAL_COUNTERS }; +typedef enum { + OPENING_QUOTE, + CLOSING_QUOTE, + NEUTRAL_QUOTE, + INVALID_QUOTE +} QuoteClass; + +#define QUOTE_CLASS(c) \ + (((c)==CHAR_RD_QUOTE || (c)==CHAR_RS_QUOTE)?CLOSING_QUOTE: \ + ((c)==CHAR_LD_QUOTE || (c)==CHAR_LS_QUOTE || (c)==CHAR_OPEN_SQUOTE)?\ + OPENING_QUOTE:((c)==CHAR_DQUOTE || (c)==CHAR_SQUOTE)?NEUTRAL_QUOTE:\ + INVALID_QUOTE) + struct counters { GTree *matching; - long quot; int c_unders; + GSList *open_quotes; }; +GQuark counters_error_quark(void); +gboolean innermost_quote_matches(struct counters *counters,gunichar ch); +gboolean count_quote(struct counters *counters,gunichar ch,QuoteClass klass, + GError **err); void increment_matching(struct counters *counters,gunichar ch,gboolean open); int matching_count(const struct counters *counters,gunichar ch,gboolean open); int matching_difference(const struct counters *counters,gunichar ch); diff -r 9fb13a5dde3b -r 466f43a12118 bookloupe/pending.c --- a/bookloupe/pending.c Mon Sep 23 21:18:27 2013 +0100 +++ b/bookloupe/pending.c Wed Oct 02 23:51:18 2013 +0100 @@ -1,6 +1,7 @@ #include #include #include +#include #include "bookloupe.h" #include "pending.h" @@ -15,20 +16,9 @@ void print_pending(const char *aline,const char *parastart, struct pending *pending) { - const char *s; - gunichar c; if (aline) - { - s=aline; - while (*s==' ') - s++; - c=g_utf8_get_char(s); - } - else - { - s=NULL; - c='\0'; - } + while (g_unichar_isspace(g_utf8_get_char(aline))) + aline=g_utf8_next_char(aline); if (pending->illustration.warning_text) { if (aline) @@ -52,38 +42,25 @@ pending->illustration.queried_line=NULL; } } - if (pending->dquote) + if (pending->quote) { - if (c!=CHAR_DQUOTE || pswit[QPARA_SWITCH]) + if (!pending->continuing_quote || !aline || + !g_str_has_prefix(aline,pending->continuing_quote)) { if (!pswit[OVERVIEW_SWITCH]) { if (pswit[ECHO_SWITCH]) g_print("\n%s\n",parastart); - g_print("%s\n",pending->dquote); + g_print("%s\n",pending->quote); } else - cnt_dquot++; + cnt_quote++; } - g_free(pending->dquote); - pending->dquote=NULL; + g_free(pending->quote); + pending->quote=NULL; } - if (pending->squote) - { - if (!CHAR_IS_SQUOTE(c) || pswit[QPARA_SWITCH] || pending->squot) - { - if (!pswit[OVERVIEW_SWITCH]) - { - if (pswit[ECHO_SWITCH]) - g_print("\n%s\n",parastart); - g_print("%s\n",pending->squote); - } - else - cnt_squot++; - } - g_free(pending->squote); - pending->squote=NULL; - } + g_free(pending->continuing_quote); + pending->continuing_quote=NULL; if (pending->rbrack) { if (!pswit[OVERVIEW_SWITCH]) @@ -159,34 +136,35 @@ * quotes on _every_ paragraph, whether the next begins with a * quote or not. */ -void check_for_mismatched_quotes(const struct counters *counters, +void check_for_mismatched_quotes(struct counters *counters, struct pending *pending) { - int squote_straight,squote_curved,difference; - if (counters->quot%2) - pending->dquote= - g_strdup_printf(" Line %ld - Mismatched quotes",linecnt); - if (pswit[SQUOTE_SWITCH]) + gboolean all_single; + gunichar c; + int difference; + const char *quote_type; + GString *str; + if (counters->open_quotes) { - if (matching_count(counters,CHAR_SQUOTE,TRUE)) - squote_straight=matching_difference(counters,CHAR_SQUOTE); + str=g_string_new(NULL); + counters->open_quotes=g_slist_reverse(counters->open_quotes); + all_single=TRUE; + while(counters->open_quotes) + { + c=GPOINTER_TO_INT(counters->open_quotes->data); + if (!CHAR_IS_SQUOTE(c)) + all_single=FALSE; + g_string_append_unichar(str,c); + counters->open_quotes=g_slist_delete_link(counters->open_quotes, + counters->open_quotes); + } + pending->continuing_quote=g_string_free(str,FALSE); + if (all_single) + quote_type="singlequotes?"; else - squote_straight=0; - if (matching_count(counters,CHAR_LS_QUOTE,TRUE)) - squote_curved=matching_difference(counters,CHAR_LS_QUOTE); - else - squote_curved=0; - if (squote_straight || squote_curved) - pending->squote= - g_strdup_printf(" Line %ld - Mismatched singlequotes?", - linecnt); - if (squote_straight && squote_straight!=1 || - squote_curved && squote_curved!=1) - /* - * Flag it to be noted regardless of the - * first char of the next para. - */ - pending->squot=1; + quote_type="quotes"; + pending->quote=g_strdup_printf(" Line %ld - Mismatched %s",linecnt, + quote_type); } difference=matching_difference(counters,COUNTER_ILLUSTRATION); if (difference) diff -r 9fb13a5dde3b -r 466f43a12118 bookloupe/pending.h --- a/bookloupe/pending.h Mon Sep 23 21:18:27 2013 +0100 +++ b/bookloupe/pending.h Wed Oct 02 23:51:18 2013 +0100 @@ -9,15 +9,15 @@ }; struct pending { - char *dquote,*squote,*rbrack,*sbrack,*cbrack,*unders; - long squot; + char *quote,*rbrack,*sbrack,*cbrack,*unders; + char *continuing_quote; struct pending_warning illustration; }; void print_pending(const char *aline,const char *parastart, struct pending *pending); void reset_pending(struct pending *pending); -void check_for_mismatched_quotes(const struct counters *counters, +void check_for_mismatched_quotes(struct counters *counters, struct pending *pending); #endif /* PENDING_H */ diff -r 9fb13a5dde3b -r 466f43a12118 test/bookloupe/Makefile.am --- a/test/bookloupe/Makefile.am Mon Sep 23 21:18:27 2013 +0100 +++ b/test/bookloupe/Makefile.am Wed Oct 02 23:51:18 2013 +0100 @@ -1,5 +1,5 @@ TESTS_ENVIRONMENT=BOOKLOUPE=../../bookloupe/bookloupe ../harness/loupe-test -TESTS=non-ascii.tst long-line.tst curved-single-quotes.tst \ - curved-genitives.tst multi-line-illustration.tst +TESTS=non-ascii.tst long-line.tst curved-single-quotes.tst curved-quotes.tst \ + runfox-quotes.tst curved-genitives.tst multi-line-illustration.tst dist_pkgdata_DATA=$(TESTS) diff -r 9fb13a5dde3b -r 466f43a12118 test/bookloupe/curved-quotes.tst --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/bookloupe/curved-quotes.tst Wed Oct 02 23:51:18 2013 +0100 @@ -0,0 +1,48 @@ +**************** INPUT **************** +When Tom had made fast his motorboat, he went to the rowing craft to +see if it was in good condition. He saw a piece of paper on one of the +seats, held down by a little stone. Picking it up he read: + + “Many thanks for the use of your boat. I had a fine row, and + I feel better, though I’m as much up a tree as ever. I hope + to see you again, sometime. If ever you are near Elmwood Hall, + look me up. + + “BRUCE BENNINGTON.” + +That was nice of him,” remarked Will, as Tom showed him the note. + +“And he didn’t damage your boat any," spoke Dick. + +"No, he knows how to handle ’em--he rows on the Elmwood Hall crew,” said +Tom. “Well, so long, fellows. I’m going for a long run to-morrow, if +you’d like to come.” + +“Sure! they chorused. +**************** WARNINGS **************** + + + + Closing quotation mark with no matching open? + + + + Mismatched quotes + + + + Closing quotation mark with no matching open? + + + + Mismatched quotes + + + + Mismatched quotes + + + + Wrongspaced quotes? + + diff -r 9fb13a5dde3b -r 466f43a12118 test/bookloupe/runfox-quotes.tst --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/bookloupe/runfox-quotes.tst Wed Oct 02 23:51:18 2013 +0100 @@ -0,0 +1,17 @@ +**************** INPUT **************** +“Now I see how it happened,” said Spotted Deer. “If you were not very +strong you would have been dead. Yes, if you were not a good war-leader +you would not have come back here. ”We will not talk any more about it.“ + +“Well, what did you find?” inquired Running Fox. +**************** WARNINGS **************** + + + + Wrongspaced quotes? + + + + Wrongspaced quotes? + + diff -r 9fb13a5dde3b -r 466f43a12118 test/compatibility/Makefile.am --- a/test/compatibility/Makefile.am Mon Sep 23 21:18:27 2013 +0100 +++ b/test/compatibility/Makefile.am Wed Oct 02 23:51:18 2013 +0100 @@ -7,6 +7,7 @@ dashes.tst control-characters.tst unusual-characters.tst \ windows-1252.tst periods.tst long-line.tst unmarked-paragraph.tst \ hebe-jeebies.tst mail-from.tst scannos.tst before-comma.tst \ - before-period.tst double-punctuation.tst genitives.tst embedded-cr.tst + before-period.tst double-punctuation.tst genitives.tst embedded-cr.tst \ + continuing-quotes.tst dist_pkgdata_DATA=$(TESTS) diff -r 9fb13a5dde3b -r 466f43a12118 test/compatibility/continuing-quotes.tst --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compatibility/continuing-quotes.tst Wed Oct 02 23:51:18 2013 +0100 @@ -0,0 +1,14 @@ +**************** INPUT **************** +When Tom had made fast his motorboat, he went to the rowing craft to +see if it was in good condition. He saw a piece of paper on one of the +seats, held down by a little stone. Picking it up he read: + + "Many thanks for the use of your boat. I had a fine row, and + I feel better, though I'm as much up a tree as ever. I hope + to see you again, sometime. If ever you are near Elmwood Hall, + look me up. + + "BRUCE BENNINGTON." + +"That was nice of him," remarked Will, as Tom showed him the note. +**************** EXPECTED ****************