Back to index

texmacs  1.0.7.15
bridge_auto.cpp
Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003 * MODULE     : bridge_auto.cpp
00004 * DESCRIPTION: Bridge for automatically inserted macro expansions (inactive)
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 tree insert_at (tree, path, tree);
00015 tree remove_at (tree, path, int);
00016 
00017 class bridge_auto_rep: public bridge_rep {
00018 protected:
00019   tree   f;
00020   bool   border;
00021   bool   valid;
00022   bridge body;
00023 
00024 public:
00025   bridge_auto_rep (typesetter ttt, tree st, path ip, tree f, bool border);
00026   void initialize ();
00027 
00028   void notify_assign (path p, tree u);
00029   void notify_insert (path p, tree u);
00030   void notify_remove (path p, int nr);
00031   bool notify_macro  (int type, string var, int level, path p, tree u);
00032   void notify_change ();
00033 
00034   void my_exec_until (path p);
00035   void exec_until (path p, bool skip_flag);
00036   bool my_typeset_will_be_complete ();
00037   void my_typeset (int desired_status);
00038 };
00039 
00040 bridge_auto_rep::bridge_auto_rep (
00041   typesetter ttt, tree st, path ip, tree f2, bool border2):
00042     bridge_rep (ttt, st, ip)
00043 {
00044   f     = f2;
00045   border= border2;
00046   valid = false;
00047 }
00048 
00049 void
00050 bridge_auto_rep::initialize () {
00051   if ((!valid) || (body->st != f[1])) {
00052     valid= true;
00053     if (is_nil (body)) body= make_bridge (ttt, attach_right (f[1], ip));
00054     else replace_bridge (body, attach_right (f[1], ip));
00055   }
00056 }
00057 
00058 bridge
00059 bridge_auto (typesetter ttt, tree st, path ip, tree f, bool border) {
00060   return tm_new<bridge_auto_rep> (ttt, st, ip, f, border);
00061 }
00062 
00063 /******************************************************************************
00064 * Event notification
00065 ******************************************************************************/
00066 
00067 void
00068 bridge_auto_rep::notify_assign (path p, tree u) {
00069   //cout << "Assign " << p << ", " << u << " in " << st << "\n";
00070   if (is_nil (body)) {
00071     st= substitute (st, p, u);
00072     valid= false;
00073   }
00074   else {
00075     // bool mp_flag= is_multi_paragraph (st);
00076     notify_macro (MACRO_ASSIGN, f[0]->label, -1, p->next, u);
00077     st= substitute (st, p, u);
00078     // if (mp_flag != is_multi_paragraph (st)) valid= false;
00079   }
00080   status= CORRUPTED;
00081 }
00082 
00083 void
00084 bridge_auto_rep::notify_insert (path p, tree u) {
00085   //cout << "Insert " << p << ", " << u << " in " << st << "\n";
00086   if (is_nil (body)) bridge_rep::notify_insert (p, u);
00087   else {
00088     // bool mp_flag= is_multi_paragraph (st);
00089     notify_macro (MACRO_INSERT, f[0]->label, -1, p->next, u);
00090     st= insert_at (st, p, u);
00091     // if (mp_flag != is_multi_paragraph (st)) valid= false;
00092   }
00093   status= CORRUPTED;
00094 }
00095 
00096 void
00097 bridge_auto_rep::notify_remove (path p, int nr) {
00098   //cout << "Remove " << p << ", " << nr << " in " << st << "\n";
00099   if (is_nil (body)) bridge_rep::notify_remove (p, nr);
00100   else {
00101     // bool mp_flag= is_multi_paragraph (st);
00102     notify_macro (MACRO_REMOVE, f[0]->label, -1, p->next,
00103                 tree (as_string (nr)));
00104     st= remove_at (st, p, nr);
00105     // if (mp_flag != is_multi_paragraph (st)) valid= false;
00106   }
00107   status= CORRUPTED;
00108 }
00109 
00110 bool
00111 bridge_auto_rep::notify_macro (
00112   int type, string var, int l, path p, tree u)
00113 {
00114   /*
00115   cout << "Macro argument " << var << " [action=" << type
00116        << ", level=" << l << "] " << p << ", " << u << " in " << st << "\n";
00117   */
00118 
00119   bool flag;
00120   if (valid) {
00121     env->macro_arg= list<hashmap<string,tree> > (
00122       hashmap<string,tree> (UNINIT), env->macro_arg);
00123     env->macro_src= list<hashmap<string,path> > (
00124       hashmap<string,path> (path (DECORATION)), env->macro_src);
00125     string var= f[0]->label;
00126     env->macro_arg->item (var)= st;
00127     env->macro_src->item (var)= ip;
00128     flag= body->notify_macro (type, var, l+1, p, u);
00129     env->macro_arg= env->macro_arg->next;
00130     env->macro_src= env->macro_src->next;
00131   }
00132   else flag= env->depends (st, var, l);
00133   if (flag) status= CORRUPTED;
00134   return flag;
00135 }
00136 
00137 void
00138 bridge_auto_rep::notify_change () {
00139   status= CORRUPTED;
00140   if (!is_nil (body)) body->notify_change ();
00141 }
00142 
00143 /******************************************************************************
00144 * Typesetting
00145 ******************************************************************************/
00146 
00147 void
00148 bridge_auto_rep::my_exec_until (path p) {
00149   env->macro_arg= list<hashmap<string,tree> >
00150     (hashmap<string,tree> (UNINIT), env->macro_arg);
00151   env->macro_src= list<hashmap<string,path> >
00152     (hashmap<string,path> (path (DECORATION)), env->macro_src);
00153   string var= f[0]->label;
00154   env->macro_arg->item (var)= st;
00155   (void) env->exec_until (f[1], p, var, 0);
00156   env->macro_arg= env->macro_arg->next;
00157   env->macro_src= env->macro_src->next;
00158 }
00159 
00160 void
00161 bridge_auto_rep::exec_until (path p, bool skip_flag) {
00162   // If we are executing until the start or the end of an automatic bridge,
00163   // some of the environment variables may be different from the usual
00164   // exec_until. For instance, for inactive* tags, we put ourselves
00165   // in source mode. The usual exec_until can only be used if we are
00166   // sure that are really executing until somewhere strictly after this bridge.
00167 
00168   if (skip_flag) bridge_rep::exec_until (p, skip_flag);
00169   else {
00170     if ((status & VALID_MASK) != PROCESSED) env->exec_until (st, p);
00171     else my_exec_until (p);
00172   }
00173 }
00174 
00175 bool
00176 bridge_auto_rep::my_typeset_will_be_complete () {
00177   return !valid;
00178 }
00179 
00180 void
00181 bridge_auto_rep::my_typeset (int desired_status) {
00182   env->macro_arg= list<hashmap<string,tree> > (
00183     hashmap<string,tree> (UNINIT), env->macro_arg);
00184   env->macro_src= list<hashmap<string,path> > (
00185     hashmap<string,path> (path (DECORATION)), env->macro_src);
00186   string var= f[0]->label;
00187   env->macro_arg->item (var)= st;
00188   env->macro_src->item (var)= ip;
00189   tree oldv= env->read (PREAMBLE);
00190   env->write_update (PREAMBLE, "false");
00191   initialize ();
00192   if (border) ttt->insert_marker (st, ip);
00193   body->typeset (desired_status);
00194   env->write_update (PREAMBLE, oldv);
00195   env->macro_arg= env->macro_arg->next;
00196   env->macro_src= env->macro_src->next;
00197 }