]> git.donarmstrong.com Git - lilypond.git/blobdiff - lily/paper-book.cc
Book parts: ragged-bottom-last and book titles
[lilypond.git] / lily / paper-book.cc
index 72648b682fe952df2d0a9a4292be258a229c3670..dfd3f6257fa64f9d68d52332095d61564a1109e8 100644 (file)
@@ -27,6 +27,7 @@ Paper_book::Paper_book ()
   header_0_ = SCM_EOL;
   pages_ = SCM_BOOL_F;
   scores_ = SCM_EOL;
+  bookparts_ = SCM_EOL;
   performances_ = SCM_EOL;
   systems_ = SCM_BOOL_F;
 
@@ -53,6 +54,7 @@ Paper_book::mark_smob (SCM smob)
   scm_gc_mark (b->pages_);
   scm_gc_mark (b->performances_);
   scm_gc_mark (b->scores_);
+  scm_gc_mark (b->bookparts_);
   return b->systems_;
 }
 
@@ -65,6 +67,15 @@ Paper_book::print_smob (SCM smob, SCM port, scm_print_state*)
   return 1;
 }
 
+Output_def *
+Paper_book::top_paper ()
+{
+  Output_def *paper = paper_;
+  while (paper->parent_)
+    paper = paper->parent_;
+  return paper;
+}
+
 SCM
 dump_fields ()
 {
@@ -82,14 +93,23 @@ Paper_book::add_score (SCM s)
   scores_ = scm_cons (s, scores_);
 }
 
+void
+Paper_book::add_bookpart (SCM p)
+{
+  bookparts_ = scm_cons (p, bookparts_);
+}
+
 void
 Paper_book::add_performance (SCM s)
 {
   performances_ = scm_cons (s, performances_);
 }
 
-void
-Paper_book::output (SCM output_channel)
+int
+Paper_book::output_aux (SCM output_channel,
+                        int first_page_number,
+                        bool is_first,
+                        bool is_last)
 {
   if (scm_is_pair (performances_))
     {
@@ -98,11 +118,44 @@ Paper_book::output (SCM output_channel)
       scm_call_2 (proc, performances (), output_channel);
     }
 
-  if (scores_ == SCM_EOL)
-    return;
+  if (scm_is_pair (bookparts_))
+    {
+      bool is_first_part = is_first;
+      int page_number = first_page_number;
+      for (SCM p = scm_reverse (bookparts_); scm_is_pair (p); p = scm_cdr (p))
+        if (Paper_book *pbookpart = unsmob_paper_book (scm_car (p)))
+          {
+            bool is_last_part = (is_last && !scm_is_pair (scm_cdr (p)));
+            page_number += pbookpart->output_aux (output_channel,
+                                                  page_number,
+                                                  is_first_part,
+                                                  is_last_part);
+            is_first_part = false;
+          }
+      return page_number;
+    }
+  else
+    {
+      if (scores_ == SCM_EOL)
+        return 0;
+      paper_->set_variable (ly_symbol2scm ("part-first-page-number"),
+                            scm_long2num (first_page_number));
+      paper_->set_variable (ly_symbol2scm ("part-is-first"),
+                            ly_bool2scm (is_first));
+      paper_->set_variable (ly_symbol2scm ("part-is-last"),
+                            ly_bool2scm (is_last));
+      /* Generate all stencils to trigger font loads.  */
+      return scm_ilength (pages ());
+    }
+}
 
-  /* Generate all stencils to trigger font loads.  */
-  pages ();
+void
+Paper_book::output (SCM output_channel)
+{
+  output_aux (output_channel,
+              robust_scm2int (paper_->c_variable ("first-page-number"), 1),
+              true,
+              true);
 
   SCM scopes = SCM_EOL;
   if (ly_is_module (header_))
@@ -137,7 +190,7 @@ Paper_book::output (SCM output_channel)
 }
 
 void
