X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Funpure-pure-container.cc;h=1aefe920afea8b647496d65bcadcb2baf10d2514;hb=220298a9a1dcd1c318a38d79aa3a5ea694a17270;hp=097cb9d80c46fc1f2baea71b6de1424a284265d9;hpb=01df8ad908c92687d0c352e5ad5f067e52809423;p=lilypond.git diff --git a/lily/unpure-pure-container.cc b/lily/unpure-pure-container.cc index 097cb9d80c..1aefe920af 100644 --- a/lily/unpure-pure-container.cc +++ b/lily/unpure-pure-container.cc @@ -1,7 +1,7 @@ /* This file is part of LilyPond, the GNU music typesetter. - Copyright (C) 2011--2012 Mike Solomon + Copyright (C) 2011--2014 Mike Solomon LilyPond is free software: you can redistribute it and/or modify @@ -22,6 +22,9 @@ #include "grob.hh" static scm_t_bits unpure_pure_container_tag; +static scm_t_bits unpure_pure_call_tag; +// Used for rerouting a function of (grob start end) to one of +// (grob) bool is_unpure_pure_container (SCM s) @@ -29,18 +32,36 @@ is_unpure_pure_container (SCM s) return (SCM_NIMP (s) && SCM_CELL_TYPE (s) == unpure_pure_container_tag); } +bool +is_unchanging_unpure_pure_container (SCM s) +// A container that has the same callback for both 'pure' and 'unpure' lookups +// and which ignores the 'start' and 'end' columnns. +// Such a callback will give the same answer for tentative or final layouts. +{ + LY_ASSERT_TYPE (is_unpure_pure_container, s, 1); + SCM pure_part = SCM_SMOB_OBJECT_2 (s); + return (SCM_UNBNDP (pure_part)); +} + SCM unpure_pure_container_unpure_part (SCM smob) { LY_ASSERT_TYPE (is_unpure_pure_container, smob, 1); - return (SCM) SCM_CELL_WORD_1 (smob); + return SCM_SMOB_OBJECT (smob); } SCM unpure_pure_container_pure_part (SCM smob) { LY_ASSERT_TYPE (is_unpure_pure_container, smob, 1); - return (SCM) SCM_CELL_WORD_2 (smob); + SCM res = SCM_SMOB_OBJECT_2 (smob); + + if (!SCM_UNBNDP (res)) + return res; + + SCM_NEWSMOB (res, unpure_pure_call_tag, + SCM_UNPACK (unpure_pure_container_unpure_part (smob))); + return res; } LY_DEFINE (ly_unpure_pure_container_p, "ly:unpure-pure-container?", @@ -54,11 +75,13 @@ LY_DEFINE (ly_make_unpure_pure_container, "ly:make-unpure-pure-container", 1, 1, 0, (SCM unpure, SCM pure), "Make an unpure-pure container. @var{unpure} should be an unpure" " expression, and @var{pure} should be a pure expression. If @var{pure}" - " is ommitted, the value of @var{unpure} will be used twice.") + " is omitted, the value of @var{unpure} will be used twice," + " except that a callback is given two extra arguments" + " that are ignored for the sake of pure calculations.") { SCM z; - if (pure == SCM_UNDEFINED) + if (SCM_UNBNDP (pure) && !ly_is_procedure (unpure)) pure = unpure; SCM_NEWSMOB2 (z, unpure_pure_container_tag, SCM_UNPACK (unpure), SCM_UNPACK (pure)); @@ -86,25 +109,46 @@ print_unpure_pure_container (SCM s, SCM port, scm_print_state *) { scm_puts ("#", port); return 1; } SCM -pure_mark (SCM pure) +pure_mark (SCM smob) { - scm_gc_mark (unpure_pure_container_unpure_part (pure)); - scm_gc_mark (unpure_pure_container_pure_part (pure)); - return pure; + scm_gc_mark (SCM_SMOB_OBJECT (smob)); + return SCM_SMOB_OBJECT_2 (smob); +} + +// Function signature has two fixed arguments so that dropping two +// will always work: if we have fewer to start with, it will trigger +// wrong-number-of-args in a sensible location rather than making +// drop-right barf. + +SCM +apply_unpure_pure (SCM clo, SCM arg1, SCM arg2, SCM rest) +{ + return scm_apply_0 (SCM_SMOB_OBJECT (clo), + scm_call_2 (ly_lily_module_constant ("drop-right"), + scm_cons2 (arg1, arg2, rest), + scm_from_int (2))); } + void init_unpure_pure_container () { unpure_pure_container_tag = scm_make_smob_type ("unpure-pure-container", 0); scm_set_smob_mark (unpure_pure_container_tag, pure_mark); scm_set_smob_print (unpure_pure_container_tag, print_unpure_pure_container); + unpure_pure_call_tag = scm_make_smob_type ("unpure-pure-call", 0); + scm_set_smob_mark (unpure_pure_call_tag, scm_markcdr); + scm_set_smob_apply (unpure_pure_call_tag, + (scm_t_subr) apply_unpure_pure, 2, 0, 1); }; ADD_SCM_INIT_FUNC (unpure_pure_container, init_unpure_pure_container);