Back to index

texmacs  1.0.7.15
typesetter.cpp
Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003 * MODULE     : typesetter.hpp
00004 * DESCRIPTION: Implementation of the main TeXmacs typesetting routines
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 "Bridge/impl_typesetter.hpp"
00013 #include "iterator.hpp"
00014 
00015 /******************************************************************************
00016 * Constructor and destructor
00017 ******************************************************************************/
00018 
00019 typesetter_rep::typesetter_rep (edit_env& env2, tree et, path ip):
00020   env (env2), old_patch (UNINIT)
00021 {
00022   paper= (env->get_string (PAGE_MEDIUM) == "paper");
00023   br= make_bridge (this, et, ip);
00024   x1= y1= x2= y2=0;
00025 }
00026 
00027 typesetter
00028 new_typesetter (edit_env& env, tree et, path ip) {
00029   return tm_new<typesetter_rep> (env, et, ip);
00030 }
00031 
00032 void
00033 delete_typesetter (typesetter ttt) {
00034   tm_delete (ttt);
00035 }
00036 
00037 /******************************************************************************
00038 * Output flux
00039 ******************************************************************************/
00040 
00041 void
00042 typesetter_rep::insert_stack (array<page_item> l2, stack_border sb2) {
00043   merge_stack (l, sb, l2, sb2);
00044 }
00045 
00046 void
00047 typesetter_rep::insert_parunit (tree t, path ip) {
00048   insert_paragraph (t, ip);
00049 }
00050 
00051 void
00052 typesetter_rep::insert_paragraph (tree t, path ip) {
00053   // cout << "Typesetting " << t << ", " << ip << "\n";
00054   stack_border     temp_sb;
00055   array<page_item> temp_l= typeset_stack (env, t, ip, a, b, temp_sb);
00056   insert_stack (temp_l, temp_sb);
00057 
00058   /*
00059   int i, n= N(temp_l);
00060   for (i=0; i<n; i++)
00061     cout << i << ", "
00062         << temp_l[i]->b->find_lip () << ", "
00063         << temp_l[i]->b->find_rip () << ",\t"
00064         << temp_l[i]->b << "\n";
00065   */
00066 }
00067 
00068 void
00069 typesetter_rep::insert_surround  (array<line_item> a2, array<line_item> b2) {
00070   a << a2;
00071   array<line_item> temp_b= b;
00072   b= copy (b2);
00073   b << temp_b;
00074 }
00075 
00076 void
00077 typesetter_rep::insert_marker (tree st, path ip) {
00078   (void) st;
00079   // if (!is_multi_paragraph (st)) {
00080   array<line_item> a2= typeset_marker (env, descend (ip, 0));
00081   array<line_item> b2= typeset_marker (env, descend (ip, 1));
00082   insert_surround (a2, b2);
00083   // }
00084 }
00085 
00086 void
00087 typesetter_rep::local_start (array<page_item>& prev_l, stack_border& prev_sb) {
00088   prev_l   = l;
00089   prev_sb  = sb;
00090   l        = array<page_item> ();
00091   sb       = stack_border ();
00092 }
00093 
00094 void
00095 typesetter_rep::local_end (array<page_item>& prev_l, stack_border& prev_sb) {
00096   array<page_item> temp_l   = l;
00097   stack_border     temp_sb  = sb;
00098   l        = prev_l;
00099   sb       = prev_sb;
00100   prev_l   = temp_l;
00101   prev_sb  = temp_sb;
00102 }
00103 
00104 /******************************************************************************
00105 * Main typesetting routines
00106 ******************************************************************************/
00107 
00108 static rectangles
00109 requires_update (rectangles log) {
00110   rectangles rs;
00111   while (!is_nil (log)) {
00112     rectangle r1= log->item;
00113     rectangle r2= log->next->item;
00114     if (r1 == rectangle (0, 0, 0, 0)) rs= rectangles (r2, rs);
00115     else if (r2 == rectangle (0, 0, 0, 0)) rs= rectangles (r1, rs);
00116     else if (r1 != r2) rs= rectangles (r1, rectangles (r2, rs));
00117     log= log->next->next;
00118   }
00119   return reverse (rs);
00120 }
00121 
00122 void
00123 typesetter_rep::determine_page_references (box b) {
00124   hashmap<string,tree> h ("?");
00125   b->collect_page_numbers (h, "?");
00126   iterator<string> it= iterate (h);
00127   while (it->busy()) {
00128     string var= it->next ();
00129     tree   val= copy (h[var]);
00130     tree   old= env->local_ref [var];
00131     if (is_func (old, TUPLE, 2))
00132       env->local_ref (var)= tuple (old[0], val);
00133     else if (is_func (old, TUPLE, 3))
00134       env->local_ref (var)= tuple (old[0], val, old[2]);
00135     else env->local_ref (var)= tuple (old, val);
00136   }
00137 }
00138 
00139 box
00140 typesetter_rep::typeset () {
00141   old_patch= hashmap<string,tree> (UNINIT);
00142   l        = array<page_item> ();
00143   sb       = stack_border ();
00144   a        = array<line_item> ();
00145   b        = array<line_item> ();
00146   paper    = (env->get_string (PAGE_MEDIUM) == "paper");
00147 
00148   // Test whether we are doing a complete typesetting
00149   env->complete= br->my_typeset_will_be_complete ();
00150   tree st= br->st;
00151   int i= 0, n= N(st);
00152   if (is_compound (st[0], "show-preamble")) { i++; env->complete= false; }
00153   if (is_compound (st[0], "hide-preamble")) i++;
00154   for (; i<n && env->complete; i++) {
00155     if (is_compound (st[i], "hide-part")) env->complete= false;
00156     if (!is_compound (st[i], "show-part")) break;
00157   }
00158 
00159   // Typeset
00160   if (env->complete) env->local_aux= hashmap<string,tree> (UNINIT);
00161   br->typeset (PROCESSED+ WANTED_PARAGRAPH);
00162   pager ppp= tm_new<pager_rep> (br->ip, env, l);
00163   box b= ppp->make_pages ();
00164   if (env->complete && paper) determine_page_references (b);
00165   tm_delete (ppp);
00166   env->complete= false;
00167 
00168   return b;
00169 }
00170 
00171 box
00172 typesetter_rep::typeset (SI& x1b, SI& y1b, SI& x2b, SI& y2b) {
00173   x1= x1b; y1= y1b; x2=x2b; y2= y2b;
00174   box b= typeset ();
00175   // cout << "-------------------------------------------------------------\n";
00176   b->position_at (0, 0, change_log);
00177   change_log= requires_update (change_log);
00178   rectangle r (0, 0, 0, 0);
00179   if (!is_nil (change_log)) r= least_upper_bound (change_log);
00180   x1b= r->x1; y1b= r->y1; x2b= r->x2; y2b= r->y2;
00181   change_log= rectangles ();
00182   return b;
00183 }
00184 
00185 /******************************************************************************
00186 * Event notification
00187 ******************************************************************************/
00188 
00189 void
00190 notify_assign (typesetter ttt, path p, tree u) {
00191   // cout << "Assign " << p << ", " << u << "\n";
00192   if (is_nil (p)) ttt->br= make_bridge (ttt, u, ttt->br->ip);
00193   else ttt->br->notify_assign (p, u);
00194 }
00195 
00196 void
00197 notify_insert (typesetter ttt, path p, tree u) {
00198   // cout << "Insert " << p << ", " << u << "\n";
00199   ttt->br->notify_insert (p, u);
00200 }
00201 
00202 void
00203 notify_remove (typesetter ttt, path p, int nr) {
00204   // cout << "Remove " << p << ", " << nr << "\n";
00205   ttt->br->notify_remove (p, nr);
00206 }
00207 
00208 void
00209 notify_split (typesetter ttt, path p) {
00210   // cout << "Split " << p << "\n";
00211   ttt->br->notify_split (p);
00212 }
00213 
00214 void
00215 notify_join (typesetter ttt, path p) {
00216   // cout << "Join " << p << "\n";
00217   ttt->br->notify_join (p);
00218 }
00219 
00220 void
00221 notify_assign_node (typesetter ttt, path p, tree_label op) {
00222   // cout << "Assign node " << p << ", " << as_string (op) << "\n";
00223   tree t= subtree (ttt->br->st, p);
00224   int i, n= N(t);
00225   tree r (op, n);
00226   for (i=0; i<n; i++) r[i]= t[i];
00227   if (is_nil (p)) ttt->br= make_bridge (ttt, r, ttt->br->ip);
00228   else ttt->br->notify_assign (p, r);
00229 }
00230 
00231 void
00232 notify_insert_node (typesetter ttt, path p, tree t) {
00233   // cout << "Insert node " << p << ", " << t << "\n";
00234   int i, pos= last_item (p), n= N(t);
00235   tree r (t, n+1);
00236   for (i=0; i<pos; i++) r[i]= t[i];
00237   r[pos]= subtree (ttt->br->st, path_up (p));
00238   for (i=pos; i<n; i++) r[i+1]= t[i];
00239   if (is_nil (path_up (p))) ttt->br= make_bridge (ttt, r, ttt->br->ip);
00240   else ttt->br->notify_assign (path_up (p), r);
00241 }
00242 
00243 void
00244 notify_remove_node (typesetter ttt, path p) {
00245   // cout << "Remove node " << p << "\n";
00246   tree t= subtree (ttt->br->st, p);
00247   if (is_nil (path_up (p))) ttt->br= make_bridge (ttt, t, ttt->br->ip);
00248   else ttt->br->notify_assign (path_up (p), t);
00249 }
00250 
00251 /******************************************************************************
00252 * Getting environment variables and typesetting interface
00253 ******************************************************************************/
00254 
00255 void
00256 exec_until (typesetter ttt, path p) {
00257   ttt->br->exec_until (p);
00258 }
00259 
00260 box
00261 typeset (typesetter ttt, SI& x1, SI& y1, SI& x2, SI& y2) {
00262   return ttt->typeset (x1, y1, x2, y2);
00263 }
00264 
00265 box
00266 typeset_as_document (edit_env env, tree t, path ip) {
00267   env->style_init_env ();
00268   env->update ();
00269   typesetter ttt= new_typesetter (env, t, ip);
00270   box b= ttt->typeset ();
00271   delete_typesetter (ttt);
00272   return b;
00273 }