Back to index

texmacs  1.0.7.15
pager.cpp
Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003 * MODULE     : pager.cpp
00004 * DESCRIPTION: Control routines for typesetting paragraphs
00005 * COPYRIGHT  : (C) 1999  Joris van der Hoeven
00006 *******************************************************************************
00007 * This software falls under the GNU general public license version 3 or later.
00008 * It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
00009 * in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
00010 ******************************************************************************/
00011 
00012 #include "pager.hpp"
00013 #include "Boxes/construct.hpp"
00014 
00015 /******************************************************************************
00016 * Routines for the pager class
00017 ******************************************************************************/
00018 
00019 pager_rep::pager_rep (path ip2, edit_env env2, array<page_item> l2):
00020   ip (ip2), env (env2), style (UNINIT), l (l2)
00021 {
00022   style (PAGE_THE_PAGE)   = tree (MACRO, compound ("page-nr"));
00023   style (PAGE_ODD_HEADER) = env->read (PAGE_ODD_HEADER);
00024   style (PAGE_ODD_FOOTER) = env->read (PAGE_ODD_FOOTER);
00025   style (PAGE_EVEN_HEADER)= env->read (PAGE_EVEN_HEADER);
00026   style (PAGE_EVEN_FOOTER)= env->read (PAGE_EVEN_FOOTER);
00027   style (PAGE_THIS_HEADER)= "";
00028   style (PAGE_THIS_FOOTER)= "";
00029 
00030   int nr_cols= env->get_int (PAR_COLUMNS);
00031   paper= (env->get_string (PAGE_MEDIUM) == "paper");
00032   string pbr= env->get_string (PAGE_BREAKING);
00033   quality= (pbr == "sloppy"? 0: (pbr == "medium"? 1: 2));
00034   env->get_page_pars (text_width, text_height, width, height,
00035                     odd, even, top, bot);
00036   may_extend= env->get_length (PAGE_EXTEND);
00037   may_shrink= env->get_length (PAGE_SHRINK);
00038   head_sep  = env->get_length (PAGE_HEAD_SEP);
00039   foot_sep  = env->get_length (PAGE_FOOT_SEP);
00040   col_sep   = env->get_length (PAR_COLUMNS_SEP);
00041   fn_sep    = env->get_vspace (PAR_FNOTE_SEP);
00042   fnote_sep = env->get_vspace (PAGE_FNOTE_SEP) + (2*env->fn->sep);
00043   fnote_bl  = env->get_length (PAGE_FNOTE_BARLEN);
00044   float_sep = env->get_vspace (PAGE_FLOAT_SEP);
00045   mnote_sep = env->get_length (PAGE_MNOTE_SEP);
00046   show_hf   = env->get_bool (PAGE_SHOW_HF) && paper;
00047   if (nr_cols > 1) text_width = (text_width+col_sep+1) * nr_cols - col_sep;
00048 
00049   page_offset= 0;
00050   cur_top= 0;
00051 }
00052 
00053 /******************************************************************************
00054 * Subroutines
00055 ******************************************************************************/
00056 
00057 box
00058 format_stack (path ip, array<box> bx, array<space> ht) {
00059   int i, n= N(bx);
00060   array<SI> spc (n);
00061   for (i=0; i<n-1; i++) spc[i]= ht[i]->def;
00062   return stack_box (ip, bx, spc);  
00063 }
00064 
00065 box
00066 format_stack (path ip, array<box> bx, array<space> ht, SI height,
00067              bool may_stretch)
00068 {
00069   int i, n= N(bx);
00070   array<SI> spc (n);
00071   space total (0);
00072   for (i=0; i<n-1; i++) total += space (bx[i]->h()) + ht[i];
00073   total += space (bx[i]->h());
00074 
00075   // stretching case
00076   if (may_stretch && (total->def < height) && (total->max > total->def)) {
00077     double f=
00078       ((double) (height - total->def)) /
00079       ((double) (total->max - total->def));
00080     for (i=0; i<n-1; i++)
00081       spc[i]= ht[i]->def+
00082        ((SI) (f*((double) ht[i]->max- ht[i]->def)));
00083   }
00084 
00085   // shrinking case
00086   else if ((total->def > height) && (total->def > total->min)) {
00087     double f=
00088       ((double) (total->def - height)) /
00089       ((double) (total->def - total->min));
00090     if (f>1.0) f=1.0;
00091     for (i=0; i<n-1; i++)
00092       spc[i]= ht[i]->def-
00093        ((SI) (f*((double) ht[i]->def- ht[i]->min)));
00094   }
00095 
00096   // normal case
00097   else for (i=0; i<n-1; i++) spc[i]= ht[i]->def;
00098 
00099   return stack_box (ip, bx, spc);
00100 }
00101 
00102 box
00103 format_stack (path ip, array<page_item> l) {
00104   int i, n= N(l);
00105   array<box> bs  (n);
00106   array<SI>  spc (n);
00107   for (i=0; i<n-1; i++) {
00108     bs [i]= l[i]->b;
00109     spc[i]= l[i]->spc->def;
00110   }
00111   if (i<n) bs [i]= l[i]->b;
00112   return stack_box (ip, bs, spc);  
00113 }
00114 
00115 box
00116 format_stack (path ip, array<page_item> l, SI height, bool may_stretch) {
00117   int i, n= N(l);
00118   array<box>   bs  (n);
00119   array<space> spc (n);
00120   for (i=0; i<n-1; i++) {
00121     bs [i]= l[i]->b;
00122     spc[i]= l[i]->spc;
00123   }
00124   if (i<n) bs [i]= l[i]->b;
00125   return format_stack (ip, bs, spc, height, may_stretch);
00126 }
00127 
00128 box
00129 page_box (path ip, box b, tree page,
00130          SI width, SI height, SI left, SI top, SI bot,
00131          box header, box footer, SI head_sep, SI foot_sep)
00132 {
00133   SI h_y= -top- header->y1+ head_sep;
00134   SI f_y= -bot- footer->y2- foot_sep;
00135 
00136   array<box> bs     (1); bs     [0]= b;
00137   array<SI>  bs_x   (1); bs_x   [0]= left;
00138   array<SI>  bs_y   (1); bs_y   [0]= -top;
00139   array<box> decs   (2); decs   [0]= header; decs   [1]= footer;
00140   array<SI>  decs_x (2); decs_x [0]= left  ; decs_x [1]= left;
00141   array<SI>  decs_y (2); decs_y [0]= h_y   ; decs_y [1]= f_y;
00142 
00143   return page_box (ip, page, width, height,
00144                  bs, bs_x, bs_y,
00145                  decs, decs_x, decs_y);
00146 }
00147 
00148 /******************************************************************************
00149 * Typesetting a page
00150 ******************************************************************************/
00151 
00152 /*
00153 void
00154 pager_rep::start_page () {
00155   lines_bx= array<box> (0);
00156   lines_ht= array<space> (0);
00157 }
00158 
00159 void
00160 pager_rep::print (page_item item) {
00161   if (item->type == PAGE_CONTROL_ITEM) {
00162     if (is_tuple (item->t, "env_page")) {
00163       if (((item->t[1] == PAGE_THIS_HEADER) ||
00164           (item->t[1] == PAGE_THIS_FOOTER)) &&
00165          (item->t[2] == "")) style (item->t[1]->label)= " ";
00166       else if (item->t[1] == PAGE_NR)
00167        page_offset= as_int (item->t[2]->label)- N(pages)- 1;
00168       else style (item->t[1]->label)= copy (item->t[2]);
00169     }
00170     return;
00171   }
00172   lines_bx << item->b;
00173   lines_ht << item->spc;
00174 }
00175 
00176 void
00177 pager_rep::end_page (bool flag) {
00178   box sb  = format_stack (ip, lines_bx, lines_ht, text_height, !flag);
00179   box lb  = move_box (ip, sb, 0, 0);
00180   SI  left= (N(pages)&1)==0? odd: even;
00181   box pb  = page_box (ip, lb, as_string (N(pages)+1+page_offset),
00182                     width, height, left, top, top+ text_height,
00183                     make_header(), make_footer(), head_sep, foot_sep);
00184 
00185   cur_top -= height;
00186   pages << pb;
00187 }
00188 */
00189 
00190 box
00191 pager_rep::make_header (bool empty_flag) {
00192   if (!show_hf || empty_flag) return empty_box (decorate ());
00193   env->write (PAGE_NR, as_string (N(pages)+1+page_offset));
00194   env->write (PAGE_THE_PAGE, style[PAGE_THE_PAGE]);
00195   tree old= env->local_begin (PAR_COLUMNS, "1");
00196   string which= (N(pages)&1)==0? PAGE_ODD_HEADER: PAGE_EVEN_HEADER;
00197   if (style [PAGE_THIS_HEADER] != "") which= PAGE_THIS_HEADER;
00198   box b= typeset_as_concat (env, attach_here (tree (PARA, style[which]),
00199                                          decorate()));
00200   style (PAGE_THIS_HEADER) = "";
00201   env->local_end (PAR_COLUMNS, old);
00202   return b;
00203 }
00204 
00205 box
00206 pager_rep::make_footer (bool empty_flag) {
00207   if (!show_hf || empty_flag) return empty_box (decorate ());
00208   env->write (PAGE_NR, as_string (N(pages)+1+page_offset));
00209   env->write (PAGE_THE_PAGE, style[PAGE_THE_PAGE]);
00210   tree old= env->local_begin (PAR_COLUMNS, "1");
00211   string which= (N(pages)&1)==0? PAGE_ODD_FOOTER: PAGE_EVEN_FOOTER;
00212   if (style [PAGE_THIS_FOOTER] != "") which= PAGE_THIS_FOOTER;
00213   box b= typeset_as_concat (env, attach_here (tree (PARA, style[which]),
00214                                          decorate()));
00215   style (PAGE_THIS_FOOTER) = "";
00216   env->local_end (PAR_COLUMNS, old);
00217   return b;
00218 }
00219 
00220 /******************************************************************************
00221 * Typesetting all pages
00222 ******************************************************************************/
00223 
00224 box
00225 pager_rep::make_pages () {
00226   if (paper) pages_make ();
00227   else papyrus_make ();
00228   int i, nr_pages= N(pages);
00229   array<SI>  x  (nr_pages);
00230   array<SI>  y  (nr_pages);
00231   for (i=0; i<nr_pages; i++) {
00232     x[i]= 0;
00233     y[i]= (i==0? 0: y[i-1]- pages[i-1]->h());
00234   }
00235   return move_box (ip, scatter_box (ip, pages, x, y), 0, 0);
00236 }