From d107aecaa349192c6ba59fea41fdc314e3a02f95 Mon Sep 17 00:00:00 2001 From: "Henry So, Jr." Date: Thu, 5 Jan 2017 13:50:59 -0500 Subject: [PATCH 1/3] Added [nocustos] to suppress an end-of-line custos at that point. Fixes #1271. --- doc/Command_Index_gregorio.tex | 8 ++++ doc/Command_Index_internal.tex | 6 --- src/dump/dump.c | 3 ++ src/gabc/gabc-notes-determination.l | 3 ++ src/gabc/gabc-write.c | 3 ++ src/gregoriotex/gregoriotex-write.c | 60 +++++++++++++++++++---------- src/struct.c | 7 ++++ src/struct.h | 3 ++ tex/gregoriotex-main.tex | 14 +++---- tex/gregoriotex-syllable.tex | 4 +- 10 files changed, 76 insertions(+), 35 deletions(-) diff --git a/doc/Command_Index_gregorio.tex b/doc/Command_Index_gregorio.tex index 22fab9474..9910c42eb 100644 --- a/doc/Command_Index_gregorio.tex +++ b/doc/Command_Index_gregorio.tex @@ -692,6 +692,14 @@ \section{Gregorio Controls} & \textit{empty} & The custos should not have an alteration.\\ \end{argtable} +\macroname{\textbackslash GreSuppressEolCustos}{}{gregoriotex-main.tex} +Macro which disables automatic custos at the end of lines. + +\macroname{\textbackslash GreResetEolCustos}{}{gregoriotex-main.tex} +Alias that resets the use of automatic custos to the value set by +\verb=\greseteolcustos=. This macro is aliased to \verb=\gre@useautoeolcustos= +or \verb=\GreSuppressEolCustos= by \verb=\greseteolcustos=. + \macroname{\textbackslash GreNextSyllableBeginsEUOUAE}{\#1\#2}{gregoriotex-syllable.tex} Indicates that the syllable which follows begins a EUOUAE block. diff --git a/doc/Command_Index_internal.tex b/doc/Command_Index_internal.tex index 496b22a43..c26b8b281 100644 --- a/doc/Command_Index_internal.tex +++ b/doc/Command_Index_internal.tex @@ -760,9 +760,6 @@ \section{Gregorio\TeX{} Controls} \macroname{\textbackslash gre@prephepisemaledgerlineheuristics}{}{gregoriotex-spaces.tex} Prepares the system to accept ledger line heuristics for the horizontal episema. -\macroname{\textbackslash gre@reseteolcustos}{}{gregoriotex-main.tex} -Alias that resets the use of automatic custos to the value set by \verb=\greseteolcustos=. This macro is aliased to \verb=\gre@useautoeolcustos= or \verb=\gre@usemanualeolcustos= by \verb=\greseteolcustos=. - \macroname{\textbackslash gre@resetledgerlineheuristics}{}{gregoriotex-spaces.tex} Resets the ledger line heuristic flags. @@ -832,9 +829,6 @@ \section{Gregorio\TeX{} Controls} \macroname{\textbackslash gre@useautoeolcustos}{}{gregoriotex-main.tex} Macro which enables automatic custos at the end of lines. -\macroname{\textbackslash gre@usemanualeolcustos}{}{gregoriotex-main.tex} -Macro which disables automatic custos at the end of lines. - \macroname{\textbackslash gre@usestylecommon}{}{gregoriotex-signs.tex} Macro which specifies the alternate glyphs which are common to all of the styles. diff --git a/src/dump/dump.c b/src/dump/dump.c index f7afa7a9e..fbf8645e4 100644 --- a/src/dump/dump.c +++ b/src/dump/dump.c @@ -259,6 +259,9 @@ void dump_write_score(FILE *f, gregorio_score *score) fprintf(f, " force_pitch true\n"); } break; + case GRE_SUPPRESS_CUSTOS: + /* not handling this would generate an error below */ + break; case GRE_SPACE: if (element->u.misc.unpitched.info.space) { char *factor = element->u.misc.unpitched.info. diff --git a/src/gabc/gabc-notes-determination.l b/src/gabc/gabc-notes-determination.l index 5c552d405..47b6b032b 100644 --- a/src/gabc/gabc-notes-determination.l +++ b/src/gabc/gabc-notes-determination.l @@ -1138,6 +1138,9 @@ void gabc_det_notes_finish(void) ¬es_lloc); } [\t\r\n]+ /* ignore ends of line and tabs */; +\[nocustos\] { + gregorio_add_suppress_custos_as_note(¤t_note, ¬es_lloc); + } z0 { gregorio_add_custos_as_note(¤t_note, ¬es_lloc); } diff --git a/src/gabc/gabc-write.c b/src/gabc/gabc-write.c index f568cb601..31b11c949 100644 --- a/src/gabc/gabc-write.c +++ b/src/gabc/gabc-write.c @@ -976,6 +976,9 @@ static void gabc_write_gregorio_element(FILE *f, gregorio_element *element, fprintf(f, "z0"); } break; + case GRE_SUPPRESS_CUSTOS: + fprintf(f, "[nocustos]"); + break; case GRE_NLBA: switch (element->u.misc.unpitched.info.nlba) { case NLBA_BEGINNING: diff --git a/src/gregoriotex/gregoriotex-write.c b/src/gregoriotex/gregoriotex-write.c index de3376cd4..97e91be5d 100644 --- a/src/gregoriotex/gregoriotex-write.c +++ b/src/gregoriotex/gregoriotex-write.c @@ -60,6 +60,8 @@ typedef struct gregoriotex_status { /* indicates if there is "above lines text" on the line */ bool abovelinestext; + + bool suppressed_custos; } gregoriotex_status; #define UNDETERMINED_HEIGHT -127 @@ -2435,14 +2437,18 @@ static __inline const char *alteration_name( } static const char *next_custos(const signed char next_note_pitch, - const gregorio_shape next_note_alteration) + const gregorio_shape next_note_alteration, + gregoriotex_status *const status) { - static char buf[30]; + static char buf[50]; - gregorio_snprintf(buf, sizeof buf, "\\GreNextCustos{%d}{%s}", + gregorio_snprintf(buf, sizeof buf, "%s\\GreNextCustos{%d}{%s}", + status->suppressed_custos? "\\GreResetEolCustos" : "", pitch_value(next_note_pitch), alteration_name(next_note_alteration)); + status->suppressed_custos = false; + return buf; } @@ -2452,7 +2458,8 @@ static const char *next_custos(const signed char next_note_pitch, static void write_note(FILE *f, gregorio_note *note, const gregorio_glyph *glyph, const char next_note_pitch, - const gregorio_shape next_note_alteration) + const gregorio_shape next_note_alteration, + gregoriotex_status *const status) { unsigned int initial_shape = note->u.note.shape; const char *shape; @@ -2507,7 +2514,8 @@ static void write_note(FILE *f, gregorio_note *note, fprintf(f, "\\GreGlyph{%s}{%d}{%s}{%d}", code_point(shape, glyph->u.notes.is_cavum, cpbuf, sizeof cpbuf), pitch_value(note->u.note.pitch), - next_custos(next_note_pitch, next_note_alteration), type); + next_custos(next_note_pitch, next_note_alteration, status), + type); break; } } @@ -2951,10 +2959,10 @@ static __inline void write_composed_multinote_glyph(FILE *const f, const bool has_next = current_note->next != NULL; if (has_next) { write_note(f, current_note, glyph, current_note->next->u.note.pitch, - S_UNDETERMINED); + S_UNDETERMINED, status); } else { write_note(f, current_note, glyph, next_note_pitch, - next_note_alteration); + next_note_alteration, status); } write_signs(f, T_ONE_NOTE, glyph, current_note, has_next ? 0 : fuse_to_next_note, status, score); @@ -3022,7 +3030,8 @@ static void write_glyph(FILE *const f, const gregorio_syllable *const syllable, fprintf(f, "\\GreGlyph{%s}{%d}{%s}{%d}", code_point(shape, glyph->u.notes.is_cavum, cpbuf, sizeof cpbuf), pitch_value(glyph->u.notes.first_note->u.note.pitch), - next_custos(next_note_pitch, next_note_alteration), type); + next_custos(next_note_pitch, next_note_alteration, status), + type); write_signs(f, gtype, glyph, glyph->u.notes.first_note, fuse_to_next_note, status, score); } else { @@ -3038,7 +3047,8 @@ static void write_glyph(FILE *const f, const gregorio_syllable *const syllable, fprintf(f, "\\GreGlyph{%s}{%d}{%s}{%d}", code_point(shape, glyph->u.notes.is_cavum, cpbuf, sizeof cpbuf), pitch_value(glyph->u.notes.first_note->u.note.pitch), - next_custos(next_note_pitch, next_note_alteration), type); + next_custos(next_note_pitch, next_note_alteration, status), + type); write_signs(f, gtype, glyph, glyph->u.notes.first_note, fuse_to_next_note, status, score); break; @@ -3056,7 +3066,8 @@ static void write_glyph(FILE *const f, const gregorio_syllable *const syllable, code_point(shape, glyph->u.notes.is_cavum, cpbuf2, sizeof cpbuf2), pitch_value(glyph->u.notes.first_note->u.note.pitch), - next_custos(next_note_pitch, next_note_alteration), type); + next_custos(next_note_pitch, next_note_alteration, status), + type); glyph->u.notes.first_note = current_note; glyph->u.notes.glyph_type = G_TORCULUS_RESUPINUS_FLEXUS; write_signs(f, gtype, glyph, glyph->u.notes.first_note, @@ -3118,7 +3129,7 @@ static void write_glyph(FILE *const f, const gregorio_syllable *const syllable, case G_STROPHA_AUCTA: case G_ALTERATION: write_note(f, glyph->u.notes.first_note, glyph, next_note_pitch, - next_note_alteration); + next_note_alteration, status); write_signs(f, T_ONE_NOTE, glyph, current_note, fuse_to_next_note, status, score); break; @@ -3141,7 +3152,8 @@ static void write_glyph(FILE *const f, const gregorio_syllable *const syllable, code_point(shape, glyph->u.notes.is_cavum, cpbuf2, sizeof cpbuf2), pitch_value(glyph->u.notes.first_note->u.note.pitch), - next_custos(next_note_pitch, next_note_alteration), type); + next_custos(next_note_pitch, next_note_alteration, status), + type); glyph->u.notes.first_note = current_note; glyph->u.notes.glyph_type = G_TORCULUS_RESUPINUS; write_signs(f, gtype, glyph, glyph->u.notes.first_note, @@ -3152,7 +3164,8 @@ static void write_glyph(FILE *const f, const gregorio_syllable *const syllable, fprintf(f, "\\GreGlyph{%s}{%d}{%s}{%d}", code_point(shape, glyph->u.notes.is_cavum, cpbuf, sizeof cpbuf), pitch_value(glyph->u.notes.first_note->u.note.pitch), - next_custos(next_note_pitch, next_note_alteration), type); + next_custos(next_note_pitch, next_note_alteration, status), + type); write_signs(f, gtype, glyph, glyph->u.notes.first_note, fuse_to_next_note, status, score); break; @@ -3931,8 +3944,8 @@ static void write_syllable(FILE *f, gregorio_syllable *syllable, syllable, element, NULL, &next_note_alteration) - element->u.misc.clef.pitch_difference); - fputs(next_custos(next_note_pitch, - next_note_alteration), f); + fputs(next_custos(next_note_pitch, next_note_alteration, + status), f); gregoriotex_print_change_line_clef(f, element); } else { /* the third argument is 0 or 1 according to the need @@ -3961,10 +3974,9 @@ static void write_syllable(FILE *f, gregorio_syllable *syllable, signed char next_note_pitch; gregorio_shape next_note_alteration; const char *alteration = ""; - /* - * We don't print custos before a bar at the end of a line - */ - /* we also print an unbreakable larger space before the custo */ + /* We don't print custos before a bar at the end of a line. + * We also print an unbreakable larger space before the + * custos */ handle_last_of_voice(f, syllable, element, *last_of_voice); next_note_pitch = gregorio_determine_next_pitch(syllable, element, NULL, &next_note_alteration); @@ -3973,11 +3985,18 @@ static void write_syllable(FILE *f, gregorio_syllable *syllable, } fprintf(f, "\\GreCustos{%d}{%s}%s%%\n", pitch_value(element->u.misc.pitched.pitch), alteration, - next_custos(next_note_pitch, next_note_alteration)); + next_custos(next_note_pitch, next_note_alteration, + status)); ++note_unit_count; } break; + case GRE_SUPPRESS_CUSTOS: + handle_last_of_voice(f, syllable, element, *last_of_voice); + fprintf(f, "\\GreSuppressEolCustos %%\n"); + status->suppressed_custos = true; + break; + case GRE_BAR: handle_last_of_voice(f, syllable, element, *last_of_voice); write_bar(f, score, syllable, element, first_of_disc); @@ -4058,6 +4077,7 @@ static void initialize_score(gregoriotex_status *const status, status->bottom_line = false; status->top_height = status->bottom_height = UNDETERMINED_HEIGHT; status->abovelinestext = status->translation = false; + status->suppressed_custos = false; /* first pass to compute positioning */ for (syllable = score->first_syllable; syllable; diff --git a/src/struct.c b/src/struct.c index 4e7a3c65e..43fc32f03 100644 --- a/src/struct.c +++ b/src/struct.c @@ -252,6 +252,13 @@ void gregorio_add_manual_custos_as_note(gregorio_note **current_note, add_pitched_item_as_note(current_note, GRE_MANUAL_CUSTOS, pitch, loc); } +void gregorio_add_suppress_custos_as_note(gregorio_note **current_note, + const gregorio_scanner_location *const loc) +{ + gregorio_note *element = create_and_link_note(current_note, loc); + element->type = GRE_SUPPRESS_CUSTOS; +} + void gregorio_add_clef_as_note(gregorio_note **current_note, gregorio_clef clef, signed char clef_line, bool flatted, const gregorio_scanner_location *const loc) diff --git a/src/struct.h b/src/struct.h index 41fe4e860..3ea7ae134 100644 --- a/src/struct.h +++ b/src/struct.h @@ -76,6 +76,7 @@ typedef struct gregorio_scanner_location { E(GRE_BAR) \ E(GRE_CUSTOS) \ E(GRE_MANUAL_CUSTOS) \ + E(GRE_SUPPRESS_CUSTOS) \ /* I don't really know how I could use the a TEXVERB_NOTE in gregoriotex, * as we don't write note by note... */ \ /* GRE_TEXVERB_NOTE, */ \ @@ -852,6 +853,8 @@ void gregorio_add_custos_as_note(gregorio_note **current_note, const gregorio_scanner_location *loc); void gregorio_add_manual_custos_as_note(gregorio_note **current_note, signed char pitch, const gregorio_scanner_location *loc); +void gregorio_add_suppress_custos_as_note(gregorio_note **current_note, + const gregorio_scanner_location *loc); void gregorio_add_clef_as_note(gregorio_note **current_note, gregorio_clef clef, signed char clef_line, bool flatted, const gregorio_scanner_location *loc); diff --git a/tex/gregoriotex-main.tex b/tex/gregoriotex-main.tex index 2479b3966..14cdd2192 100644 --- a/tex/gregoriotex-main.tex +++ b/tex/gregoriotex-main.tex @@ -328,7 +328,7 @@ \fi % \gre@adjustlineifnecessary\relax % %% - \gre@reseteolcustos\relax % + \GreResetEolCustos\relax % }% \def\gre@mark@translation{\directlua{gregoriotex.mark_translation()}}% @@ -1187,7 +1187,7 @@ \ifhmode\par\fi % \gre@beginningofscoretrue% \global\gre@dimen@morawidth=0pt\relax % - \gre@reseteolcustos% + \GreResetEolCustos% \gre@resetledgerlineheuristics% \global\setluatexattribute\gre@attr@glyph@id{0}% \global\setluatexattribute\gre@attr@syllable@id{0}% @@ -1334,7 +1334,7 @@ %blank line removing algorithm (in lua) will let some blank space after the %last line... (see bug #20953) \global\gre@endofscoretrue % - \gre@usemanualeolcustos% + \GreSuppressEolCustos% \gre@debugmsg{eolshift}{set lastoflinecount to 1}% \relax% }% @@ -1375,7 +1375,7 @@ % Flag indicating if we block the custos. We just block custos at the end of a score, to prevent a bug. \newif\ifgre@blockeolcustos% -\def\gre@usemanualeolcustos{% +\def\GreSuppressEolCustos{% \gre@blockeolcustostrue% \gre@localrightbox{}% }% @@ -1385,9 +1385,9 @@ \def\greseteolcustos#1{% \IfStrEqCase{#1}{% {manual}% - {\global\let\gre@reseteolcustos\gre@usemanualeolcustos\relax}% + {\global\let\GreResetEolCustos\GreSuppressEolCustos\relax}% {auto}% - {\global\let\gre@reseteolcustos\gre@useautoeolcustos\relax}% + {\global\let\GreResetEolCustos\gre@useautoeolcustos\relax}% }[% all other cases \gre@error{Unrecognized option "#1" for \protect\greseteolcustos\MessageBreak Possible options are: 'manual' and 'auto'}% ]% @@ -1691,7 +1691,7 @@ \gre@in@euouaetrue % % as soon as the EUOUAE starts, we stop blocking the EOL custos that might % have been blocked on the prior syllable. - \gre@reseteolcustos % + \GreResetEolCustos % } \def\GreEndEUOUAE#1{% diff --git a/tex/gregoriotex-syllable.tex b/tex/gregoriotex-syllable.tex index 945b4f03d..6b51fcec2 100644 --- a/tex/gregoriotex-syllable.tex +++ b/tex/gregoriotex-syllable.tex @@ -1068,7 +1068,7 @@ \def\GreNextSyllableBeginsEUOUAE#1#2{% \GreNoBreak % \ifgre@blockeolcustosbeforeeuouae % - \gre@usemanualeolcustos % + \GreSuppressEolCustos % \fi % \ifgre@raggedbreakbeforeeuouae % \directlua{gregoriotex.save_euouae(#1,1)}% @@ -1575,7 +1575,7 @@ \def\GreUpcomingNewLineForcesCustos#1{% \ifcase#1\relax % 0 - forced off - \gre@usemanualeolcustos % + \GreSuppressEolCustos % \or % 1 - forced on \gre@useautoeolcustos % \GreNextCustos{\gre@nextcustospitch}{\gre@nextcustosalteration}% From a635d69422f104aa025face3bca9bd956394c491 Mon Sep 17 00:00:00 2001 From: "Henry So, Jr." Date: Fri, 6 Jan 2017 06:43:22 -0500 Subject: [PATCH 2/3] Added a change log entry for [nocustos]. Fixes #1271. --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3f15c6074..067009c5b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,7 +29,8 @@ As of v3.0.0 this project adheres to [Semantic Versioning](http://semver.org/). - More general support for protrusions. The `` tag in gabc indicates where a protrusion should begin. There is an optional argument `` that allows the protrusion factor to be specified (in this example, `.5`). Additionally, the comma, semicolon, colon, and period are automatically protruded, with configurable protrusion factors. See GregorioRef and [#931](https://github.com/gregorio-project/gregorio/issues/931) for more information. - `minimalinitialwidth` space, controlling the minimum amount of space an initial should take require; ignored when `manualinitialwidth` is set to something non-zero (see [#1213](https://github.com/gregorio-project/gregorio/issues/1213)). - new scripts in `contrib/` to check the syllabation of a gabc score against hyphenation rules, such as those on [hyphen-la](https://github.com/gregorio-project/hyphen-la) -- the visibility of a particular nabc voice can now be set by `\gresetnabc{n}{(in)visible}` (where `n` is the number of the nabc voice), see (see [#1257](https://github.com/gregorio-project/gregorio/issues/1257)). +- the visibility of a particular nabc voice can now be set by `\gresetnabc{n}{(in)visible}`, where `n` is the number of the nabc voice (see [#1257](https://github.com/gregorio-project/gregorio/issues/1257)). +- `[nocustos]` may be used in gabc to prevent a custos should the line end at that point (see [#1271](https://github.com/gregorio-project/gregorio/issues/1271)). ### Deprecated - '\gresethyphenprotrusion{percentage}`, supplanted by `\gresetprotrusionfactor{eolhyphen}{factor}`. Note that the value the new command takes is a factor rather than a percentage. From 65a30c2c7c664e9b2fe561923697d5a94ea6b25f Mon Sep 17 00:00:00 2001 From: "Henry So, Jr." Date: Fri, 6 Jan 2017 14:10:06 -0500 Subject: [PATCH 3/3] Added documentation for [nocustos] in GregorioRef. Fixes #1271. --- doc/Gabc.tex | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/doc/Gabc.tex b/doc/Gabc.tex index 4e5d168cd..5f1091024 100644 --- a/doc/Gabc.tex +++ b/doc/Gabc.tex @@ -181,6 +181,15 @@ \subsubsection{Mode Headers} {\scriptsize\verb=t. irregularis=} & & & \writemode{t. irregularis}{}{} \\ \end{tabularx} +\subsection{General Syntax} + +\subsection{Note Syntax} + +\verb=[nocustos]= will prevent a custos from appearing at the point where +specified, if line formatting causes a line break there. The \verb=[nocustos]= +tag must appear \emph{before} spaces appearing at the point specified or it will +have no effect. + \subsection{Neume Fusion} Neume fusion allows for the composition of new shapes based on a set of