From ff3200286b13aef689d7574a40fe98d90a709390 Mon Sep 17 00:00:00 2001 From: Seymour Shlien Date: Tue, 14 Jun 2022 14:46:35 -0400 Subject: [PATCH] 2022.06.14 --- VERSION | 2 +- abc.h | 1 + abcmatch.c | 2 +- doc/CHANGES | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++ doc/readme.txt | 8 +++---- drawtune.c | 4 ++++ genmidi.c | 58 +++++++++++++++++++++++++++++++++++++++++--------- matchsup.c | 4 +++- parseabc.c | 55 +++++++++++++++++++++++++++++++++++------------ parseabc.h | 6 +++++- store.c | 9 ++++++-- structs.h | 1 + toabc.c | 16 +++++++++++--- yapstree.c | 25 +++++++++++++++------- 14 files changed, 204 insertions(+), 45 deletions(-) diff --git a/VERSION b/VERSION index ac52e0f..02ecb2d 100644 --- a/VERSION +++ b/VERSION @@ -1,2 +1,2 @@ -2022 June 07 2022 +2022 June 14 2022 diff --git a/abc.h b/abc.h index b9893b6..e282323 100644 --- a/abc.h +++ b/abc.h @@ -91,6 +91,7 @@ MUSICLINE, MUSICSTOP, WORDLINE, WORDSTOP, +WORDEXTEND, INSTRUCTION, NOBEAM, CHORDNOTE, diff --git a/abcmatch.c b/abcmatch.c index eb57d76..7bf9d73 100644 --- a/abcmatch.c +++ b/abcmatch.c @@ -49,7 +49,7 @@ Matching: -#define VERSION "1.81 June 07 2021 abcmatch" +#define VERSION "1.82 June 14 2022 abcmatch" #include #include #include diff --git a/doc/CHANGES b/doc/CHANGES index 04f1c72..616b04a 100644 --- a/doc/CHANGES +++ b/doc/CHANGES @@ -14779,3 +14779,61 @@ umlaut_get_buffer() umlaut_build_string() and parsename/parsesname were combined into one function. +June 14 2022 + +James Allwright has added support to the w:+ and +: lyric fields +as defined in the 2.3 abc standard. The following examples tests +the new feature. + +X:1 +T: Strange w: field example from abc 2.2 standard +N: This example appears in section 3.3 of the standard, which says : +N: The following is a legal continuation of the w: field, +N: although the usage not recommended +M: 4/4 +L:1/4 +K:G +abcd|efgz| +%%vocalfont Times-Roman 14 +w:nor-mal +% legal, but not recommended +%%vocalfont Times-Italic * ++:i-ta-lic +%%vocalfont Times-Roman * ++:nor-mal + +X:2 +T: Continuation Example +M:4/4 +L:1/8 +K:G +% legacy style continuation +B3A | "G"G2D2 B,2D2 | G4 z2G2 | "D7"A2A2 A2A2 | A4 || +w: Oh, the Grand Old Duke of York, \ +w: he had ten thou-sand men. +% + field style continuation +B3A | "G"G2D2 B,2D2 | G4 z2G2 | "D7"A2A2 A2A2 | A4 || +w: Oh, the Grand Old Duke of York, ++: he had ten thou-sand men. +% w: + style continuation +B3A | "G"G2D2 B,2D2 | G4 z2G2 | "D7"A2A2 A2A2 | A4 z2 || +w: Oh, the Grand Old Duke of York, +w: + he had ten thou-sand men. + +There are numerous small changes. +In abc.h, added WORDEXTEND feature type. +In parseabc.h defined W_PLUS_FIELD and PLUS_FIELD + and added a new integer parameter 'append' to the + function event_word +In structs.h added lyrics_end +In parseabc.c preparse_words() has been split into two + new functions preparse2_words() and preparse1_words() + new input parameter in the function event_words() +In store.c, toabc.c, matchsup.c, and yapstree.c, modified + the function event_words. +In genmidi.c introduced function check_wordextend() +In drawtune.c added the case WORDEXTEND in functions sizevoice() + and printvoiceline(). + + + diff --git a/doc/readme.txt b/doc/readme.txt index 1978ad8..6e36721 100644 --- a/doc/readme.txt +++ b/doc/readme.txt @@ -1,10 +1,10 @@ abcMIDI : abc <-> MIDI conversion utilities midi2abc version 3.54 April 28 2022 -abc2midi version 4.73 May 20 2022 -abc2abc version 2.17 May 20 2022 -yaps version 1.89 May 20 2022 -abcmatch version 1.81 June 07 2022 +abc2midi version 4.74 June 14 2022 +abc2abc version 2.18 June 14 2022 +yaps version 1.90 June 14 2022 +abcmatch version 1.82 June 14 2022 midicopy version 1.38 May 06 2022 24th January 2002 diff --git a/drawtune.c b/drawtune.c index aff416d..0563938 100644 --- a/drawtune.c +++ b/drawtune.c @@ -1636,6 +1636,8 @@ static void sizevoice(struct voice* v, struct tune* t) break; case WORDSTOP: break; + case WORDEXTEND: + break; case INSTRUCTION: break; case NOBEAM: @@ -3369,6 +3371,8 @@ static int printvoiceline(struct voice* v) break; case WORDSTOP: break; + case WORDEXTEND: + break; case INSTRUCTION: break; case NOBEAM: diff --git a/genmidi.c b/genmidi.c index 134cef4..b78d99e 100644 --- a/genmidi.c +++ b/genmidi.c @@ -289,7 +289,7 @@ char *featname[] = { "CHORDOFF", "CHORDOFFEX", "DRUMON", "DRUMOFF", "DRONEON", "DRONEOFF", "SLUR_TIE", "TNOTE", "LT", "GT", "DYNAMIC", "LINENUM", -"MUSICLINE", "MUSICSTOP", "WORDLINE", "WORDSTOP", +"MUSICLINE", "MUSICSTOP", "WORDLINE", "WORDSTOP", "WORDEXTEND", "INSTRUCTION", "NOBEAM", "CHORDNOTE", "CLEF", "PRINTLINE", "NEWPAGE", "LEFT_TEXT", "CENTRE_TEXT", "VSKIP", "COPYRIGHT", "COMPOSER", "ARPEGGIO", @@ -812,7 +812,6 @@ int track; while ((j < notes) && (done > 0)) { - j = j+1; if (feature[j] == TITLE) { if (track != 2) mf_write_meta_event(0L, sequence_name, atext[pitch[j]], strlen (atext[pitch[j]])); @@ -830,9 +829,35 @@ int track; text_data(atitle); done--; } + j = j+1; } } +/* [JA] 2022.06.14 */ +/* scan ahead to see if a WORDSTOP is cancelled by a subsequent WORDEXTEND */ +static int check_wordextend(int startplace) +{ + int place; + int result; + int this_feature; + + place = startplace; + result = 0; + while ((result == 0) && (place < notes) ) { + this_feature = feature[place]; + if (this_feature == WORDEXTEND) { + return 1; + } + /* we should stop searching if we find any of these */ + if ((this_feature == WORDLINE) || (this_feature == PART) || + (this_feature == VOICE) || (this_feature == MUSICLINE)) { + return 0; + } + place = place + 1; + } + return 0; +} + static int findwline(startline) int startline; /* Find next line of lyrics at or after startline. */ @@ -875,14 +900,27 @@ int startline; }; break; case WORDSTOP: - if (inwline) { - versecount = versecount + 1; - }; - inwline = 0; - /* stop if we are part-way through a lyric set */ - if (extending) { - done = 1; - }; + /* [JA] 2022-06-14 */ + /* WORDSTOP marks the end of a w: field (i.e. no continuation). + * if it is followed by WORDEXTEND (indicating w: + or +:) then + * we over-ride it. + */ + if (!check_wordextend(place)) { + if (inwline) { + versecount = versecount + 1; + }; + inwline = 0; + /* stop if we are part-way through a lyric set */ + if (extending) { + done = 1; + }; + } + break; + case WORDEXTEND: + /* don't need to do anything with WORDEXTEND here as we search + * foward for it when we find WORDSTOP + * [JA] 2022-06-14 + */ break; case PART: done = 1; diff --git a/matchsup.c b/matchsup.c index 542e426..7a14b87 100644 --- a/matchsup.c +++ b/matchsup.c @@ -665,9 +665,11 @@ char *f; }; } -void event_words(p, continuation) +/* [JA] 2022.06.14 */ +void event_words(p, append, continuation) /* handles a w: field in the abc */ char* p; +int append; int continuation; { } diff --git a/parseabc.c b/parseabc.c index bf95893..1b90ffe 100644 --- a/parseabc.c +++ b/parseabc.c @@ -2130,17 +2130,24 @@ char key; char *s; { appendfield(s); -} +} -void -preparse_words (s) - char *s; -/* takes a line of lyrics (w: field) and strips off */ -/* any continuation character */ +/* [JA] 2022-06-14 */ +/* Second level of processing for a line of lyrics, takes either + * w: with any + at the start removed or +: . + * It then strips off any continuation character + * append is set to + * PLUS_FIELD for +: + * W_PLUS_FIELD for w: + + * 0 for regular w: + */ +void preparse2_words(char *field, int append) { int continuation; int l; + char *s; + s = field; /* printf("Parsing %s\n", s); */ /* strip off any trailing spaces */ l = strlen (s) - 1; @@ -2156,7 +2163,6 @@ preparse_words (s) else { /* [SS] 2014-08-14 */ - event_warning ("\\n continuation no longer supported in w: line"); continuation = 1; /* remove continuation character */ *(s + l) = '\0'; @@ -2167,7 +2173,28 @@ preparse_words (s) l = l - 1; }; }; - event_words (s, continuation); + event_words (s, append, continuation); +} + +/* first level of w: field processing + * takes a line of lyrics (w: field) and handles + * any + after w: + */ +void preparse1_words (char *field) +{ + int append; + char *s; + + /* look for '+' at the start of word field */ + s = field; + append = 0; + skipspace(&s); + if (*s == '+') { + append = W_PLUS_FIELD; + s = s + 1; + skipspace(&s); + } + preparse2_words(s, append); } void @@ -2506,7 +2533,11 @@ parsefield (key, field) }; break; case 'w': - preparse_words (place); + preparse1_words (place); + break; + case '+': + /* implement +: field as meaning w: + */ + preparse2_words(place, PLUS_FIELD); break; case 'd': /* decoration line in abcm2ps */ @@ -2515,10 +2546,6 @@ parsefield (key, field) case 's': event_field (key, place); /* [SS] 2010-02-23 */ break; - case '+': - if (lastfieldcmd == 'w') - append_fieldcmd (key, place); /*[SS] 2014-08-15 */ - break; /* [SS] 2014-09-07 */ default: event_field (key, place); }; @@ -3413,7 +3440,7 @@ parseline (line) if (parsing) parsemusic (p); } - else if (inbody) preparse_words (p); /* [SS] 2017-10-23 */ + else if (inbody) preparse1_words (p); /* [SS] 2017-10-23 */ else { if (parsing) event_text (p); diff --git a/parseabc.h b/parseabc.h index 35aa14b..60daba2 100644 --- a/parseabc.h +++ b/parseabc.h @@ -52,6 +52,10 @@ struct fraction { int denom; }; +/* non-zero values for append in words_fn() */ +#define W_PLUS_FIELD 1 +#define PLUS_FIELD 2 + #ifndef KANDR extern int readnump(char **p); extern int readsnump(char **p); @@ -117,7 +121,7 @@ extern void event_specific_in_header(char *package, char *s); extern void event_startinline(void); extern void event_closeinline(void); extern void event_field(char k, char *f); -extern void event_words(char *p, int continuation); +extern void event_words(char *p, int append, int continuation); extern void event_part(char *s); diff --git a/store.c b/store.c index 0b03dc0..e9a4849 100644 --- a/store.c +++ b/store.c @@ -186,7 +186,7 @@ int main() */ -#define VERSION "4.73 May 20 2022 abc2midi" +#define VERSION "4.74 June 14 2022 abc2midi" /* enables reading V: indication in header */ #define XTEN1 1 @@ -2731,9 +2731,11 @@ char *f; }; } -void event_words(p, continuation) +/* [JA] 2022.06.14 */ +void event_words(p, append, continuation) /* handles a w: field in the abc */ char* p; +int append; int continuation; { @@ -2745,6 +2747,9 @@ int continuation; v->haswords = 1; wordvoice = v->indexno; words[wcount] = addstring(p); + if ((append == PLUS_FIELD) || (append == W_PLUS_FIELD)) { + addfeature(WORDEXTEND, 0, 0, 0); + }; addfeature(WORDLINE, wcount, 0, 0); if (continuation == 0) { addfeature(WORDSTOP, 0, 0, 0); diff --git a/structs.h b/structs.h index dc1eac2..8e9f4b4 100644 --- a/structs.h +++ b/structs.h @@ -176,6 +176,7 @@ struct voice { float tuple_height; /* variables for assigning syllables to notes */ struct feature* linestart; + struct feature* lyrics_end; struct feature* lineend; struct chord* thischord; struct feature* chordplace; diff --git a/toabc.c b/toabc.c index 7ef8f99..05c2d0d 100644 --- a/toabc.c +++ b/toabc.c @@ -21,7 +21,7 @@ /* back-end for outputting (possibly modified) abc */ -#define VERSION "2.17 May 20 2022 abc2abc" +#define VERSION "2.18 June 14 2022 abc2abc" /* for Microsoft Visual C++ 6.0 or higher */ #ifdef _MSC_VER @@ -1153,8 +1153,10 @@ char* p; freevstring(&syll); } -void event_words(p, continuation) +/* [JA] 2022.06.14 */ +void event_words(p, append, continuation) char* p; +int append; int continuation; /* a w: field has been encountered */ { @@ -1163,13 +1165,21 @@ int continuation; if (xinbody && newbreaks) { parse_words(p); } else { + initvstring(&afield); + if (append == W_PLUS_FIELD) { + addtext("+ ", &afield); + } addtext(p, &afield); if (continuation) { addch(' ', &afield); addch('\\', &afield); }; - event_field('w', afield.st); + if (append == PLUS_FIELD) { + event_field('+', afield.st); + } else { + event_field('w', afield.st); + } }; } diff --git a/yapstree.c b/yapstree.c index f5b38bf..9ea6a3e 100644 --- a/yapstree.c +++ b/yapstree.c @@ -22,7 +22,7 @@ /* yapstree.c - back-end for abc parser. */ /* generates a data structure suitable for typeset music */ -#define VERSION "1.89 May 20 2022 yaps" +#define VERSION "1.90 June 14 2022 yaps" #include #ifdef USE_INDEX #define strchr index @@ -852,6 +852,7 @@ static struct voice* newvoice(int n) v->instructions_pending = NULL; v->beamed_tuple_pending = 0; v->linestart = NULL; + v->lyrics_end = NULL; v->lineend = NULL; v->more_lyrics = 0; v->lyric_errors = 0; @@ -1425,6 +1426,7 @@ void event_startmusicline() parser_voice = &voicecode[voicenum - 1]; cv->linestart = addnumberfeature(MUSICLINE, 0); + cv->lyrics_end = NULL; if (cv->more_lyrics != 0) { event_error("Missing continuation w: field"); cv->more_lyrics = 0; @@ -1711,8 +1713,10 @@ struct feature* apply_syll(char* s, struct feature* wordplace, int* errors) return(ft); } -void event_words(p, continuation) +/* [JA] 2022.06.14 */ +void event_words(p, append, continuation) char* p; +int append; int continuation; /* A line of lyrics (w: ) has been encountered in the abc */ { @@ -1728,7 +1732,11 @@ int continuation; }; return; }; - wordplace = cv->linestart; + if (append && (cv->lyrics_end != NULL)) { + wordplace = cv->lyrics_end; + } else { + wordplace = cv->linestart; + } if (cv->more_lyrics) { errors = cv->lyric_errors; } else { @@ -1790,6 +1798,7 @@ int continuation; }; }; }; + cv->lyrics_end = wordplace; if (continuation) { cv->more_lyrics = 1; cv->lyric_errors = errors; @@ -1799,11 +1808,11 @@ int continuation; if (errors > 0) { event_error("Lyric line too long for music"); } else { - clearvstring(&syll); - wordplace = apply_syll(syll.st, wordplace, &errors); - if (errors == 0) { - event_error("Lyric line too short for music"); - }; +// clearvstring(&syll); +// wordplace = apply_syll(syll.st, wordplace, &errors); +// if (errors == 0) { +// event_error("Lyric line too short for music"); +// }; }; }; freevstring(&syll);