-Paper_book::classic_output (SCM output)
+Paper_book::classic_output_aux (SCM output)
 {
   if (scm_is_pair (performances_))
     {
@@ -148,6 +201,12 @@ Paper_book::classic_output (SCM output)
   
   /* Generate all stencils to trigger font loads.  */
   systems ();
+}
+
+void
+Paper_book::classic_output (SCM output)
+{
+  classic_output_aux (output);
 
   SCM scopes = SCM_EOL;
   if (ly_is_module (header_))
@@ -271,7 +330,7 @@ set_system_penalty (SCM sys, SCM header)
 }
 
 void
-set_label (SCM sys, SCM label)
+set_labels (SCM sys, SCM labels)
 {
   if (Paper_score *ps = dynamic_cast<Paper_score*> (unsmob_music_output (sys)))
     {
@@ -279,13 +338,19 @@ set_label (SCM sys, SCM label)
       if (cols.size ())
        {
          Paper_column *col = dynamic_cast<Paper_column*> (cols[0]);
-         col->set_property ("labels", scm_cons (label, col->get_property ("labels")));
+         col->set_property ("labels", 
+                            scm_append_x (scm_list_2 (col->get_property ("labels"),
+                                                      labels)));
          Paper_column *col_right = dynamic_cast<Paper_column*> (col->find_prebroken_piece (RIGHT));
-         col_right->set_property ("labels", scm_cons (label, col_right->get_property ("labels")));
+         col_right->set_property ("labels", 
+                                  scm_append_x (scm_list_2 (col_right->get_property ("labels"),
+                                                            labels)));
        }
     }
   else if (Prob *pb = unsmob_prob (sys))
-    pb->set_property ("labels", scm_cons (label, pb->get_property ("labels")));
+    pb->set_property ("labels", 
+                     scm_append_x (scm_list_2 (pb->get_property ("labels"),
+                                               labels)));
 }
 
 SCM
@@ -322,7 +387,7 @@ Paper_book::get_system_specs ()
       SCM props = paper_->lookup_variable (ly_symbol2scm ("book-title-properties"));
       Prob *ps = make_paper_system (props);
       paper_system_set_stencil (ps, title);
-
+      
       system_specs = scm_cons (ps->self_scm (), system_specs);
       ps->unprotect ();
     }
@@ -333,6 +398,7 @@ Paper_book::get_system_specs ()
 
   SCM interpret_markup_list = ly_lily_module_constant ("interpret-markup-list");
   SCM header = SCM_EOL;
+  SCM labels = SCM_EOL;
   for (SCM s = scm_reverse (scores_); scm_is_pair (s); s = scm_cdr (s))
     {
       if (ly_is_module (scm_car (s)))
@@ -355,9 +421,8 @@ Paper_book::get_system_specs ()
            }
          if (scm_is_symbol (page_marker->label ()))
            {
-             /* set previous element label */
-             if (scm_is_pair (system_specs))
-               set_label (scm_car (system_specs), page_marker->label ());
+             /* The next element label is to be set */
+             labels = scm_cons (page_marker->label (), labels);
            }
        }
       else if (Music_output *mop = unsmob_music_output (scm_car (s)))
@@ -377,6 +442,11 @@ Paper_book::get_system_specs ()
 
              header = SCM_EOL;
              system_specs = scm_cons (pscore->self_scm (), system_specs);
+             if (scm_is_pair (labels))
+               {
+                 set_labels (scm_car (system_specs), labels);
+                 labels = SCM_EOL;
+               }
            }
          else
            {
@@ -413,6 +483,11 @@ Paper_book::get_system_specs ()
              system_specs = scm_cons (ps->self_scm (), system_specs);
              ps->unprotect ();
              
+             if (scm_is_pair (labels))
+               {
+                 set_labels (scm_car (system_specs), labels);
+                 labels = SCM_EOL;
+               }
              // FIXME: figure out penalty.
              //set_system_penalty (ps, scores_[i].header_);
            }
@@ -432,46 +507,54 @@ Paper_book::systems ()
     return systems_;
 
   systems_ = SCM_EOL;
-  SCM specs = get_system_specs ();
-  for (SCM s = specs; scm_is_pair (s); s = scm_cdr (s))
+  if (scm_is_pair (bookparts_))
     {
-      if (Paper_score *pscore = dynamic_cast<Paper_score*> (unsmob_music_output (scm_car (s))))
-       {
-         SCM system_list = scm_vector_to_list (pscore->get_paper_systems ());
-         system_list = scm_reverse (system_list);
-         systems_ = scm_append (scm_list_2 (system_list, systems_));
-       }
-      else
-       {
-         systems_ = scm_cons (scm_car (s), systems_);
-       }
+      for (SCM p = scm_reverse (bookparts_); scm_is_pair (p); p = scm_cdr (p))
+        if (Paper_book *pbookpart = unsmob_paper_book (scm_car (p)))
+          systems_ = scm_append_x (scm_list_2 (systems_, pbookpart->systems ()));
     }
