From: Han-Wen Nienhuys Date: Sat, 21 Sep 2002 14:12:08 +0000 (+0000) Subject: front port X-Git-Tag: release/1.7.0~2 X-Git-Url: https://git.donarmstrong.com/?a=commitdiff_plain;h=9f3df01392cdaf8120bf67c5034e507242be90e7;p=lilypond.git front port --- diff --git a/ChangeLog b/ChangeLog index 71cf1f201c..d983fe9c29 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,76 @@ +2002-09-21 Han-Wen Nienhuys + + * scm/tex.scm (header-end): enclose lily output in begingroup/endgroup. + + * tex/lilyponddefs.tex: set hsize for plain tex, but only for + positive line widths. + +2002-09-20 Jan Nieuwenhuizen + + * tex/lilyponddefs.tex: Handle \scoreshift and \outputscale in one + go. Fix comments. + + * cygwin: Cygwin updates. + +2002-09-19 Han-Wen Nienhuys + + * Documentation/windows/installing.texi (Top): version for python, + urls for ghostscript (thanks to John Potelle) + + * lily/simultaneous-music-iterator.cc + (Simultaneous_music_iterator): init children_list_ before + triggering GC. + + * lily/*-iterator.cc: be even more careful with smobbed copy + constructors. + + * lily/break-align-engraver.cc (acknowledge_grob): also typeset + LeftEdge item. + +2002-09-15 Werner Lemberg + + Improving LilyPond's output to make them ordinary TeX boxes with + predictable dimensions. System boxes are now vertically centered on + the baseline; this offset can be further controlled with + \lilypondscoreshift. + + * lily/system.cc (System::post_processing): Pass length of current + system to `start-system' (including any horizontal indentation). + + * scm/tex.scm, scm/pdftex.scm: Make output of various functions + prettier. + (lily-def): Append `%'. + (start-system): Add parameter `wd'. Output more TeX code to specify + box dimensions. + (stop-system, stop-last-system): Complement changes in + `start-system'. + * scm/sketch.scm, scm/ps.scm, scm/pdf.scm, scm/ascii-script.scm: + Updated. + + * scripts/ly2dvi.py (global_latex_definition): Set \parindent to 0. + * buildscripts/mf-to-table.py (write_tex_defs): Append `%'. + Write final `\endinput'. + + * tex/lily-ps-defs.tex, tex/lily-pdf-defs.tex, + tex/lilypond-plaintex.tex, tex/lilypond-latex.tex, + tex/lilyponddefs.tex, tex/titledefs.tex: Reformat code. Assure that + files and macro definitions don't produce spurious spaces and + paragraphs (using \endlinechar). + * tex/lilyponddefs.tex: New dimension `\scoreshift'. + + * Documentation/user/internals.itely: Improved formatting, fixing + typos. Added a section `Output details' to describe how the TeX + code looks like. + +2002-09-17 Rune Zedeler + + * lily/accidental-engraver.cc: Also work with partial measures. + +2002-09-17 Han-Wen Nienhuys + + * lily/text-spanner-engraver.cc: whoops. Set bound in the correct + spanner. + 2002-09-21 Han-Wen Nienhuys * lily/identifier-smob.cc (unpack_identifier): new file. @@ -30,519 +103,3 @@ * VERSION (MY_PATCH_LEVEL): make 1.7.0 - * Documentation/user/refman.itely: patch by Graham Percival - - * scripts/lilypond-book.py (make_pixmap): let gs write to - outputfile directly - -2002-09-15 Han-Wen Nienhuys - - * lily/simultaneous-music-iterator.cc - (Simultaneous_music_iterator): init children_list_ - - * lily/part-combine-music-iterator.cc - (Part_combine_music_iterator): init state_ - - * lily/sequential-iterator.cc (Sequential_iterator): init cursor_ - - * lily/percent-repeat-iterator.cc (Percent_repeat_iterator): init - child_iter_. - - * lily/sequential-iterator.cc (Sequential_iterator): init list_ - - * lily/translator-def.cc (Translator_def): make a GC proof copy - constructor. - -2002-09-14 Han-Wen Nienhuys - - * lily/percent-repeat-iterator.cc (process): quit iter. - - * lily/simultaneous-music-iterator.cc - (Simultaneous_music_iterator): protection bugfix. - (get_pending_events): bugfix: don't use s twice. - - * debian/: debian patches by Anthony Fok. - - * lily/clef-engraver.cc (create_clef): bugfix for octavate clef - (thanks Rune!) - - * Documentation/user/tutorial.itely: replace grob by - object. Explain \once. - - * scm/music-property-description.scm (once): add 'once - -2002-09-13 Han-Wen Nienhuys - - * lily/simultaneous-music-iterator.cc (skip): call quit() - when an iterator exits early. - -2002-09-13 Juergen Reuter - - * lily/rests.ly: added comment on bogus warnings about missing flags - - * lily/clef.cc, lily/rests.cc: added warning when font character - lookup fails. - - * lily/rests.cc: workaround: consider missing ledgered rests in - ancient font. - - * lily/rests.cc: bugfix: cleaned up font lookup code that handles - special cases of styles 'default' and 'classical'. This should - also fix the behaviour of lily/multi-measure-rest.cc, which so far - did not consider styles 'default' and 'classical'. - -2002-09-13 Rune Zedeler - - * scm/drums.scm: "set" the automatic properties instead of - "override", (whoops!) - -2002-09-13 Mats Bengtsson - - * ly/a3-init.ly, scripts/ly2dvi.py (ly_paper_to_latexpaper): - Add support for A3 paper. - -2002-09-13 Han-Wen Nienhuys - - * lily/tuplet-bracket.cc (brew_molecule): don't crash on broken - tuplet brackets. - - * lily/property-iterator.cc (do_quit): add finalization functions - to undo property settings. - - * lily/parser.yy (property_def): syntax for \once \property .... - - * lily/note-spacing.cc (get_spacing): don't get crazy when there - is no (live) stem. - - * lily/my-lily-lexer.cc: new keyword \once - - * lily/global-translator.cc (apply_finalizations): new function - (add_finalization): new function - - * input/regression/property-once.ly: new file - -2002-09-10 Juergen Reuter - - * lily/stem.cc: added warning when font symbol not found; - small cleanups - -2002-09-11 Han-Wen Nienhuys - - * mf/GNUmakefile: make PFA for sauter CM fonts. - -2002-09-10 Han-Wen Nienhuys - - * mf/GNUmakefile: make map file for pfa target as well. - - * scm/tex.scm (end-output): add newline to output - - * lily/include/sequential-iterator.hh (class Sequential_iterator): - don't use Protected_scm for music-iterator members. - - * lily/music-iterator.cc (Music_iterator): initialize music_ - - -2002-09-09 Juergen Reuter - - * input/test/accid.ly: updated test file to show all available - accidentals styles - - * lily/accidental.cc, lily/key-signature-interface.cc, - lily/include/accidental-interface.hh: added method - get_fontcharname() to provide proper fall-back cases for missing - accidentals; print warning if font char lookup fails - - * lily/time-signature.cc: fixed documentation bug - -2002-09-09 Han-Wen Nienhuys - - * lily/music-iterator.cc (quit, do_quit): new function: break link - to translator group explicitly. This used to be done from the - destructor of music-iterator. Now that iterators are GC'd, this is - no longer possible. Add new function do_quit() to all applicable - derived classes. - - * lily/lyric-combine-music-iterator.cc (construct_children): don't - unprotect objects. - (Lyric_combine_music_iterator): small typo bugfix. - - * lily/musical-request.cc: do ADD_MUSIC for String_number_req. - - * lily/include/lily-guile.hh (scm_remember_upto_here_1): add glue - - * lily/sequential-iterator.cc (get_pending_events): don't delete - music-iterator. - -2002-09-08 Rune Zedeler - - * scm/music-property-description.scm: describe string-number (whoops) - - * Documentation/user/refman.itely: Tablature and bar number updates - -2002-09-08 Han-Wen Nienhuys - - * lily/lyric-combine-music-iterator.cc - (Lyric_combine_music_iterator): small bugfix - - * lily/include/simultaneous-music-iterator.hh (class - Simultaneous_music_iterator): use SCM list for list of iterators. - - * lily/cxx-function-smob.cc: remove file. - - * lily/include/cxx-function-smob.hh: remove file. - - * lily/include/music-iterator.hh (class Music_iterator): smobify - music-iterator; many changes throughout. They are now constructed - through procedures that return to the smobbed iterator. - - * lily/include/*.hh: all derived_mark() functions are now const. - - * lily/syllable-group.cc (set_lyric_align): remove conditional - again. - - * Documentation/bibliography/computer-notation.bib (note): add - Beyond MIDI and The Virtual Score. - -2002-09-07 Rune Zedeler - - * input/sondag-morgen/*.ly: Tablature fixes - - * ly/performer-init.ly: BUGFIX: add alias Timing to Score context - - * lily/parser.yy and lily/lexer.ll: Use E_UNSIGNED instead of E_DIGIT - - * lily/musical-request.cc (String_number_req): Added - - * lily/tab-note-heads-engraver.cc: Use String_number_req instead - of Text_script_req; read properties stringOneTopmost and - highStringOne. - - * ly/engraver-init.ly (tabStaffContext): Bugfix: remove Key_engraver; - set stringOneTopmost and highStringOne to #t - - * scm/output-lib.scm (tablature-stem-attachment-function): Changed - (guitar-tunings): List added - ((every-nth-bar-number-visible n) barnum): Instead of - default-bar-number-visibility - ((every-nth-bar-number-visible n) barnum): added - - * scm/grob-description.scm (TabNoteHead): Extra-offset added (UGH!) - - * scm/translator-property-description.scm: Added new functions - - * input/test/tablature.ly: Changed to better demonstrate possibilities. - - * input/test/bar-number-every-fifth: Use new function - -2002-09-07 Han-Wen Nienhuys - - * scripts/lilypond-book.py: revert pre use for python - 2.2. Document why. - -2002-09-07 Jeremie Lumbroso - - * Documentation/user/refman.itely: very minor corrections and - rephrasing of the reference manual -- revision up to line #400. - - * Documentation/user/refman.itely: replaced all occurrence "staffs" - with "staves". - -2002-09-07 Han-Wen Nienhuys - - * lily/lexer.ll: scan E_DIGIT - - * lily/parser.yy (string_request): use E_DIGIT for string requests - - * lily/beam.cc (get_thickness): new function - - * ly/performer-init.ly (ScoreContext): add Timing alias - - * lily/translator-def.cc (Translator_def): copy alias list too. - - * lily/stem.cc (height): add half beam thickness for beamed stems. - This fixes tuplet bracket vertical offsets on beams. - - * lily/text-spanner-engraver.cc (stop_translation_timestep): small - cleanups; only hang spanner on paper-columns if there are no - note-columns to hang on. Also hang finished spanner on the last - note. - - * lily/tuplet-bracket.cc (calc_position_and_height): only quantize - inside staff. - -2002-09-07 Rune Zedeler - - * scm/output-lib.scm: (default-bar-number-visibility) added - - * ly/engraver-init.ly (ScoreContext) set barNumberVisibility to - #default-bar-number-visibility - -2002-09-06 Han-Wen Nienhuys - - * input/test/poly-metric.ly: update to use Timing. - - * lily/bar-number-engraver.cc (process_music): only run - barNumberVisibility if currentBarNumber is a number. - - * lily/parser.yy (chord_inversion): use CHORD_SLASH for '/' - (command_element): use Timing as alias for Score. - -2002-09-06 Jeremie Lumbroso - - * Documentation/user/refman.itely: minor corrections (replacing - `grob' by `object'), addition of an example in the tablature - section. - -2002-09-06 Han-Wen Nienhuys - - * VERSION: 1.6.2 released - - * input/test/empty-staffs.ly: new file. - - * Documentation/topdocs/INSTALL.texi: adds a bit of information - about compiling in OpenBSD. (Graham Percival) - -2002-09-05 Han-Wen Nienhuys - - * scm/documentation-lib.scm (scm->string): don't crash if a - procedure doesn't have a name. - -2002-09-05 Juergen Reuter - - * input/test/custos.ly: updated test file to show all available - custos styles - - * lily/custos.cc: small code clean-ups - - * input/test/rests.ly: updated test file to show all available - rest styles - - * mf/feta-eindelijk.mf: bugfix: added missing maxima rest - -2002-09-05 Rune Zedeler - - * scm/output-lib.scm (make-molecule-boxer): Fixed and moved from - input/test/boxed-molecule.ly - - * input/test/boxed-molecule.ly: Fixed to use default - make-molecule-boxer - - * input/test/bar-number-every-fifth.ly: Added - - * lily/bar-number-engraver.cc: Add property barNumberVisibility - and use it to decide which BarNumbers to suicide. - -2002-09-05 Han-Wen Nienhuys - - * input/test/poly-metric.ly: new file. - - * scripts/lilypond-book.py (output_verbatim): python 2.2 workaround. - - * scm/documentation-lib.scm (scm->string): print procedure name in - stead of # - - * scripts/ly2dvi.py (run_lilypond): exit with error if lily exited - any file with an error. - - * input/regression/molecule-hacking.ly: also restore Y - extent. Fixes bugs with stem attachment of parenthesized note - heads. - -2002-09-04 Han-Wen Nienhuys - - * input/test/clef-end-of-line.ly: new file. - - * lily/stem-engraver.cc (acknowledge_grob): warn about too long - tremolos. Thanks to Erik Sandberg - - * input/trip.ly (fugaIIPedal): small cleanups. - - * lily/grob-pq-engraver.cc: more helpful message. - (stop_translation_timestep): use scm_merge_x for merging the lists. - - * Documentation/user/appendices.itely: switch off parmesan listing - -2002-09-01 Juergen Reuter - - * input/test/ancient-font.ly, input/test/ancient-time.ly, - input/test/mensural-ligatures.ly, lily/ligature-head.cc, - lily/mensural-ligature-engraver.cc, lily/note-head.cc, - lily/time-signature.cc, scm/output-lib.scm: removed obsolete - code that sets grob property font-family; also small updates to - various input/test files. - -2002-09-01 Han-Wen Nienhuys - - * input/test/tab-staff.ly: removed. - - * lily/paper-def.cc (find_font): load virtual font for a list of - font names. - - * scm/font.scm (paper20-style-sheet-alist): equate ancient and - music font-families. - - * lily/virtual-font-metric.cc (get_char_molecule): new function - - * lily/system-start-delimiter.cc (staff_brace): use virtual fonts - for the list of braces - - * lily/font-metric.cc (get_char_molecule): new function. - -2002-08-31 Han-Wen Nienhuys - - * lily/virtual-font-metric.cc: new file - - * lily/include/virtual-font-metric.hh (class Virtual_font_metric): - new file - - * scripts/lilypond-book.py: use old re's for python 2.2 as well - - * debian/control: Debian patches by Anthony Fok - - * input/regression/lyric-combine-polyphonic.ly: new file. - - * ly/engraver-init.ly (VoiceContext): add Grob_pq_engraver to - Voice context. - -2002-08-31 Graham Percival - - * Documentation/user/tutorial.itely: editorial changes - (spelling, grammar, etc) of the orchestral score, integrating text + - music, and the end of tutorial. - -2002-08-31 Rune Zedeler - - * input/test/sondag-morgen/*.ly: 1.6 compatibility knee fixes - - * lily/tab-note-heads-engraver.cc: Bugfix for instruments not - having 6 strings. - -2002-08-31 Han-Wen Nienhuys - - * VERSION: 1.6.1 released - - * lily/kpath.cc: - * lily/lily-guile.cc: macosx fixes. - - * lily/script-column.cc (before_line_breaking): use stable sorting - algorithm to preserve script ordering. - (grob_script_priority_less): new function - - * lily/script-engraver.cc (process_music): - * lily/text-engraver.cc (process_acknowledged_grobs): - * lily/fingering-engraver.cc (make_script): don't use direction - for script-priority. This fixes orderings for multiple down - script/fingering. - - * scripts/ly2dvi.py (run_lilypond): don't exit if LilyPond fails, - but try to assemble the files anyway. - - * input/regression/prefatory-empty-spacing.ly: new file. - - * lily/break-align-interface.cc (do_alignment): translate last - break-align-group if it is invisible/empty. - - * scm/grob-description.scm (all-grob-descriptions): LeftEdge is - not a BreakAlignGroup. Do not use - Break_align_interface::alignment_callback - -2002-08-30 Han-Wen Nienhuys - - * scripts/lilypond-book.py (LatexPaper.find_latex_dims): give more - meaningful error if running latex fails - - * Documentation/user/refman.itely (Tablatures): small - corrections. Thanks to Karl Berry - -2000-08-30 Heikki Junes - - * make/lilypond.mandrake.spec.in: Mandrake adaptations from - redhat spec and rpm-skeleton found in Mandrake's home page. - -2002-08-29 Graham Percival - - * Documentation/user/tutorial.itely: editorial changes (spelling, - grammar, etc) of the "Fine tuning" section. - -2002-08-29 Juergen Reuter - - * input/test/ancient-font.ly, mf/parmesan-heads.mf, - scm/output-lib.scm, lily/note-head.cc: bugfix: make neume note - heads accessible - -2002-08-29 Mats Bengtsson - - * scm/music-functions.scm (unfold-repeats): Call new - shift-duration-log correctly also for unfolded repeats. - -2002-08-27 Mats Bengtsson - - * tex/titledefs.tex: Define \fetafont for use in titles. - - * scm/music-functions.scm (shift-duration-log), lily/parser.yy - (Repeated_music): Handle dots correctly for \repeat tremolo. - -2002-08-26 Han-Wen Nienhuys - - * lily/score.cc: remove paranoia code. - - * lily/parser.yy: don't include malloc.h - -2002-08-25 Han-Wen Nienhuys - - * flower/polynomial.cc (operator +): optimize += operator. No - copying. - - * lily/source-file.cc (get_line): use binary search to determine - line number. This kills another quadratic time-complexity term. - - * lily/include/source-file.hh (class Source_file): add newline_locations - - * flower/include/array.icc (binary_search_bounds): new function. - -2002-08-22 Han-Wen Nienhuys - - * input/regression/tuplet-properties.ly (texidoc): bugfix - - * input/regression/beam-shortened-lengths.ly: add \stemUp - - * Documentation/user/refman.itely: - -2002-08-22 Tom Cato - - * Documentation/user/refman.itely: spelling fix. - -2002-08-21 Jan Nieuwenhuizen - - * lily/main.cc (setup_paths): Prepend dirs to search path, instead - of appending. Fixes build when typical LilyPond 1.4 leftovers clutter - the system. - - * flower/include/file-path.hh (prepend): New function. - -2002-08-20 Han-Wen Nienhuys - - * Documentation/misc/ChangeLog-1.5: move 1.5 ChangeLog to misc/ - - * lily/completion-note-heads-engraver.cc (class - Completion_heads_engraver): don't be confused by polyphonic rhythms. - - * input/regression/completion-heads-polyphony.ly: new file. - -2002-08-19 Han-Wen Nienhuys - - * GNUmakefile.in (web-ext): distribute .ly with web tarball too. - This means that the 1.6 binaries must be rebuilt. - - * make/lilypond-vars.make: banish ps-to-X scripts - - * make/generic-rules.make: remove blurb rule. - - * GNUmakefile.in: make lilypond-fource file, so PK fonts are not - removed every make-run. - - * make/ly-rules.make: don't remove .tely file. - - * input/test/chords.ly (scales): whole notes only. Prevents - weird breaks. - diff --git a/Documentation/user/internals.itely b/Documentation/user/internals.itely index b15d2fa5bf..c60766df94 100644 --- a/Documentation/user/internals.itely +++ b/Documentation/user/internals.itely @@ -17,39 +17,41 @@ phases. We list them here: @c todo: moved from refman. The purpose of LilyPond is explained informally by the term `music -typesetter'. This is not a fully correct name: not only does the +typesetter'. This is not a fully correct name: Not only does the program print musical symbols, it also makes aesthetic decisions. Symbols and their placements are @emph{generated} from a high-level musical description. In other words, LilyPond would be best described -by `music compiler' or `music to notation compiler'. +to be a `music compiler' or `music to notation compiler'. LilyPond is linked to GUILE, GNU's Scheme library for extension -programming. The Scheme library provides the glue that holds together +programming. The Scheme library provides the glue that holds together the low-level routines and separate modules which are written in C++. When lilypond is run to typeset sheet music, the following happens: + @itemize @bullet -@item GUILE Initialization: various scheme files are read -@item parsing: first standard @code{ly} initialization files are read, and +@item GUILE initialization: Various scheme files are read. + +@item Parsing: First standard @code{ly} initialization files are read, then the user @file{ly} file is read. -@item interpretation: the music in the file is processed ``in playing -order'', i.e. the order that you use to read sheet music, or the -order in which notes are played. The result of this step is a typesetting -specification. -@item typesetting: -The typesetting specification is solved: positions and formatting is -calculated. +@item Interpretation: The music in the file is processed `in playing +order', i.e., the order that you use to read sheet music, or the +order in which notes are played. The result of this step is a +typesetting specification. -@item the visible results ("virtual ink") are written to the output file. +@item Typesetting: The typesetting specification is solved: positions +and formatting is calculated. + +@item The visible results ("virtual ink") are written to the output file. @end itemize During these stages different types of data play the the main role: -during parsing, @strong{Music} objects are created. During the +During parsing, @strong{Music} objects are created. During the interpretation, @strong{contexts} are constructed, and with these -contexts a network of @strong{graphical objects} (``grobs'') is -created. These grobs contain unknown variables, and the network forms a -set of equations. After solving the equations and filling in these +contexts a network of @strong{graphical objects} (`grobs') is +created. These grobs contain unknown variables, and the network forms a +set of equations. After solving the equations and filling in these variables, the printed output is written to an output file. These threemanship of tasks (parsing, translating, typesetting) and @@ -57,61 +59,56 @@ data-structures (music, context, graphical objects) permeates the entire design of the program. - @table @b -@item Parsing: +@item Parsing -The LY file is read, and converted to a list of @code{Scores}, which -each contain @code{Music} and paper/midi-definitions. Here @code{Music}, -@code{Pitch} and @code{Duration} objects are created. +The @code{ly} file is read and converted to a list of @code{Scores}, which +each contain @code{Music} and paper/midi-definitions. Here @code{Music}, +@code{Pitch}, and @code{Duration} objects are created. @item Interpreting music @cindex interpreting music -All music events are "read" in the same order as they would be played -(or read from paper). At every step of the interpretation, musical -events are delivered to -interpretation contexts, +All music events are `read' in the same order as they would be played +(or read from paper). At every step of the interpretation, musical +events are delivered to interpretation contexts, @cindex engraver -which use them to build @code{Grob}s (or MIDI objects, for MIDI output). +which use them to build @code{Grob}s (or MIDI objects for MIDI output). In this stage @code{Music_iterators} do a traversal of the @code{Music} -structure. The music events thus encountered are reported to +structure. The music events thus encountered are reported to @code{Translator}s, a set of objects that collectively form interpretation contexts. - @item Prebreaking - @cindex prebreaking At places where line breaks may occur, clefs and bars are prepared for a possible line break. @item Preprocessing - @cindex preprocessing In this stage, all information that is needed to determine line breaking is computed. -@item Break calculation: +@item Break calculation The lines and horizontal positions of the columns are determined. @item Breaking Relations between all grobs are modified to reflect line breaks: When a -spanner, e.g. a slur, crosses a line-break, then the spanner is "broken -into pieces", for every line that the spanner is in, a copy of the grob -is made. A substitution process redirects all grob-reference so that +spanner, e.g. a slur, crosses a line break, then the spanner is `broken +into pieces'; for every line that the spanner is in, a copy of the grob +is made. A substitution process redirects all grob references so that each spanner grob will only reference other grobs in the same line. -@item Outputting: +@item Outputting All vertical dimensions and spanning objects are computed, and all grobs -are output, line by line. The output is encoded in the form of +are output, line by line. The output is encoded in the form of @code{Molecule}s @end table @@ -120,13 +117,13 @@ The data types that are mentioned here are all discussed in this section. - @c FIXME: Note entry vs Music entry at top level menu is confusing. @c . {Music entry} @menu * Interpretation context:: * Syntactic details:: * Lexical details:: +* Output details:: @end menu @@ -145,35 +142,38 @@ section. Interpretation contexts are objects that only exist during a run of LilyPond. During the interpretation phase of LilyPond (when it prints -"interpreting music"), the music expression in a @code{\score} block is -interpreted in time order. This is the same order that humans hear and -play the music. +@code{interpreting music} to standard output), the music expression in +a @code{\score} block is interpreted in time order. This is the same +order that humans hear and play the music. During this interpretation, the interpretation context holds the -state for the current point within the music. It contains information +state for the current point within the music. It contains information like @itemize @bullet - @item What notes are playing at this point? - @item What symbols will be printed at this point? - @item What is the current key signature, time signature, point within - the measure, etc.? +@item What notes are playing at this point? + +@item What symbols will be printed at this point? + +@item What is the current key signature, time signature, point within +the measure, etc.? @end itemize Contexts are grouped hierarchically: A @internalsref{Voice} context is contained in a @internalsref{Staff} context (because a staff can contain multiple voices at any point), a @internalsref{Staff} context is contained in -@internalsref{Score}, @internalsref{StaffGroup}, or @internalsref{ChoirStaff} context. +@internalsref{Score}, @internalsref{StaffGroup}, or +@internalsref{ChoirStaff} context. Contexts associated with sheet music output are called @emph{notation contexts}, those for sound output are called @emph{performance -contexts}. The default definitions of the standard notation and +contexts}. The default definitions of the standard notation and performance contexts can be found in @file{ly/engraver-init.ly} and @file{ly/performer-init.ly}, respectively. + @node Creating contexts @subsection Creating contexts - @cindex @code{\context} @cindex context selection @@ -181,11 +181,12 @@ Contexts for a music expression can be selected manually, using the following music expression. @example - \context @var{contexttype} [= @var{contextname}] @var{musicexpr} +\context @var{contexttype} [= @var{contextname}] @var{musicexpr} @end example +@noindent This instructs lilypond to interpret @var{musicexpr} within the context - of type @var{contexttype} and with name @var{contextname}. If this +of type @var{contexttype} and with name @var{contextname}. If this context does not exist, it will be created. @lilypond[verbatim,singleline] @@ -194,9 +195,9 @@ context does not exist, it will be created. c4 f } } - @end lilypond +@noindent In this example, the @code{c} and @code{d} are printed on the default staff. For the @code{e}, a context Staff called @code{another} is specified; since that does not exist, a new @@ -206,15 +207,13 @@ context is finished, the context is ended as well. So after the third quarter, @code{another} is removed. - @node Default contexts @subsection Default contexts Most music expressions don't need an explicit @code{\context} -declaration: they inherit the -notation context from their parent. Each note is a music expression, and -as you can see in the following example, only the sequential music -enclosing the three notes has an explicit context. +declaration: they inherit the notation context from their parent. Each +note is a music expression, and as you can see in the following example, +only the sequential music enclosing the three notes has an explicit context. @lilypond[verbatim,singleline] \score { \notes \context Voice = goUp { c'4 d' e' } } @@ -223,30 +222,32 @@ enclosing the three notes has an explicit context. There are some quirks that you must keep in mind when dealing with defaults: -First, every top level music is interpreted by the Score context, in other +First, every top level music is interpreted by the Score context; in other words, you may think of @code{\score} working like + @example - \score @{ - \context Score @var{music} - @} +\score @{ + \context Score @var{music} +@} @end example Second, contexts are created automatically to be able to interpret the -music expressions. Consider the following example. +music expressions. Consider the following example. @lilypond[verbatim, singleline] -\score { \context Score \notes { c'4 ( d' )e' } } +\score { \context Score \notes { c'4 ( d' )e' } } @end lilypond +@noindent The sequential music is interpreted by the Score context initially (notice that the @code{\context} specification is redundant), but when a -note is encountered, contexts are setup to accept that note. In this -case, a Thread, Voice and Staff are created. The rest of the sequential -music is also interpreted with the same Thread, Voice and Staff context, -putting the notes on the same staff, in the same voice. +note is encountered, contexts are setup to accept that note. In this +case, a Thread, Voice, and Staff context are created. The rest of the +sequential music is also interpreted with the same Thread, Voice, and +Staff context, putting the notes on the same staff, in the same voice. This is a convenient mechanism, but do not expect opening chords to work -without @code{\context}. For every note, a separate staff is +without @code{\context}. For every note, a separate staff is instantiated. @cindex explicit context @@ -260,73 +261,78 @@ instantiated. Of course, if the chord is preceded by a normal note in sequential music, the chord will be interpreted by the Thread of the preceding note: + @lilypond[verbatim,singleline] -\score { \notes { c'4 } } +\score { \notes { c'4 } } @end lilypond - @node Context properties @subsection Context properties -Notation contexts have properties. These properties are from -the @file{.ly} file using the following expression: +Notation contexts have properties. These properties are from +the @file{.ly} file using the following expression: @cindex @code{\property} + @example - \property @var{contextname}.@var{propname} = @var{value} +\property @var{contextname}.@var{propname} = @var{value} @end example +@noindent Sets the @var{propname} property of the context @var{contextname} to the specified Scheme expression @var{value}. All @var{propname} and @var{contextname} are strings, which are typically unquoted. Properties that are set in one context are inherited by all of the contained contexts. This means that a property valid for the -@internalsref{Voice} context can be set in the @internalsref{Score} context (for -example) and thus take effect in all @internalsref{Voice} contexts. +@internalsref{Voice} context can be set in the @internalsref{Score} context +(for example) and thus take effect in all @internalsref{Voice} contexts. @cindex @code{Current} If you don't wish to specify the name of the context in the -@code{\property}-expression -itself, you can refer to the abstract context name, -@code{Current}. The @code{Current} context is the latest -used context. This will typically mean the @internalsref{Thread} +@code{\property}-expression itself, you can refer to the abstract context +name, @code{Current}. The @code{Current} context is the latest +used context. This will typically mean the @internalsref{Thread} context, but you can force another context with the -@code{\property}-command. Hence the expressions +@code{\property}-command. Hence the expressions @example - \property @var{contextname}.@var{propname} = @var{value} +\property @var{contextname}.@var{propname} = @var{value} @end example +@noindent and @example - \context @var{contextname} - \property Current.@var{propname} = @var{value} +\context @var{contextname} +\property Current.@var{propname} = @var{value} @end example +@noindent do the same thing. -The main use for this is in macros - allowing the specification of a +The main use for this is in macros -- allowing the specification of a property-setting without restriction to a specific context. Properties can be unset using the following expression: + @example - \property @var{contextname}.@var{propname} \unset +\property @var{contextname}.@var{propname} \unset @end example @cindex properties, unsetting @cindex @code{\unset} -This removes the definition of @var{propname} in @var{contextname}. If +@noindent +This removes the definition of @var{propname} in @var{contextname}. If @var{propname} was not defined in @var{contextname} (but was inherited from a higher context), then this has no effect. - @refbugs The syntax of @code{\unset} is asymmetric: @code{\property \unset} is not the inverse of @code{\property \set}. + @node Engravers and performers @subsection Engravers and performers @@ -336,75 +342,87 @@ Basic building blocks of translation are called engravers; they are special C++ classes. - @node Changing context definitions @subsection Changing context definitions - @cindex context definition @cindex translator definition The most common way to define a context is by extending an existing -context. You can change an existing context from the paper block, by +context. You can change an existing context from the paper block by first initializing a translator with an existing context identifier: + @example \paper @{ \translator @{ @var{context-identifier} - @} @} + @} +@} @end example + +@noindent Then you can add and remove engravers using the following syntax: + @example - \remove @var{engravername} - \consists @var{engravername} +\remove @var{engravername} +\consists @var{engravername} @end example - +@noindent Here @var{engravername} is a string, the name of an engraver in the system. - @lilypond[verbatim,singleline] -\score { \notes { - c'4 c'4 } +\score { + \notes { + c'4 c'4 + } \paper { - \translator { \StaffContext - \remove Clef_engraver - } } } + \translator { + \StaffContext + \remove Clef_engraver + } + } +} @end lilypond @cindex engraver -You can also set properties in a translator definition. The syntax is as +You can also set properties in a translator definition. The syntax is as follows: + @example - @var{propname} = @var{value} - @var{propname} \set @var{grob-propname} = @var{pvalue} - @var{propname} \override @var{grob-propname} = @var{pvalue} - @var{propname} \revert @var{grob-propname} +@var{propname} = @var{value} +@var{propname} \set @var{grob-propname} = @var{pvalue} +@var{propname} \override @var{grob-propname} = @var{pvalue} +@var{propname} \revert @var{grob-propname} @end example + +@noindent @var{propname} is a string, @var{grob-propname} a symbol, @var{value} -and @code{pvalue} are Scheme expressions. These type of property +and @code{pvalue} are Scheme expressions. These types of property assignments happen before interpretation starts, so a @code{\property} command will override any predefined settings. - - To simplify editing translators, all standard contexts have standard +To simplify editing translators, all standard contexts have standard identifiers called @var{name}@code{Context}, e.g. @code{StaffContext}, -@code{VoiceContext}, see @file{ly/engraver-init.ly}. +@code{VoiceContext}; see @file{ly/engraver-init.ly}. + @node Defining new contexts @subsection Defining new contexts If you want to build a context from scratch, you must also supply the following extra information: + @itemize @bullet - @item A name, specified by @code{\name @var{contextname}}. +@item A name, specified by @code{\name @var{contextname}}. - @item A cooperation module. This is specified by @code{\type +@item A cooperation module. This is specified by @code{\type @var{typename}}. @end itemize This is an example: + @example \translator @code{ \type "Engraver_group_engraver" @@ -416,52 +434,52 @@ This is an example: }@ @end example +@noindent The argument of @code{\type} is the name for a special engraver that handles cooperation between simple engravers such as -@code{Note_head_engraver} and @code{Staff_symbol_engraver}. Alternatives +@code{Note_head_engraver} and @code{Staff_symbol_engraver}. Alternatives for this engraver are the following: + @table @code @cindex @code{Engraver_group_engraver} - @item @code{Engraver_group_engraver} - The standard cooperation engraver. -@cindex @code{Score_engraver} - - @item @code{Score_engraver} - This is cooperation module that should be in the top level context, -and only the top level context. +@item @code{Engraver_group_engraver} +The standard cooperation engraver. +@cindex @code{Score_engraver} +@item @code{Score_engraver} +This is a cooperation module that should be in the top level context. @end table -Other modifiers are +Other modifiers are @itemize @bullet - @item @code{\alias} @var{alternate-name} - This specifies a different name. In the above example, +@item @code{\alias} @var{alternate-name}: +This specifies a different name. In the above example, @code{\property Staff.X = Y} will also work on @code{SimpleStaff}s - @item @code{\consistsend} @var{engravername} - Analogous to @code{\consists}, but makes sure that - @var{engravername} is always added to the end of the list of - engravers. +@item @code{\consistsend} @var{engravername}: +Analogous to @code{\consists}, but makes sure that +@var{engravername} is always added to the end of the list of +engravers. - Some engraver types need to be at the end of the list; this - insures they stay there even if a user adds or removes engravers. +Some engraver types need to be at the end of the list; this +insures they stay there even if a user adds or removes engravers. End-users generally don't need this command. - @item @code{\accepts} @var{contextname} - Add @var{contextname} to the list of contexts this context can - contain in the context hierarchy. The first listed context is the - context to create by default. +@item @code{\accepts} @var{contextname}: +Add @var{contextname} to the list of contexts this context can +contain in the context hierarchy. The first listed context is the +context to create by default. - @item @code{\denies}. The opposite of @code{\accepts}. Added for +@item @code{\denies}: +The opposite of @code{\accepts}. Added for completeness, but is never used in practice. - - - @item @code{\name} @var{contextname} - This sets the type name of the context, e.g. @internalsref{Staff}, - @internalsref{Voice}. If the name is not specified, the translator won't do - anything. + +@item @code{\name} @var{contextname}: +This sets the type name of the context, e.g. @internalsref{Staff}, +@internalsref{Voice}. If the name is not specified, the translator won't do +anything. @end itemize In the @code{\paper} block, it is also possible to define translator @@ -469,7 +487,6 @@ identifiers. Like other block identifiers, the identifier can only be used as the very first item of a translator. In order to define such an identifier outside of @code{\score}, you must do -@quotation @example \paper @{ foo = \translator @{ @dots{} @} @@ -484,9 +501,6 @@ such an identifier outside of @code{\score}, you must do @} @end example -@end quotation - - @cindex paper types, engravers, and pre-defined translators @@ -509,18 +523,18 @@ This section describes details that were too boring to be put elsewhere. @c . {Identifiers} @node Identifiers @subsection Identifiers -@cindex Identifiers +@cindex Identifiers @ignore - What has this section got to do with identifiers? - It seems more appropriate in the introduction to Chapter 4, - "Internals". +What has this section got to do with identifiers? +It seems more appropriate in the introduction to Chapter 4, +"Internals". - /MB + /MB @end ignore -All of the information in a LilyPond input file, is internally -represented as a Scheme value. In addition to normal Scheme data types +All of the information in a LilyPond input file is internally +represented as a Scheme value. In addition to normal Scheme data types (such as pair, number, boolean, etc.), LilyPond has a number of specialized data types, @@ -537,25 +551,27 @@ specialized data types, @item Moment (rational number) @end itemize -LilyPond also includes some transient object types. Objects of these +LilyPond also includes some transient object types. Objects of these types are built during a LilyPond run, and do not `exist' per se within -your input file. These objects are created as a result of your input +your input file. These objects are created as a result of your input file, so you can include commands in the input to manipulate them, -during a lilypond run. +during a LilyPond run. @itemize @bullet -@item Grob: short for Graphical object. -@item Molecule: device-independent page output object, -including dimensions. Produced by some Grob functions -@item Translator: object that produces audio objects or Grobs. This is -not yet user accessible. -@item Font_metric: object representing a font. +@item Grob: short for `Graphical object'. + +@item Molecule: Device-independent page output object, +including dimensions. Produced by some Grob functions. + +@item Translator: An object that produces audio objects or Grobs. This is +not yet user-accessible. + +@item Font_metric: An object representing a font. @end itemize @node Music expressions @subsection Music expressions - @cindex music expressions Music in LilyPond is entered as a music expression. Notes, rests, lyric @@ -577,72 +593,83 @@ quarter note @code{d}: @cindex Simultaneous music @cindex @code{\simultaneous} -The two basic compound music expressions are simultaneous and +The two basic compound music expressions are simultaneous and sequential music. @example - \sequential @code{@{} @var{musicexprlist} @code{@}} - \simultaneous @code{@{} @var{musicexprlist} @code{@}} +\sequential @code{@{} @var{musicexprlist} @code{@}} +\simultaneous @code{@{} @var{musicexprlist} @code{@}} @end example + For both, there is a shorthand: + @example - @code{@{} @var{musicexprlist} @code{@}} +@code{@{} @var{musicexprlist} @code{@}} @end example + +@noindent for sequential and + @example - @code{<} @var{musicexprlist} @code{>} +@code{<} @var{musicexprlist} @code{>} @end example + +@noindent for simultaneous music. In principle, the way in which you nest sequential and simultaneous to produce music is not relevant. In the following example, three chords are expressed in two different ways: @lilypond[fragment,verbatim,center] - \notes \context Voice { - - < { a b c' } { c' d' e' } > - } +\notes \context Voice { + + < { a b c' } { c' d' e' } > +} @end lilypond - Other compound music expressions include + @example - \repeat @var{expr} - \transpose @var{pitch} @var{expr} - \apply @var{func} @var{expr} - \context @var{type} = @var{id} @var{expr} - \times @var{fraction} @var{expr} +\repeat @var{expr} +\transpose @var{pitch} @var{expr} +\apply @var{func} @var{expr} +\context @var{type} = @var{id} @var{expr} +\times @var{fraction} @var{expr} @end example @c . {Manipulating music expressions} @node Manipulating music expressions -@subsection Manipulating music expressions +@subsection Manipulating music expressions The @code{\apply} mechanism gives you access to the internal -representation of music. You can write Scheme-functions that operate -directly on it. The syntax is +representation of music. You can write Scheme-functions that operate +directly on it. The syntax is + @example - \apply #@var{func} @var{music} +\apply #@var{func} @var{music} @end example + +@noindent This means that @var{func} is applied to @var{music}. The function @var{func} should return a music expression. -This example replaces the text string of a script. It also shows a dump +This example replaces the text string of a script. It also shows a dump of the music it processes, which is useful if you want to know more about how music is stored. @lilypond[verbatim,singleline] #(define (testfunc x) - (if (equal? (ly-get-mus-property x 'text) "foo") - (ly-set-mus-property! x 'text "bar")) - ;; recurse - (ly-set-mus-property! x 'elements - (map testfunc (ly-get-mus-property x 'elements))) - (display x) - x -) -\score { \notes + (if (equal? (ly-get-mus-property x 'text) "foo") + (ly-set-mus-property! x 'text "bar")) + ;; recurse + (ly-set-mus-property! x 'elements + (map testfunc (ly-get-mus-property x 'elements))) + (display x) + x) + +\score { + \notes \apply #testfunc { c'4_"foo" } } @end lilypond @@ -650,8 +677,7 @@ about how music is stored. For more information on what is possible, see the automatically generated documentation. - -Directly accessing internal representations is dangerous: the +Directly accessing internal representations is dangerous: The implementation is subject to changes, so you should avoid this feature if possible. @@ -670,7 +696,8 @@ A final example is a function that reverses a piece of music in time: music = \notes { c'4 d'4( e'4 f'4 } -\score { \context Voice { +\score { + \context Voice { \music \apply #reverse-music \music } @@ -680,6 +707,7 @@ music = \notes { c'4 d'4( e'4 f'4 } More examples are given in the distributed example files in @code{input/test/}. + @c . {Span requests} @menu * Span requests:: @@ -690,29 +718,28 @@ More examples are given in the distributed example files in @cindex Span requests Notational constructs that start and end on different notes can be -entered using span requests. The syntax is as follows: - +entered using span requests. The syntax is as follows: @example - \spanrequest @var{startstop} @var{type} +\spanrequest @var{startstop} @var{type} @end example - @cindex @code{\start} @cindex @code{\stop} -This defines a spanning request. The @var{startstop} parameter is either +@noindent +This defines a spanning request. The @var{startstop} parameter is either -1 (@code{\start}) or 1 (@code{\stop}) and @var{type} is a string that describes what should be started. Much of the syntactic sugar is a -shorthand for @code{\spanrequest}, for example, +shorthand for @code{\spanrequest}, for example @lilypond[fragment,verbatim,center] - c'4-\spanrequest \start "slur" - c'4-\spanrequest \stop "slur" +c'4-\spanrequest \start "slur" +c'4-\spanrequest \stop "slur" @end lilypond Among the supported types are @code{crescendo}, @code{decrescendo}, -@code{beam}, @code{slur}. This is an internal command. Users are +@code{beam}, @code{slur}. This is an internal command. Users are encouraged to use the shorthands which are defined in the initialization file @file{spanners.ly}. @@ -723,8 +750,8 @@ file @file{spanners.ly}. @cindex Assignments Identifiers allow objects to be assigned to names during the parse -stage. To assign an identifier, you use @var{name}@code{=}@var{value} -and to refer to an identifier, you precede its name with a backslash: +stage. To assign an identifier, use @var{name}@code{=}@var{value}. +To refer to an identifier, precede its name with a backslash: `@code{\}@var{name}'. @var{value} is any valid Scheme value or any of the input-types listed above. Identifier assignments can appear at top level in the LilyPond file, but also in @code{\paper} blocks. @@ -745,15 +772,19 @@ foo = \foo * 2.0 When an identifier is referenced, the information it points to is copied. For this reason, an identifier reference must always be the first item in a block. + @example -\paper @{ +\paper @{ foo = 1.0 \paperIdent % wrong and invalid @} +@end example +@example \paper @{ \paperIdent % correct - foo = 1.0 @} + foo = 1.0 +@} @end example @@ -768,49 +799,51 @@ first item in a block. @cindex @code{\lyrics} To simplify entering notes, lyrics, and chords, LilyPond has three -special input modes in addition to the default mode: note, lyrics and +special input modes in addition to the default mode: note, lyrics, and chords mode. These input modes change the way that normal, unquoted -words are interpreted: for example, the word @code{cis} may be +words are interpreted: For example, the word @code{cis} may be interpreted as a C-sharp, as a lyric syllable `cis' or as a C-sharp major triad respectively. A mode switch is entered as a compound music expression + @example @code{\notes} @var{musicexpr} @code{\chords} @var{musicexpr} -@code{\lyrics} @var{musicexpr}. +@code{\lyrics} @var{musicexpr} @end example +@noindent In each of these cases, these expressions do not add anything to the meaning of their arguments. They just instruct the parser in what mode to parse their arguments. Different input modes may be nested. + @c . {Ambiguities} @node Ambiguities @subsection Ambiguities @cindex ambiguities @cindex grammar - -The grammar contains a number of ambiguities. We hope to resolve them at +The grammar contains a number of ambiguities. We hope to resolve them at some time. @itemize @bullet - @item The assignment +@item The assignment @example foo = bar @end example - is interpreted as the string identifier assignment. However, + +@noindent +is interpreted as the string identifier assignment. However, it can also be interpreted as making a string identifier @code{\foo} containing @code{"bar"}, or a music identifier @code{\foo} containing the syllable `bar'. The former interpretation is chosen. - @item If you do a nested repeat like - - @quotation +@item If you do a nested repeat like @example \repeat @dots{} @@ -818,19 +851,18 @@ the syllable `bar'. The former interpretation is chosen. \alternative @end example - @end quotation - - then it is ambiguous to which @code{\repeat} the - @code{\alternative} belongs. This is the classic if-then-else - dilemma. It may be solved by using braces. - +@noindent +then it is ambiguous to which @code{\repeat} the +@code{\alternative} belongs. This is the classic if-then-else +dilemma. It may be solved by using braces. @end itemize + @c . {Lexical details} @node Lexical details @section Lexical details -Even more boring details, now on lexical side of the input parser. +Even more boring details, now on the lexical side of the input parser. @menu * Direct Scheme:: @@ -841,46 +873,45 @@ Even more boring details, now on lexical side of the input parser. @node Direct Scheme @subsection Direct Scheme - @cindex Scheme @cindex GUILE @cindex Scheme, in-line code - - - -@cindex GUILE -@cindex Scheme @cindex accessing Scheme @cindex evaluating Scheme @cindex LISP -LilyPond internally uses GUILE, a Scheme-interpreter. Scheme is a -language from the LISP family. You can learn more about Scheme at -@uref{http://www.scheme.org}. It is used to represent data throughout -the whole program. The hash-sign (@code{#}) accesses GUILE directly: the +LilyPond internally uses GUILE, a Scheme-interpreter. Scheme is a +language from the LISP family. You can learn more about Scheme at +@uref{http://www.scheme.org}. It is used to represent data throughout +the whole program. The hash-sign (@code{#}) accesses GUILE directly: The code following the hash-sign is evaluated as Scheme. The boolean value @var{true} is @code{#t} in Scheme, so for LilyPond @var{true} looks like @code{##t}. LilyPond contains a Scheme interpreter (the GUILE library) for -internal use. In some places, Scheme expressions also form valid syntax: -wherever it is allowed, +internal use. In some places, Scheme expressions also form valid syntax: +Wherever it is allowed, + @example - #@var{scheme} +#@var{scheme} @end example + +@noindent evaluates the specified Scheme code. Example: + @example - \property Staff.TestObject \override #'foobar = #(+ 1 2) +\property Staff.TestObject \override #'foobar = #(+ 1 2) @end example -@code{\override} expects two Scheme expressions, so there are two Scheme -expressions. The first one is a symbol (@code{foobar}), the second one + +@code{\override} expects two Scheme expressions. +The first one is a symbol (@code{foobar}), the second one an integer (namely, 3). -In-line scheme may be used at the top level. In this case the result is +In-line Scheme may be used at the top level. In this case the result is discarded. Scheme is a full-blown programming language, and a full discussion is -outside the scope of this document. Interested readers are referred to +outside the scope of this document. Interested readers are referred to the website @uref{http://www.schemers.org/} for more information on Scheme. @@ -904,7 +935,7 @@ by a @emph{required} decimal point and an optional exponent such as A real constant can be followed by one of the dimension keywords: @code{\mm} @code{\pt}, @code{\in}, or @code{\cm}, for millimeters, points, inches and centimeters, respectively. This converts the number -a number that is the internal representation of that dimension. +that is the internal representation of that dimension. @node Strings @@ -918,3 +949,87 @@ sequences have special interpretations as in the C language. A string that contains no spaces can be written without the quotes. Strings can be concatenated with the @code{+} operator. + +@c . {Output details} +@node Output details +@section Output details + +LilyPond's default output format is @TeX{}. Using the option @option{-f} +(or @option{--format}) other output formats can be selected also, but +currently none of them reliably work. + +At the beginning of the output file, various global parameters are defined. +It also contains a large @code{\special} call to define PostScript routines +to draw items not representable with @TeX{}, mainly slurs and ties. A DVI +driver must be able to understand such embedded PostScript, or the output +will be rendered incompletely. + +Then the file @file{lilyponddefs.tex} is loaded to define the macros used +in the code which follows. @file{lilyponddefs.tex} includes various other +files, partially depending on the global parameters. + +Now the music is output system by system (a `system' consists of all +staves belonging together). From @TeX{}'s point of view, a system is an +@code{\hbox} which contains a lowered @code{\vbox} so that it is centered +vertically on the baseline of the text. Between systems, +@code{\interscoreline} is inserted vertically to have stretchable space. +The horizontal dimension of the @code{\hbox} is given by the +@code{linewidth} parameter from LilyPond's @code{\paper} block (using the +natural line width if its value is@w{ }@minus{}1). + +After the last system LilyPond emits a stronger variant of +@code{\interscoreline} only if the macro @code{\lilypondpaperlastpagefill} +is not defined (flushing the systems to the top of the page). You can +avoid that manually by saying + +@example +\def\lilypondpaperlastpagefill@{1@} +@end example + +@noindent +or by setting the variable @code{lastpagefill} in LilyPond's @code{\paper} +block. + +It is possible to fine-tune the vertical offset further by defining the +macro @code{\lilypondscoreshift}. Example: + +@example +\def\lilypondscoreshift@{0.25\baselineskip@} +@end example + +@noindent +@code{\baselineskip} is the distance from one text line to the next. + +The code produced by LilyPond can be used by both @TeX{} and La@TeX{}. + +Here an example how to embed a small LilyPond file @code{foo.ly} into +running La@TeX{} text without using the @code{lilypond-book} script +(@pxref{Integrating text and music with lilypond-book}). + +@example +\documentclass@{article@} + +\def\lilypondpaperlastpagefill@{@} +\lineskip 5pt +\def\lilypondscoreshift@{0.25\baselineskip@} + +\begin@{document@} +This is running text which includes an example music file +\input@{foo.tex@} +right here. +\end@{document@} +@end example + +The file @file{foo.tex} has been simply produced with + +@example +lilypond foo.ly +@end example + +It is important to set the @code{indent} parameter to zero in the +@code{\paper} block of @file{foo.ly}. + +The call to @code{\lineskip} assures that there is enough vertical space +between the LilyPond box and the surrounding text lines. + +@c EOF diff --git a/Documentation/windows/installing.texi b/Documentation/windows/installing.texi index 43088e2c3e..0a751d8990 100644 --- a/Documentation/windows/installing.texi +++ b/Documentation/windows/installing.texi @@ -63,7 +63,9 @@ You can use GSView-2.6. This old package has two advantages. It has gsview and ghostscript bundeled, and it doesn't popup @emph{Register Now|Cancel} windows all the time. -Install @uref{ftp://ftp.cs.wisc.edu/ghost/ghostgum/gsv26w32.exe, GSView-2.6} (GhostView for Windows), or visit +Install +@uref{ftp://mirror.cs.wisc.edu/pub/mirrors/ghost/aladdin/gs550/gsv27550.exe,GSView-2.7} +(GhostView for Windows), or visit @uref{ftp://ftp.cs.wisc.edu/ghost/ghostgum,ftp.cs.wisc.edu}. @c check/update versions @@ -403,7 +405,7 @@ following commands: @item Version info @quotation @example - python --version + python -V lilypond --version ly2dvi --version @end example diff --git a/NEWS b/NEWS index c6381820b6..128ad15be7 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,3 @@ - New features in 1.7 since 1.6 * Deeper integration of the input language and Scheme. You can now use diff --git a/buildscripts/mf-to-table.py b/buildscripts/mf-to-table.py index 5e9ed27a98..d8aa7275d9 100644 --- a/buildscripts/mf-to-table.py +++ b/buildscripts/mf-to-table.py @@ -120,7 +120,8 @@ Comment Automatically generated by mf-to-table.py def write_tex_defs (file, global_info, charmetrics): nm = global_info['FontFamily'] for m in charmetrics: - file.write (r'''\def\%s%s{\char%d}%s''' % (nm, m['tex'], m['code'],'\n')) + file.write (r'''\def\%s%s{\char%d}%%%s''' % (nm, m['tex'], m['code'],'\n')) + file.write ('\\endinput\n') def write_ps_encoding (file, global_info, charmetrics): encs = ['.notdef'] * 256 diff --git a/cygwin/README.in b/cygwin/README.in index 8afb8882cf..8db0f9e9a2 100644 --- a/cygwin/README.in +++ b/cygwin/README.in @@ -14,7 +14,7 @@ When it all works, head straight to the tutorial: Runtime requirements: cygwin-1.3.10 or newer - libguile14 + libguile12 bash libiconv2 libintl2 @@ -38,15 +38,15 @@ Build requirements: binutils-20011102 or newer gcc-2.95.3-5 or newer bison-1.35 or newer - guile-devel-1.5.6-5 or newer + guile-devel-1.6.0-1 or newer fileutils flex-2.5.4 or newer - libguile14-1.5.6-5 or newer - libkpathsea3-20020530-2 or newer + libguile12-1.6.0-1 or newer + libkpathsea3-20020911-1 or newer python-2.2 or newer sed-3.02 or newer sh-utils - tetex-devel-20020530-2 or newer + tetex-devel-20020911-1 or newer texinfo-4.2 or newer Website/documentation build requirements (lilypond-doc package): diff --git a/cygwin/bug-lilypond-cygwin.sh b/cygwin/bug-lilypond-cygwin.sh index 0db601ea82..1c61929e58 100644 --- a/cygwin/bug-lilypond-cygwin.sh +++ b/cygwin/bug-lilypond-cygwin.sh @@ -41,6 +41,7 @@ type -p lilypond.exe type -p python.exe lilypond --version +python -V ly2dvi --version diff --git a/cygwin/changelog b/cygwin/changelog index 5a87f40af7..bdd38dabaf 100644 --- a/cygwin/changelog +++ b/cygwin/changelog @@ -1,3 +1,15 @@ +lilypond (1.6.4-1) stable; urgency=low + + * New upstream release. + + -- Jan Nieuwenhuizen Fri, 20 Sep 2002 23:02:21 +0200 + +lilypond (1.6.0-1) stable; urgency=low + + * New upstream release. + + -- Jan Nieuwenhuizen Mon, 19 Aug 2002 16:03:02 +0200 + lilypond (1.5.73-1) unstable; urgency=low * New upstream release. diff --git a/cygwin/lilypond.hint b/cygwin/lilypond.hint index 4e9dcf9a37..e8c3ac0757 100644 --- a/cygwin/lilypond.hint +++ b/cygwin/lilypond.hint @@ -1,6 +1,6 @@ sdesc: "A program for printing sheet music" category: Publishing -requires: bash libguile14 libiconv2 libintl2 libkpathsea3 python tetex-bin tetex-tiny +requires: bash libguile12 libiconv2 libintl2 libkpathsea3 python tetex-bin tetex-tiny #requires: tetex-bin, tetex-tiny | tetex-base #suggests: emacs gsview lilypond-doc rxvt tetex-x11 XFree86-serv ldesc: "A program for printing sheet music. diff --git a/cygwin/mknetrel b/cygwin/mknetrel index b5698171fe..b2f32622b2 100644 --- a/cygwin/mknetrel +++ b/cygwin/mknetrel @@ -1,16 +1,16 @@ # -*- shell-script -*- -# stable LilyPond releases: lilypond-1.4 -# archive=ftp://lilypond.org/pub/LilyPond/v1.4 +# stable LilyPond releases: lilypond-1.6 +# archive=ftp://lilypond.org/pub/LilyPond/v1.6 -# LilyPond development: lilypond-1.5 -# archive=ftp://lilypond.org/pub/LilyPond/v1.5 +# LilyPond development: lilypond-1.7 +# archive=ftp://lilypond.org/pub/LilyPond/v1.7 # Guile specific mknetrel overrides # To use this, do something like: cat >/dev/null < guile-config <get_grob_property ("break-align-symbol"), edge); - announce_grob(edge, SCM_EOL); + edge_ = new Item (get_property ("LeftEdge")); + add_to_group (edge_->get_grob_property ("break-align-symbol"), edge_); + announce_grob(edge_, SCM_EOL); } add_to_group (align_name, item); diff --git a/lily/chord-tremolo-iterator.cc b/lily/chord-tremolo-iterator.cc index b4d7696968..fd456b6ac3 100644 --- a/lily/chord-tremolo-iterator.cc +++ b/lily/chord-tremolo-iterator.cc @@ -35,9 +35,12 @@ Chord_tremolo_iterator::Chord_tremolo_iterator (Chord_tremolo_iterator const &sr : Music_iterator (src) { factor_ = src.factor_; - child_iter_ = src.child_iter_ ? src.child_iter_->clone () : 0; - if (child_iter_) - scm_gc_unprotect_object (child_iter_->self_scm()); + child_iter_ = 0; + if (src.child_iter_) + { + child_iter_ = src.child_iter_->clone (); + scm_gc_unprotect_object (child_iter_->self_scm()); + } } void @@ -87,7 +90,5 @@ Chord_tremolo_iterator::try_music_in_children (Music *m) const return child_iter_->try_music (m); } - - IMPLEMENT_CTOR_CALLBACK (Chord_tremolo_iterator); diff --git a/lily/folded-repeat-iterator.cc b/lily/folded-repeat-iterator.cc index b2e07aed32..4c72fcf1b1 100644 --- a/lily/folded-repeat-iterator.cc +++ b/lily/folded-repeat-iterator.cc @@ -40,9 +40,15 @@ Folded_repeat_iterator::do_quit() Folded_repeat_iterator::Folded_repeat_iterator (Folded_repeat_iterator const &src) : Music_iterator (src) { - main_iter_ = src.main_iter_ ? src.main_iter_->clone () : 0; - alternative_iter_ = src.alternative_iter_ ? src.alternative_iter_->clone () : 0; + main_iter_ = 0; + alternative_iter_ = 0; main_length_mom_ = src.main_length_mom_; + + if (src.alternative_iter_) + alternative_iter_ = src.alternative_iter_->clone (); + if (src.main_iter_) + main_iter_ = src.main_iter_->clone (); + if (main_iter_) scm_gc_unprotect_object (main_iter_->self_scm()); if (alternative_iter_) diff --git a/lily/grob.cc b/lily/grob.cc index 382cbe2de7..4124e7ffc3 100644 --- a/lily/grob.cc +++ b/lily/grob.cc @@ -240,8 +240,11 @@ Grob::get_molecule () const mol = get_uncached_molecule (); - Grob *me = (Grob*)this; - me->set_grob_property ("molecule", mol); + if (live ()) + { + Grob *me = (Grob*)this; + me->set_grob_property ("molecule", mol); + } return unsmob_molecule (mol); } @@ -372,6 +375,13 @@ Grob::handle_broken_dependencies () void Grob::suicide () { + if (!live ()) + return; + +#if 0 // see below. + String nm = name(); +#endif + mutable_property_alist_ = SCM_EOL; immutable_property_alist_ = SCM_EOL; @@ -383,6 +393,19 @@ Grob::suicide () dim_cache_[a].offset_callbacks_ = SCM_EOL; dim_cache_[a].offsets_left_ = 0; } + +#if 0 + /* + This can make debugging a little easier: we can still know what + the object used to be. However, since all its links have been + broken, it's usually more convenient to set a conditional + breakpoint in GDB before the property lists are wiped. + */ + mutable_property_alist_ = scm_acons (ly_symbol2scm ("name"), + scm_makfrom0str (nm.to_str0()), + mutable_property_alist_ + ); +#endif } void diff --git a/lily/include/music.hh b/lily/include/music.hh index 87b4b93eda..b5cbab61a1 100644 --- a/lily/include/music.hh +++ b/lily/include/music.hh @@ -66,7 +66,5 @@ protected: DECLARE_UNSMOB(Music,music); -#endif // MUSIC_HH - - +#endif // MUSIC_HH diff --git a/lily/lily-guile.cc b/lily/lily-guile.cc index 4c1836df82..39bb53649a 100644 --- a/lily/lily-guile.cc +++ b/lily/lily-guile.cc @@ -204,6 +204,7 @@ ly_init_ly_module (void *data) scm_primitive_load_path (scm_makfrom0str ("lily.scm")); } + SCM lily_module ; void diff --git a/lily/lyric-combine-music-iterator.cc b/lily/lyric-combine-music-iterator.cc index 127945b3d6..e1c72a5e9d 100644 --- a/lily/lyric-combine-music-iterator.cc +++ b/lily/lyric-combine-music-iterator.cc @@ -136,8 +136,13 @@ Lyric_combine_music_iterator::do_quit () Lyric_combine_music_iterator::Lyric_combine_music_iterator (Lyric_combine_music_iterator const & src) : Music_iterator (src) { - lyric_iter_ = src.lyric_iter_ ? src.lyric_iter_->clone () : 0; - music_iter_ = src.music_iter_ ? src.music_iter_->clone () : 0; + lyric_iter_ = 0; + music_iter_ = 0; + + if (src.lyric_iter_) + lyric_iter_ = src.lyric_iter_->clone (); + if (src.music_iter_) + music_iter_ = src.music_iter_->clone (); if (lyric_iter_) scm_gc_unprotect_object (lyric_iter_->self_scm()); diff --git a/lily/music-wrapper-iterator.cc b/lily/music-wrapper-iterator.cc index 7798d65eaf..15ca7968f3 100644 --- a/lily/music-wrapper-iterator.cc +++ b/lily/music-wrapper-iterator.cc @@ -18,9 +18,12 @@ Music_wrapper_iterator::Music_wrapper_iterator () Music_wrapper_iterator::Music_wrapper_iterator (Music_wrapper_iterator const &src) : Music_iterator (src) { - child_iter_ = (src.child_iter_) ? src.child_iter_->clone () : 0; - if (child_iter_) + child_iter_ = 0; + if (src.child_iter_) + { + child_iter_ = src.child_iter_->clone () ; scm_gc_unprotect_object (child_iter_->self_scm()); + } } void @@ -30,7 +33,7 @@ Music_wrapper_iterator::do_quit() } void -Music_wrapper_iterator::derived_mark()const +Music_wrapper_iterator::derived_mark () const { if (child_iter_) scm_gc_mark (child_iter_->self_scm()); @@ -52,15 +55,6 @@ Music_wrapper_iterator::ok () const void Music_wrapper_iterator::skip (Moment m) { - /* - FIXME: should make sure that the initial try_music () is skipped as - well, if you would do - - iter = get_iterator (Side_effect_music); // eg. property setting - iter->skip (1/2) - iter->process () - - */ child_iter_->skip (m); } diff --git a/lily/part-combine-music-iterator.cc b/lily/part-combine-music-iterator.cc index 11a0a75bff..276e2f4271 100644 --- a/lily/part-combine-music-iterator.cc +++ b/lily/part-combine-music-iterator.cc @@ -45,8 +45,13 @@ Part_combine_music_iterator::do_quit () Part_combine_music_iterator::Part_combine_music_iterator (Part_combine_music_iterator const &src) : Music_iterator (src) { - first_iter_ = src.first_iter_ ? src.first_iter_->clone () : 0; - second_iter_ = src.second_iter_ ? src.second_iter_->clone () : 0; + first_iter_ = 0; + second_iter_ = 0; + + if(src.first_iter_) + first_iter_ = src.first_iter_->clone (); + if (src.second_iter_) + second_iter_ = src.second_iter_->clone (); first_until_ = src.first_until_; second_until_ = src.second_until_; diff --git a/lily/percent-repeat-iterator.cc b/lily/percent-repeat-iterator.cc index cc9c112ad8..d09e6c8f3b 100644 --- a/lily/percent-repeat-iterator.cc +++ b/lily/percent-repeat-iterator.cc @@ -17,7 +17,6 @@ IMPLEMENT_CTOR_CALLBACK (Percent_repeat_iterator); Percent_repeat_iterator::Percent_repeat_iterator () { child_iter_ = 0; - } void @@ -29,11 +28,14 @@ Percent_repeat_iterator::do_quit() Percent_repeat_iterator::Percent_repeat_iterator (Percent_repeat_iterator const & p) : Music_iterator (p) { - child_iter_ = p.child_iter_ ? p.child_iter_->clone (): 0; - finish_mom_ = p.finish_mom_ ; - - if(child_iter_) - scm_gc_unprotect_object (child_iter_->self_scm()); + child_iter_ = 0; + finish_mom_ = p.finish_mom_ ; + + if (p.child_iter_) + { + child_iter_ = p.child_iter_->clone (); + scm_gc_unprotect_object (child_iter_->self_scm()); + } } bool diff --git a/lily/sequential-iterator.cc b/lily/sequential-iterator.cc index 6817d3a0d5..798283abaa 100644 --- a/lily/sequential-iterator.cc +++ b/lily/sequential-iterator.cc @@ -66,10 +66,13 @@ Sequential_iterator::Sequential_iterator (Sequential_iterator const &src) cursor_ = src.cursor_; list_ = src.cursor_; here_mom_ = src.here_mom_; - iter_ = (src.iter_) ? src.iter_->clone () : 0; + iter_ = 0; - if (iter_) - scm_gc_unprotect_object (iter_->self_scm()); + if (src.iter_) + { + iter_ = src.iter_->clone (); + scm_gc_unprotect_object (iter_->self_scm()); + } } void diff --git a/lily/simultaneous-music-iterator.cc b/lily/simultaneous-music-iterator.cc index 957b7bb628..bdeb2a7f43 100644 --- a/lily/simultaneous-music-iterator.cc +++ b/lily/simultaneous-music-iterator.cc @@ -24,6 +24,7 @@ Simultaneous_music_iterator::Simultaneous_music_iterator (Simultaneous_music_ite { separate_contexts_b_ = src.separate_contexts_b_; + children_list_ = SCM_EOL; SCM children_list = SCM_EOL; SCM *tail = &children_list; diff --git a/lily/system.cc b/lily/system.cc index 2536331c4c..20f97023a8 100644 --- a/lily/system.cc +++ b/lily/system.cc @@ -275,7 +275,7 @@ System::break_into_pieces (Array const &breaking) { System *system = dynamic_cast (clone ()); system->rank_ = i; - // system->set_immutable_grob_property ("rank", gh_int2scm (i)); + Link_array c (breaking[i].cols_); pscore_->typeset_line (system); @@ -442,7 +442,11 @@ System::post_processing (bool last_line) /* line preamble. */ + Interval j (extent (this, X_AXIS)); + Real length = j[RIGHT]; + output_scheme (scm_list_n (ly_symbol2scm ("start-system"), + gh_double2scm (length), gh_double2scm (height), SCM_UNDEFINED)); diff --git a/lily/text-spanner-engraver.cc b/lily/text-spanner-engraver.cc index e0d1c5f0a7..7be64f5283 100644 --- a/lily/text-spanner-engraver.cc +++ b/lily/text-spanner-engraver.cc @@ -40,8 +40,6 @@ private: }; - - Text_spanner_engraver::Text_spanner_engraver () { finished_ = 0; @@ -142,11 +140,10 @@ Text_spanner_engraver::typeset_all () if (finished_) { Side_position_interface::add_staff_support (finished_); - if (!finished_->get_bound (RIGHT)) { Grob* e = unsmob_grob (get_property ("currentMusicalColumn")); - span_->set_bound (RIGHT, e); + finished_->set_bound (RIGHT, e); } typeset_grob (finished_); finished_ = 0; diff --git a/scm/ascii-script.scm b/scm/ascii-script.scm index 5f5c09752a..d25c819468 100644 --- a/scm/ascii-script.scm +++ b/scm/ascii-script.scm @@ -204,8 +204,8 @@ "") ; issue no command (func "select-font" (car name-mag-pair)))) -(define (start-system height) - (func "start-system" height)) +(define (start-system width height) + (func "start-system" width height)) (define (stop-system) (func "stop-system")) diff --git a/scm/lily.scm b/scm/lily.scm index f85bf23871..1bab46f71e 100644 --- a/scm/lily.scm +++ b/scm/lily.scm @@ -12,10 +12,9 @@ ;;; General settings ;; debugging evaluator is slower. -(debug-enable 'debug) +;(debug-enable 'debug) ;(debug-enable 'backtrace) -(read-enable 'positions) - +;(read-enable 'positions) (define-public (line-column-location line col file) @@ -83,7 +82,7 @@ (cons (f (car x)) (f (cdr x)))) ;; used where? -(define (reduce operator list) +(define-public (reduce operator list) "reduce OP [A, B, C, D, ... ] = A op (B op (C ... )) " @@ -121,7 +120,7 @@ is the first to satisfy CRIT (define (!= l r) (not (= l r))) -(define (filter-list pred? list) +(define-public (filter-list pred? list) "return that part of LIST for which PRED is true." (if (null? list) '() (let* ((rest (filter-list pred? (cdr list)))) @@ -129,7 +128,7 @@ is the first to satisfy CRIT (cons (car list) rest) rest)))) -(define (filter-out-list pred? list) +(define-public (filter-out-list pred? list) "return that part of LIST for which PRED is true." (if (null? list) '() (let* ((rest (filter-list pred? (cdr list)))) @@ -137,7 +136,7 @@ is the first to satisfy CRIT (cons (car list) rest) rest)))) -(define (uniqued-alist alist acc) +(define-public (uniqued-alist alist acc) (if (null? alist) acc (if (assoc (caar alist) acc) (uniqued-alist (cdr alist) acc) diff --git a/scm/output-lib.scm b/scm/output-lib.scm index 00c827595b..21a50dda79 100644 --- a/scm/output-lib.scm +++ b/scm/output-lib.scm @@ -94,23 +94,6 @@ molecule-boxer ) - -(define (arg->string arg) - (cond ((number? arg) (inexact->string arg 10)) - ((string? arg) (string-append "\"" arg "\"")) - ((symbol? arg) (string-append "\"" (symbol->string arg) "\"")))) - -;; ugh: naming. -(define (func name . args) - (string-append - "(" name - (if (null? args) - "" - (apply string-append - (map (lambda (x) (string-append " " (arg->string x))) args))) - ")\n")) - - ;;(define (mm-to-pt x) ;; (* (/ 72.27 25.40) x)) diff --git a/scm/pdf.scm b/scm/pdf.scm index 6e91201bea..b2adf3bea1 100644 --- a/scm/pdf.scm +++ b/scm/pdf.scm @@ -221,7 +221,7 @@ (* (- y1 y2) (- y1 y2)))) 2)))) -(define (start-system height) "") +(define (start-system width height) "") (define (stem breadth width depth height) (filledbox breadth width depth height)) diff --git a/scm/pdftex.scm b/scm/pdftex.scm index a62c213751..9624b8b4e5 100644 --- a/scm/pdftex.scm +++ b/scm/pdftex.scm @@ -21,7 +21,7 @@ (define this-module (current-module)) (define (unknown) - "%\n\\unknown%\n") + "%\n\\unknown\n") (define (select-font name-mag-pair) @@ -114,7 +114,7 @@ (begin ; uncomment for some stats about lily memory ; (display (gc-stats)) - (string-append "\n\\EndLilyPondOutput" + (string-append "%\n\\EndLilyPondOutput\n" ; Put GC stats here. ))) @@ -164,9 +164,10 @@ ((equal? (ly-unit) "pt") (/ 72.0 72.27)) (else (error "unknown unit" (ly-unit))) )) - "}\n" - "\\input lilyponddefs \\outputscale=\\lilypondpaperoutputscale \\lilypondpaperunit" - "\\turnOnPostScript" + "}%\n" + "\\input lilyponddefs\n" + "\\outputscale=\\lilypondpaperoutputscale \\lilypondpaperunit\n" + "\\turnOnPostScript\n" "\\pdfcompresslevel=0")) ;; Note: this string must match the string in ly2dvi.py!!! @@ -195,7 +196,7 @@ (tex-val (output-tex-string val))) (if (equal? (sans-surrounding-whitespace tex-val) "") (string-append "\\let\\" tex-key "\\undefined\n") - (string-append "\\def\\" tex-key "{" tex-val "}\n"))) + (string-append "\\def\\" tex-key "{" tex-val "}%\n"))) (define (number->dim x) (string-append @@ -213,13 +214,21 @@ (define (bezier-sandwich l thick) (embedded-pdf (list 'bezier-sandwich `(quote ,l) thick))) -(define (start-system ht) - (string-append"\\vbox to " (number->dim ht) "{\\hbox{%\n")) +(define (start-system wd ht) + (string-append "\\leavevmode\n" + "\\scoreshift = " (number->dim (* ht 0.5)) "\n" + "\\ifundefined{lilypondscoreshift}%\n" + "\\else\n" + " \\advance\\scoreshift by -\\lilypondscoreshift\n" + "\\fi\n" + "\\hbox to " (number->dim wd) "{%\n" + "\\lower\\scoreshift\n" + "\\vbox to " (number->dim ht) "{\\hbox{%\n")) (define (stop-system) - "}\\vss}\\interscoreline\n") + "}\\vss}\\hss}\\interscoreline\n") (define (stop-last-system) - "}\\vss}") + "}\\vss}\\hss}") (define (filledbox breapth width depth height) (string-append "\\kern" (number->dim (- breapth)) diff --git a/scm/ps.scm b/scm/ps.scm index 4be3fecf8b..2c99fe5d24 100644 --- a/scm/ps.scm +++ b/scm/ps.scm @@ -267,14 +267,11 @@ ; TODO: use HEIGHT argument - (define (start-system height) - (string-append - "\n" - (ly-number->string height) - " start-system { -set-ps-scale-to-lily-scale - -")) +(define (start-system width height) + (string-append "\n" (ly-number->string height) + " start-system\n" + "{\n" + "set-ps-scale-to-lily-scale")) (define (stem breapth width depth height) (string-append (numbers->string (list breapth width depth height)) diff --git a/scm/sketch.scm b/scm/sketch.scm index 70e84d592e..d69ce7e20f 100644 --- a/scm/sketch.scm +++ b/scm/sketch.scm @@ -247,9 +247,9 @@ layer('Layer 1',1,1,0,0,(0,0,0)) sketch-beziers (list x y (primitive-eval l) thick))) ; TODO: use HEIGHT argument -(define (start-system height) +(define (start-system width height) "G()\n" - ) +) ;; r((520.305,0,0,98.0075,51.8863,10.089)) ;; width, 0, 0, height, x, y diff --git a/scm/tex.scm b/scm/tex.scm index 84ae0ba65c..b5b7d27a9c 100644 --- a/scm/tex.scm +++ b/scm/tex.scm @@ -1,3 +1,4 @@ + ;;; tex.scm -- implement Scheme output routines for TeX ;;; ;;; source file of the GNU LilyPond music typesetter @@ -55,7 +56,7 @@ (define (unknown) - "%\n\\unknown%\n") + "%\n\\unknown\n") (define (select-font name-mag-pair) (let* @@ -146,7 +147,7 @@ (begin ; uncomment for some stats about lily memory ; (display (gc-stats)) - (string-append "\n\\EndLilyPondOutput\n" + (string-append "%\n\\endgroup\\EndLilyPondOutput\n" ; Put GC stats here. ))) @@ -172,15 +173,16 @@ ((equal? (ly-unit) "pt") (/ 72.0 72.27)) (else (error "unknown unit" (ly-unit))) )) - " mul }" + " mul }%\n" "\\special{\\string! " ;; URG: ly-gulp-file: now we can't use scm output without Lily (regexp-substitute/global #f "\n" (ly-gulp-file "music-drawing-routines.ps") 'pre " %\n" 'post) "}" - "\\input lilyponddefs \\outputscale=\\lilypondpaperoutputscale \\lilypondpaperunit" - "\\turnOnPostScript")) + "\\input lilyponddefs\n" + "\\outputscale=\\lilypondpaperoutputscale \\lilypondpaperunit\n" + "\\turnOnPostScript\\begingroup\\parindent0pt\n")) ;; Note: this string must match the string in ly2dvi.py!!! (define (header creator generate) @@ -207,10 +209,7 @@ (tex-val (output-tex-string val))) (if (equal? (sans-surrounding-whitespace tex-val) "") (string-append "\\let\\" tex-key "\\undefined\n") - (string-append "\\def\\" tex-key "{" tex-val "}\n")) - ) - ) - + (string-append "\\def\\" tex-key "{" tex-val "}%\n")))) (define (number->dim x) (string-append @@ -228,14 +227,21 @@ (define (bezier-sandwich l thick) (embedded-ps (list 'bezier-sandwich `(quote ,l) thick))) -(define (start-system ht) - (string-append "\\vbox to " (number->dim ht) "{\\hbox{" - "%\n")) +(define (start-system wd ht) + (string-append "\\leavevmode\n" + "\\scoreshift = " (number->dim (* ht 0.5)) "\n" + "\\ifundefined{lilypondscoreshift}%\n" + "\\else\n" + " \\advance\\scoreshift by -\\lilypondscoreshift\n" + "\\fi\n" + "\\hbox to " (number->dim wd) "{%\n" + "\\lower\\scoreshift\n" + "\\vbox to " (number->dim ht) "{\\hbox{%\n")) (define (stop-system) - "}\\vss}\\interscoreline\n") + "}\\vss}\\hss}\\interscoreline\n") (define (stop-last-system) - "}\\vss}") + "}\\vss}\\hss}") (define (filledbox breapth width depth height) (if (and #f (defined? 'ps-testing)) @@ -285,3 +291,4 @@ (display (my-eval-in-module expr this-module) port ) ) + diff --git a/scripts/ly2dvi.py b/scripts/ly2dvi.py index de3f99cd1f..8f86be23fa 100644 --- a/scripts/ly2dvi.py +++ b/scripts/ly2dvi.py @@ -692,6 +692,7 @@ lily output file in TFILES after that, and return the Latex file constructed. ' s = global_latex_preamble (extra) + '\\begin{document}\n' + s = s + '\\parindent 0pt\n' s = s + '\\thispagestyle{firstpage}\n' first = 1 diff --git a/tex/lily-pdf-defs.tex b/tex/lily-pdf-defs.tex index 69cacb71a6..f85aa5b1e8 100644 --- a/tex/lily-pdf-defs.tex +++ b/tex/lily-pdf-defs.tex @@ -1,17 +1,27 @@ -% Defines an embeddedpdf command so that we can do the right thing. +% lily-pdf-defs.tex +% +% Define an \embeddedpdf command so that we can do the right thing. +% +\edef\lilypdfdefsELC{\the\endlinechar}% +\endlinechar -1\relax \def\lilySpace{ } -\def\turnOnPostScript{% - % This sets CTM so that you get to the currentpoint - % by executing a 0 0 moveto - \def\embeddedpdf##1{% - \pdfliteral{q \lilypondpaperoutputscale\lilySpace 0 0 % - \lilypondpaperoutputscale\lilySpace 0 0 cm % - \lilyoutputscalefactor\lilySpace 0 0 % - \lilyoutputscalefactor\lilySpace 0 0 cm % - ##1 Q}% - } + +\def\turnOnPostScript{ + % This sets CTM so that you get to the currentpoint + % by executing a 0 0 moveto + \def\embeddedpdf##1{ + \pdfliteral{ + q \lilypondpaperoutputscale\lilySpace 0 0 % + \lilypondpaperoutputscale\lilySpace 0 0 cm % + \lilyoutputscalefactor\lilySpace 0 0 % + \lilyoutputscalefactor\lilySpace 0 0 cm % + ##1 Q + } + } } \def\turnOnExperimentalFeatures{} +\endlinechar \lilypdfdefsELC +\endinput diff --git a/tex/lily-ps-defs.tex b/tex/lily-ps-defs.tex index 80bf79c97d..4efc3c418c 100644 --- a/tex/lily-ps-defs.tex +++ b/tex/lily-ps-defs.tex @@ -1,27 +1,38 @@ +% lily-ps-defs.tex % -% WARNING: don't leave blank lines in the PS-code; they are -% transformed into \par -% +\edef\lilypsdefsELC{\the\endlinechar}% +\endlinechar -1\relax -% -% header info (macros/defs, etc) should go into a \special{! ... }, +% Header info (macros/defs, etc) should go into a \special{! ... }; % note the ! sign. See dvips.info for details. % -% escape the colon with \string to avoid problems with french babel -% -\def\PSsetTeXdimen#1{\expandafter\special{! /#1 (\csname #1\endcsname) set_tex_dimen}} +% Escape the colon with \string to avoid problems with French while using +% the Babel package. + +\def\PSsetTeXdimen#1{ + \expandafter\special{ + ! /#1 (\csname #1\endcsname) set_tex_dimen + } +} + \def\lilySpace{ } -\def\turnOnPostScript{% - % This sets CTM so that you get to the currentpoint - % by executing a 0 0 moveto - \def\embeddedps##1{% - \special{ps\string: @beginspecial @setspecial - \lilypondpaperoutputscale\lilySpace\scaletounit - \lilypondpaperoutputscale\lilySpace\scaletounit - % FUCKING REDHAT XDVI -- ARG! - skeel ##1 @endspecial}% - } - \PSsetTeXdimen{lilypondpaperblotdiameter} + +\def\turnOnPostScript{ + % This sets CTM so that you get to the currentpoint + % by executing a 0 0 moveto + \def\embeddedps##1{ + \special{ + ps\string: @beginspecial @setspecial % + \lilypondpaperoutputscale\lilySpace\scaletounit % + \lilypondpaperoutputscale\lilySpace\scaletounit % + % FUCKING REDHAT XDVI -- ARG! + skeel ##1 @endspecial + } + } + \PSsetTeXdimen{lilypondpaperblotdiameter} } + \def\turnOnExperimentalFeatures{} +\endlinechar \lilypsdefsELC +\endinput diff --git a/tex/lilypond-latex.tex b/tex/lilypond-latex.tex index 1c7a3f5a3c..e139af70cb 100644 --- a/tex/lilypond-latex.tex +++ b/tex/lilypond-latex.tex @@ -1,26 +1,46 @@ +% lilypond-latex.tex +% +\edef\lilypondlatexELC{\the\endlinechar}% +\endlinechar -1\relax + \message{LaTeX definitions} + \def\texsuffix{LaTeX} + \def\lilyfooterLaTeX{ -\let\nopagenumbers\relax - %% FIXME - \def\ps@plain{ - \renewcommand{\@oddhead}{}% - \renewcommand{\@evenfoot}{}% - \renewcommand{\@evenhead}{}% - \renewcommand{\@oddfoot}{% - \ifnum\thepage=1{\hfil \lilypondtagline}% - \else{% - foo\hfil\the\pageno\hfil}% - \fi}} - \def\ps@empty{ - \renewcommand{\@oddhead}{}% - \renewcommand{\@evenfoot}{}% - \renewcommand{\@evenhead}{}% - \renewcommand{\@oddfoot}{% - \ifnum\thepage=1{\hfil \lilypondtagline}% - \else{foo\hfil\the\pageno\hfil}% - \fi}}% -\nopagenumbers + \let\nopagenumbers\relax + + %% FIXME + \def\ps@plain{ + \renewcommand{\@oddhead}{} + \renewcommand{\@evenfoot}{} + \renewcommand{\@evenhead}{} + \renewcommand{\@oddfoot}{ + \ifnum\thepage = 1\relax + {\hfil \lilypondtagline} + \else + {foo\hfil \the\pageno \hfil} + \fi + } + } + + \def\ps@empty{ + \renewcommand{\@oddhead}{} + \renewcommand{\@evenfoot}{} + \renewcommand{\@evenhead}{} + \renewcommand{\@oddfoot}{ + \ifnum\thepage = 1\relax + {\hfil \lilypondtagline} + \else + {foo\hfil \the\pageno \hfil} + \fi + } + } + + \nopagenumbers } \def\nolilyfooterLaTeX{} + +\endlinechar \lilypondlatexELC +\endinput diff --git a/tex/lilypond-plaintex.tex b/tex/lilypond-plaintex.tex index 7dddb283b7..b269993355 100644 --- a/tex/lilypond-plaintex.tex +++ b/tex/lilypond-plaintex.tex @@ -1,9 +1,38 @@ +% lilypond-plaintex.tex +% +\edef\lilypondplaintexELC{\the\endlinechar}% +\endlinechar -1\relax + \message{LilyPond Plain TeX settings} - \def\texsuffix{PlainTeX} + +\def\texsuffix{PlainTeX} \def\lilyfooterPlainTeX{ - \footline={\ifnum\pageno=1\smalltextfont\lilypondcopyright\hfil \lilypondtagline - \else\hfil\the\pageno\hfil\fi}% + \footline = { + \ifnum\pageno = 1\relax + \smalltextfont\lilypondcopyright\hfil \lilypondtagline + \else + \hfil \the\pageno \hfil + \fi + } } + + +%% make plain work ok Out Of The Box + +\ifundefined{lilypondpaperunit} +\def\lhsize{\hsize} +\else +\def\lhsize{\lilypondpaperlinewidth\lilypondpaperunit} +\fi + +\ifdim0pt<\lhsize +\hsize=\lhsize +\fi + \advance\hoffset by -.6in + \def\nolilyfooterPlainTeX{\nopagenumbers} + +\endlinechar \lilypondplaintexELC +\endinput diff --git a/tex/lilyponddefs.tex b/tex/lilyponddefs.tex index ccf820e122..acacba8e3d 100644 --- a/tex/lilyponddefs.tex +++ b/tex/lilyponddefs.tex @@ -1,43 +1,62 @@ -%% -%% include file for LilyPond -%% -%% this file defines various macros to accomodate lilypond output -%% -%% let's not make par before endinput +% lilyponddefs.tex +% +% Include file for LilyPond. +% +% This file defines various macros to accomodate lilypond output. +% +% Avoid \par while reading this file. +\edef\lilyponddefsELC{\the\endlinechar}% +\endlinechar -1\relax % TeXbook ex 7.7 -\def\ifundefined#1{\expandafter\ifx\csname#1\endcsname\relax} +\def\ifundefined#1{ + \expandafter\ifx\csname#1\endcsname\relax +} +% If we must make titles, do so, before we're skipped. + +\ifx\mustmakelilypondtitle\undefined +\else + \makelilypondtitle +\fi + +\ifx\mustmakelilypondpiecetitle\undefined +\else + \makelilypondpiecetitle +\fi -% If we must make titles, do so, before we're Skipped. -\ifx\mustmakelilypondtitle\undefined\else\makelilypondtitle\fi -\ifx\mustmakelilypondpiecetitle\undefined\else\makelilypondpiecetitle\fi -% % skip if included already -\def\SkipLilydefs{\endinput} + +\def\SkipLilydefs{ + \endlinechar \lilyponddefsELC + \endinput} \ifundefined{EndLilyPondOutput} - \def\EndLilyPondOutput{\csname bye\endcsname} - \def\SkipLilydefs{} + \def\EndLilyPondOutput{\csname bye\endcsname} + \def\SkipLilydefs{} \fi \SkipLilydefs -% need to do some stuff to turn pagenumbering off +% need to do some stuff to turn page numbering off + \ifundefined{documentclass} - \input lilypond-plaintex + \input lilypond-plaintex \else - \input lilypond-latex + \input lilypond-latex \fi % The feta characters -\input feta20.tex +\input feta20 -\font\fetasixteen=feta16 +\font\fetasixteen = feta16 \def\fetafont{\fetasixteen} \def\fetachar#1{\hbox{\fetasixteen#1}} - -\def\botalign#1{\vbox to 0pt{\vss #1}} -\def\leftalign#1{\hbox to 0pt{#1\hss}} +\def\botalign#1{ + \vbox to 0pt{\vss #1} +} +\def\leftalign#1{ + \hbox to 0pt{#1\hss} +} % Attempt to keep lilypiecetitle together with the piece: @@ -45,22 +64,28 @@ % TODO: figure this out. % -\def\myfilbreak{} %\par\vfil\penalty200\vfilneg} +\def\myfilbreak{}%\par\vfil\penalty200\vfilneg} \ifundefined{lilypondpaperinterscorelinefill} - \def\lilypondpaperinterscorelinefill{0} + \def\lilypondpaperinterscorelinefill{0} \else - \def\lilypondpaperinterscorelinefill{1} + \def\lilypondpaperinterscorelinefill{1} \fi -\def\interscoreline{\vskip \lilypondpaperinterscoreline \lilypondpaperunit plus \lilypondpaperinterscorelinefill fill} +\def\interscoreline{ + \vskip \lilypondpaperinterscoreline \lilypondpaperunit + plus \lilypondpaperinterscorelinefill fill +} -\def\placebox#1#2#3{% - \botalign{\hbox{\raise #1\leftalign{\kern #2{}#3}}}}% +\def\placebox#1#2#3{ + \botalign{ + \hbox{\raise #1\leftalign{\kern #2{}#3}} + } +} % Are we using PDFTeX? If so, use pdf definitions. -% MiKTeX checks \pdfoutput the wrong way, makes our +% MiKTeX checks \pdfoutput the wrong way; this makes our % check more complicated. \ifx\pdfoutput\undefined \input lily-ps-defs @@ -68,30 +93,39 @@ \ifx\pdfoutput\relax \input lily-ps-defs \else - \pdfoutput=1 + \pdfoutput = 1 \input lily-pdf-defs \fi \fi -\def\EndLilyPondOutput{% -\ifundefined{lilypondpaperlastpagefill}% - \vskip 0pt plus \lilypondpaperinterscorelinefill00 fill -\fi -\csname bye\endcsname} +\def\EndLilyPondOutput{ + \ifundefined{lilypondpaperlastpagefill} + \vskip 0pt plus \lilypondpaperinterscorelinefill00 fill + \fi + \csname bye\endcsname +} -% need to do some stuff to turn pagenumbering off -% they seriously mess up your fragments. +% Need to do some stuff to turn page numbering off; +% they seriously mess up your fragments. \ifx\csname nolilyfooter\endcsname\relax - \message{[footer defined]}% - \csname lilyfooter\texsuffix\endcsname% + \message{[footer defined]} + \csname lilyfooter\texsuffix\endcsname \else - \message{[footer empty]} - \csname% - nolilyfooter\texsuffix\endcsname + \message{[footer empty]} + \csname nolilyfooter\texsuffix\endcsname \fi +% It is very bad that lilyponddefs.tex gets included in every lilypond +% output snippet. This is necessary because these output snippets +% often get encapsulated, eg by texinfo. This should be fixed by +% putting the variable parts in this file into a macro so that loading +% the file multiple times can be avoided. \ifx\outputscale\undefined - \csname global\endcsname\csname newdimen\endcsname\outputscale + \csname global\endcsname\csname newdimen\endcsname\outputscale + \csname global\endcsname\csname newdimen\endcsname\scoreshift \fi + +% Restore newline functionality (disabled to avoid \par). +\endlinechar \lilyponddefsELC \endinput diff --git a/tex/titledefs.tex b/tex/titledefs.tex index 653afeb09c..9894742ba4 100644 --- a/tex/titledefs.tex +++ b/tex/titledefs.tex @@ -1,100 +1,195 @@ -%% -%% LilyPond titling for LaTeX -%% -%% Note -%% -%% Defining a value, but leaving it empty: -%% \def\lilypondfoo{} -%% makes LaTeX break on the \\ in: -%% \ifx\lilypondfoo\undefined\else{\lilypondfoo\\}\fi -%% +% titledefs.tex +% +% LilyPond titling for LaTeX +% +% Note: +% +% Defining a value, but leaving it empty: +% \def\lilypondfoo{} +% makes LaTeX break on the \\ in: +% \ifx\lilypondfoo\undefined\else{\lilypondfoo\\}\fi +% +\edef\titledefsELC{\the\endlinechar}% +\endlinechar -1\relax + % The feta characters for use in titles \input feta20.tex -% + \font\fetasixteen=feta16 \def\fetafont{\fetasixteen} \def\fetachar#1{\hbox{\fetasixteen#1}} -% -\def\makelilypondtitle -{ + +\def\makelilypondtitle{ \begin{center} - \ifx\lilyponddedication\undefined\else{\normalfont\lilyponddedication\\}\fi - \bfseries - \ifx\lilypondtitle\undefined\else{\huge\lilypondtitle\\}\fi - \ifx\lilypondsubtitle\undefined\else{\Large\lilypondsubtitle\\}\fi - \ifx\lilypondsubsubtitle\undefined\else{\large\lilypondsubsubtitle\\}\fi + \ifx\lilyponddedication\undefined + \else + {\normalfont\lilyponddedication\\} + \fi + + \bfseries + + \ifx\lilypondtitle\undefined + \else + {\huge\lilypondtitle\\} + \fi + + \ifx\lilypondsubtitle\undefined + \else + {\Large\lilypondsubtitle\\} + \fi + + \ifx\lilypondsubsubtitle\undefined + \else + {\large\lilypondsubsubtitle\\} + \fi \end{center} + \bigskip - % urg - \edef\saveparskip{\parskip}\parskip-5mm + \begin{minipage}[t]{0.45\textwidth} - \ifx\lilypondpoet\undefined\else{\lilypondpoet\\}\fi - \ifx\lilypondtexttranslator\undefined\else{\lilypondtexttranslator\\}\fi - \ifx\lilypondmeter\undefined\else{\lilypondmeter\\}\fi - \end{minipage}\hspace*{\fill} + \ifx\lilypondpoet\undefined + \else + {\lilypondpoet\\} + \fi + + \ifx\lilypondtexttranslator\undefined + \else + {\lilypondtexttranslator\\} + \fi + + \ifx\lilypondmeter\undefined + \else + {\lilypondmeter\\} + \fi + \end{minipage} + + \hspace*{\fill} + \begin{minipage}[t]{0.45\textwidth} - \begin{flushright} - \ifx\lilypondcomposer\undefined\else{\large\normalfont\scshape\lilypondcomposer\\}\fi - \ifx\lilypondopus\undefined\else{\lilypondopus\\}\fi - \ifx\lilypondarranger\undefined\else{\lilypondarranger\\}\fi - \end{flushright}% - \end{minipage}\par - \parskip\saveparskip - \ifx\lilypondinstrument\undefined\else{\center{\large\lilypondinstrument}\par}\fi - \ifx\lilypondpiece\undefined\else{\flushleft{\large\normalfont\scshape\lilypondpiece}\par}\fi -% \leavevmode - \global\let\lilypondopus\relax% - \global\let\lilypondpiece\relax% - \global\let\mustmakelilypondtitle\undefined% + \begin{flushright} + \ifx\lilypondcomposer\undefined + \else + {\large\normalfont\scshape\lilypondcomposer\\} + \fi + + \ifx\lilypondopus\undefined + \else + {\lilypondopus\\} + \fi + + \ifx\lilypondarranger\undefined + \else + {\lilypondarranger\\} + \fi + \end{flushright} + \end{minipage} + + \par + + \ifx\lilypondinstrument\undefined + \else + {\center{\large\lilypondinstrument} + \par} + \fi + + \ifx\lilypondpiece\undefined + \else + {\flushleft{\large\normalfont\scshape\lilypondpiece} + \par} + \fi + +% \leavevmode + + \global\let\lilypondopus\relax + \global\let\lilypondpiece\relax + \global\let\mustmakelilypondtitle\undefined } -% -\def\makelilypondpiecetitle -{ + +\def\makelilypondpiecetitle{ \bigskip\myfilbreak - \ifx\lilypondopus\undefined\else{\flushright{\lilypondopus}\par}\fi - \ifx\lilypondpiece\undefined\else{\flushleft{\large\normalfont\scshape\lilypondpiece}\par}\fi - \nopagebreak% - \global\let\lilypondopus\relax% - \global\let\lilypondpiece\relax% - \global\let\mustmakelilypondpiecetitle\undefined% + + \ifx\lilypondopus\undefined + \else + {\flushright{\lilypondopus} + \par} + \fi + + \ifx\lilypondpiece\undefined + \else + {\flushleft{\large\normalfont\scshape\lilypondpiece} + \par} + \fi + + \nopagebreak + + \global\let\lilypondopus\relax + \global\let\lilypondpiece\relax + \global\let\mustmakelilypondpiecetitle\undefined } + % header -- head ? -% these names can't be changed: they're uses in mutopia headers -\def\theheader -{ - \ifx\lilypondhead\undefined\relax\else% - \lilypondhead\fi +% these names can't be changed: they're used in mutopia headers + +\def\theheader{ + \ifx\lilypondhead\undefined + \else + \lilypondhead + \fi } -\def\thefooter -{ - \ifx\lilypondfooter\undefined\relax\else% - \lilypondfooter\fi + +\def\thefooter{ + \ifx\lilypondfooter\undefined + \else + \lilypondfooter + \fi } -\def\makelilypondtagline -{ - \ifx\undefined\lilypondtagline\relax\else\lilypondtagline\fi + +\def\makelilypondtagline{ + \ifx\undefined\lilypondtagline + \else + \lilypondtagline + \fi } -\def\thecopyright -{ - \ifx\lilypondcopyright\undefined\thefooter\else% - \lilypondcopyright\fi + +\def\thecopyright{ + \ifx\lilypondcopyright\undefined + \thefooter + \else + \lilypondcopyright + \fi } -% + % Moved header and footer definitions here from the ly2dvi script. % Separate page styles for first, last and ordinary (plain) pages. + \makeatletter + \renewcommand{\ps@plain}{ - \renewcommand{\@oddfoot}{\parbox{\textwidth}{\mbox{}\thefooter}}% - \renewcommand{\@evenfoot}{\@oddfoot}% - \renewcommand{\@evenhead}{\hbox to\textwidth{\textbf{\thepage}\hfill{\small\theheader}}} - \renewcommand{\@oddhead}{\hbox to - \textwidth{{\small\theheader}\hfill\textbf{\thepage}}}} + \renewcommand{\@oddfoot}{ + \parbox{\textwidth}{\mbox{}\thefooter}} + \renewcommand{\@evenfoot}{ + \@oddfoot} + \renewcommand{\@evenhead}{ + \hbox to \textwidth{\textbf{\thepage}\hfill{\small\theheader}}} + \renewcommand{\@oddhead}{ + \hbox to \textwidth{{\small\theheader}\hfill\textbf{\thepage}}} +} + \newcommand{\ps@firstpage}{ - \renewcommand{\@oddfoot}{\parbox{\textwidth}{\mbox{}\thecopyright}}% - \renewcommand{\@evenfoot}{\@oddfoot}} + \renewcommand{\@oddfoot}{ + \parbox{\textwidth}{\mbox{}\thecopyright}} + \renewcommand{\@evenfoot}{ + \@oddfoot} +} + \newcommand{\ps@lastpage}{ - \renewcommand{\@oddfoot}{\parbox{\textwidth}{\mbox{}\makelilypondtagline}}% - \renewcommand{\@evenfoot}{\@oddfoot}} + \renewcommand{\@oddfoot}{ + \parbox{\textwidth}{\mbox{}\makelilypondtagline}} + \renewcommand{\@evenfoot}{ + \@oddfoot} +} + \makeatother -\endinput +\endlinechar \titledefsELC +\endinput