Back to index

texmacs  1.0.7.15
bridge_document.cpp
Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003 * MODULE     : bridge_document.cpp
00004 * DESCRIPTION: Bridge between logical and physically typesetted document
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.hpp"
00013 
00014 bridge bridge_docrange (typesetter ttt, tree st, path ip, array<bridge>& brs,
00015                      int begin, int end, bool divide);
00016 
00017 class bridge_document_rep: public bridge_rep {
00018 protected:
00019   array<bridge> brs;
00020   bridge acc; // binary splitting acceleration for long documents
00021 
00022 public:
00023   bridge_document_rep (typesetter ttt, tree st, path ip);
00024   void initialize ();
00025   void initialize_acc ();
00026 
00027   void notify_assign (path p, tree u);
00028   void notify_insert (path p, tree u);
00029   void notify_remove (path p, int nr);
00030   bool notify_macro  (int type, string var, int l, path p, tree u);
00031   void notify_change ();
00032 
00033   void my_exec_until (path p);
00034   bool my_typeset_will_be_complete ();
00035   void my_typeset (int desired_status);
00036 };
00037 
00038 bridge_document_rep::bridge_document_rep (typesetter ttt, tree st, path ip):
00039   bridge_rep (ttt, st, ip)
00040 {
00041   initialize ();
00042 }
00043 
00044 void
00045 bridge_document_rep::initialize () {
00046   int i, n= N(st);
00047   brs= array<bridge> (n);
00048   for (i=0; i<n; i++)
00049     brs[i]= make_bridge (ttt, st[i], descend (ip, i));
00050   initialize_acc ();
00051 }
00052 
00053 void
00054 bridge_document_rep::initialize_acc () {
00055   if (true || ttt->paper) acc= bridge ();
00056   else acc= bridge_docrange (ttt, st, ip, brs, 0, N(st), true);
00057 }
00058 
00059 bridge
00060 bridge_document (typesetter ttt, tree st, path ip) {
00061   return tm_new<bridge_document_rep> (ttt, st, ip);
00062 }
00063 
00064 /******************************************************************************
00065 * Event notification
00066 ******************************************************************************/
00067 
00068 void
00069 bridge_document_rep::notify_assign (path p, tree u) {
00070   // cout << "Assign " << p << ", " << u << " in " << st << "\n";
00071   ASSERT (!is_nil (p) || is_func (u, DOCUMENT) || is_func (u, PARA),
00072          "nil path");
00073   if (is_nil (p)) { st= u; initialize (); }
00074   else {
00075     if (is_atom (p)) {
00076       replace_bridge (brs[p->item], u, descend (ip, p->item));
00077       st= substitute (st, p->item, brs[p->item]->st);
00078     }
00079     else {
00080       brs[p->item]->notify_assign (p->next, u);
00081       st= substitute (st, p->item, brs[p->item]->st);
00082     }
00083     if (!is_nil (acc)) acc->notify_assign (p, u);
00084   }
00085   status= CORRUPTED;
00086 }
00087 
00088 void
00089 bridge_document_rep::notify_insert (path p, tree u) {
00090   //cout << "Insert " << p << ", " << u << " in " << st << "\n";
00091   ASSERT (!is_nil (p), "nil path");
00092   if (is_atom (p)) {
00093     int i, j, n= N(brs), pos= p->item, nr= N(u);
00094     array<bridge> brs2 (n+nr);
00095     if (pos>0) brs[pos-1]->notify_change (); // touch in case of surroundings
00096     if (pos<n) brs[pos  ]->notify_change (); // touch in case of surroundings
00097     for (i=0; i<pos; i++) brs2[i]= brs[i];
00098     for (j=0; j<nr ; j++) brs2[i+j]= make_bridge (ttt, u[j], descend (ip,i+j));
00099     for (; i<n; i++) {
00100       brs2[i+nr]= brs[i];
00101       brs2[i+nr]->ip->item += nr;
00102     }
00103     brs= brs2;
00104     st = (st (0, p->item) * u) * st (p->item, N(st));
00105     if (!is_nil (acc)) acc->notify_insert (p, u);
00106     // initialize_acc ();
00107   }
00108   else {
00109     brs[p->item]->notify_insert (p->next, u);
00110     st= substitute (st, p->item, brs[p->item]->st);
00111     if (!is_nil (acc)) acc->notify_assign (p->item, st[p->item]);
00112   }
00113   status= CORRUPTED;
00114 }
00115 
00116 void
00117 bridge_document_rep::notify_remove (path p, int nr) {
00118   // cout << "Remove " << p << ", " << nr << " in " << st << "\n";
00119   ASSERT (!is_nil (p), "nil path");
00120   if (is_atom (p)) {
00121     int i, n= N(brs), pos= p->item;
00122     array<bridge> brs2 (n-nr);
00123     for (i=0; i<pos ; i++) brs2[i]= brs[i];
00124     for (; i<n-nr; i++) {
00125       brs2[i]= brs[i+nr];
00126       brs2[i]->ip->item -= nr;
00127     }
00128     bool change_flag= false;
00129     for (i=pos; i<pos+nr; i++)
00130       change_flag |= !brs[i]->changes->empty();
00131     brs= brs2;
00132     n -= nr;
00133     st = st (0, pos) * st (pos+nr, N(st));
00134     if (pos>0) brs[pos-1]->notify_change (); // touch in case of surroundings
00135     if (pos<n) brs[pos  ]->notify_change (); // touch in case of surroundings
00136     if (change_flag) // touch brs[pos..n] for correct ``changes handling''
00137       for (i=pos; i<n; i++)
00138        brs[i]->notify_change ();
00139     if (!is_nil (acc)) acc->notify_remove (p, nr);
00140     // initialize_acc ();
00141   }
00142   else {
00143     brs[p->item]->notify_remove (p->next, nr);
00144     st= substitute (st, p->item, brs[p->item]->st);
00145     if (!is_nil (acc)) acc->notify_assign (p->item, st[p->item]);
00146   }
00147   status= CORRUPTED;
00148 }
00149 
00150 bool
00151 bridge_document_rep::notify_macro (int tp, string var, int l, path p, tree u) {
00152   bool flag= false;
00153   int i, n= N(brs);
00154   for (i=0; i<n; i++)
00155     flag= brs[i]->notify_macro (tp, var, l, p, u) || flag;
00156   if (flag) {
00157     status= CORRUPTED;
00158     if (!is_nil (acc)) acc->notify_change ();
00159   }
00160   return flag;
00161 }
00162 
00163 void
00164 bridge_document_rep::notify_change () {
00165   status= CORRUPTED;
00166   if (!is_nil (acc)) acc->notify_change ();
00167   if (N(brs)>0) brs[0]->notify_change ();
00168   if (N(brs)>1) brs[N(brs)-1]->notify_change ();
00169 }
00170 
00171 /******************************************************************************
00172 * Typesetting
00173 ******************************************************************************/
00174 
00175 void
00176 bridge_document_rep::my_exec_until (path p) {
00177   if (is_nil (acc)) {
00178     int i;
00179     for (i=0; i<p->item; i++)
00180       brs[i]->exec_until (path (right_index (brs[i]->st)), true);
00181     if (i<N(st)) brs[i]->exec_until (p->next);
00182   }
00183   else acc->my_exec_until (p);
00184 }
00185 
00186 bool
00187 bridge_document_rep::my_typeset_will_be_complete () {
00188   if (is_nil (acc)) {
00189     int i, n= N(brs);
00190     for (i=0; i<n; i++)
00191       if (!brs[i]->my_typeset_will_be_complete ()) return false;
00192     return true;
00193   }
00194   else return acc->my_typeset_will_be_complete ();
00195 }
00196 
00197 void
00198 bridge_document_rep::my_typeset (int desired_status) {
00199   //cout << INDENT;
00200   if (is_nil (acc)) {
00201     int i, n= N(st);
00202     array<line_item> a= ttt->a;
00203     array<line_item> b= ttt->b;
00204     for (i=0; i<n; i++) {
00205       //cout << "Typesetting " << st[i] << LF;
00206       int wanted= (i==n-1? desired_status & WANTED_MASK: WANTED_PARAGRAPH);
00207       ttt->a= (i==0  ? a: array<line_item> ());
00208       ttt->b= (i==n-1? b: array<line_item> ());
00209       brs[i]->typeset (PROCESSED+ wanted);
00210     }
00211   }
00212   else acc->my_typeset (desired_status);
00213   //cout << UNINDENT;
00214 }