-  
-  systems_ = scm_reverse (systems_);
-
-  /* backwards compatibility for the old page breaker */
-  int i = 0;
-  Prob *last = 0;
-  for (SCM s = systems_; scm_is_pair (s); s = scm_cdr (s))
+  else
     {
-      Prob *ps = unsmob_prob (scm_car (s));
-      ps->set_property ("number", scm_from_int (++i));
-
-      if (last
-         && to_boolean (last->get_property ("is-title"))
-         && !scm_is_number (ps->get_property ("penalty")))
-       ps->set_property ("penalty", scm_from_int (10000));
-      last = ps;
-
-      if (scm_is_pair (scm_cdr (s)))
-       {
-         SCM perm = ps->get_property ("page-break-permission");
-         Prob *next = unsmob_prob (scm_cadr (s));
-         if (perm == SCM_EOL)
-           next->set_property ("penalty", scm_from_int (10001));
-         else if (perm == ly_symbol2scm ("force"))
-           next->set_property ("penalty", scm_from_int (-10001));
-       }
+      SCM specs = get_system_specs ();
+      for (SCM s = specs; scm_is_pair (s); s = scm_cdr (s))
+        {
+          if (Paper_score *pscore = dynamic_cast<Paper_score*> (unsmob_music_output (scm_car (s))))
+            {
+              SCM system_list = scm_vector_to_list (pscore->get_paper_systems ());
+              system_list = scm_reverse (system_list);
+              systems_ = scm_append (scm_list_2 (system_list, systems_));
+            }
+          else
+            {
+              systems_ = scm_cons (scm_car (s), systems_);
+            }
+        }
+      systems_ = scm_reverse (systems_);
+
+      /* backwards compatibility for the old page breaker */
+      int i = 0;
+      Prob *last = 0;
+      for (SCM s = systems_; scm_is_pair (s); s = scm_cdr (s))
+        {
+          Prob *ps = unsmob_prob (scm_car (s));
+          ps->set_property ("number", scm_from_int (++i));
+          
+          if (last
+              && to_boolean (last->get_property ("is-title"))
+              && !scm_is_number (ps->get_property ("penalty")))
+            ps->set_property ("penalty", scm_from_int (10000));
+          last = ps;
+          
+          if (scm_is_pair (scm_cdr (s)))
+            {
+              SCM perm = ps->get_property ("page-break-permission");
+              Prob *next = unsmob_prob (scm_cadr (s));
+              if (perm == SCM_EOL)
+                next->set_property ("penalty", scm_from_int (10001));
+              else if (perm == ly_symbol2scm ("force"))
+                next->set_property ("penalty", scm_from_int (-10001));
+            }
+        }
     }
 
   return systems_;
@@ -484,22 +567,29 @@ Paper_book::pages ()
     return pages_;
 
   pages_ = SCM_EOL;
-  SCM proc = paper_->c_variable ("page-breaking-wrapper");
-  pages_ = scm_apply_0 (proc, scm_list_1 (self_scm ()));
-
-  /* set systems_ from the pages */
-  if (systems_ == SCM_BOOL_F)
+  if (scm_is_pair (bookparts_))
     {
-      systems_ = SCM_EOL;
-      for (SCM p = pages_; scm_is_pair (p); p = scm_cdr (p))
-       {
-         Prob *page = unsmob_prob (scm_car (p));
-         SCM systems = page->get_property ("lines");
-
-         systems_ = scm_append (scm_list_2 (systems_, systems));
-       }
+      for (SCM p = scm_reverse (bookparts_); scm_is_pair (p); p = scm_cdr (p))
+        if (Paper_book *pbookpart = unsmob_paper_book (scm_car (p)))
+          pages_ = scm_append_x (scm_list_2 (pages_, pbookpart->pages ()));
+    }
+  else
+    {
+      SCM proc = paper_->c_variable ("page-breaking-wrapper");
+      pages_ = scm_apply_0 (proc, scm_list_1 (self_scm ()));
+
+      /* set systems_ from the pages */
+      if (systems_ == SCM_BOOL_F)
+        {
+          systems_ = SCM_EOL;
+          for (SCM p = pages_; scm_is_pair (p); p = scm_cdr (p))
+            {
+              Prob *page = unsmob_prob (scm_car (p));
+              SCM systems = page->get_property ("lines");
+              systems_ = scm_append (scm_list_2 (systems_, systems));
+            }
+        }
     }
-
   return pages_;
 }