Back to index

texmacs  1.0.7.15
bridge_surround.cpp
Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003 * MODULE     : bridge_surround.cpp
00004 * DESCRIPTION: Bridge between logical and physical paragraph surroundings
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 class bridge_surround_rep: public bridge_rep {
00015 protected:
00016   bridge               body;
00017   hashmap<string,tree> changes_before;
00018 
00019   bool                 corrupted;
00020   array<line_item>     a;
00021   array<line_item>     b;
00022 
00023 public:
00024   bridge_surround_rep (typesetter ttt, tree st, path ip);
00025   void initialize ();
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 level, path p, tree u);
00031   void notify_change ();
00032 
00033   void my_clean_links ();
00034   void my_exec_until (path p);
00035   bool my_typeset_will_be_complete ();
00036   void my_typeset (int desired_status);
00037 };
00038 
00039 bridge_surround_rep::bridge_surround_rep (typesetter ttt, tree st, path ip):
00040   bridge_rep (ttt, st, ip), changes_before (UNINIT)
00041 {
00042   initialize ();
00043 }
00044 
00045 void
00046 bridge_surround_rep::initialize () {
00047   while (N(st)<3) // hack for temporarily incorrect situations (A-backspace)
00048     st= tree (SURROUND, "") * st;
00049   if (is_nil (body)) body= make_bridge (ttt, st[2], descend (ip, 2));
00050   else replace_bridge (body, st[2], descend (ip, 2));
00051   changes_before= hashmap<string,tree> (UNINIT);
00052   corrupted= true;
00053 }
00054 
00055 bridge
00056 bridge_surround (typesetter ttt, tree st, path ip) {
00057   return tm_new<bridge_surround_rep> (ttt, st, ip);
00058 }
00059 
00060 /******************************************************************************
00061 * Event notification
00062 ******************************************************************************/
00063 
00064 void
00065 bridge_surround_rep::notify_assign (path p, tree u) {
00066   // cout << "Assign " << p << ", " << u << " in " << st << "\n";
00067   ASSERT (!is_nil (p) || is_func (u, SURROUND), "nil path");
00068   if (is_nil (p) || (p->item != 2)) {
00069     st= substitute (st, p, u);
00070     initialize ();
00071   }
00072   else {
00073     // bool mp_flag= is_multi_paragraph (st);
00074     if (is_atom (p)) {
00075       body= make_bridge (ttt, u, descend (ip, 2));
00076       st= substitute (st, 2, body->st);
00077     }
00078     else {
00079       body->notify_assign (p->next, u);
00080       st= substitute (st, p->item, body->st);
00081     }
00082     // if (mp_flag != is_multi_paragraph (st)) initialize ();
00083   }
00084   status= CORRUPTED;
00085 }
00086 
00087 void
00088 bridge_surround_rep::notify_insert (path p, tree u) {
00089   // cout << "Insert " << p << ", " << u << " in " << st << "\n";
00090   ASSERT (!is_nil (p), "nil path");
00091   if (is_atom (p) || (p->item != 2)) bridge_rep::notify_insert (p, u);
00092   else {
00093     // bool mp_flag= is_multi_paragraph (st);
00094     body->notify_insert (p->next, u);
00095     st= substitute (st, 2, body->st);
00096     // if (mp_flag != is_multi_paragraph (st)) initialize ();
00097   }
00098   status= CORRUPTED;
00099 }
00100 
00101 void
00102 bridge_surround_rep::notify_remove (path p, int nr) {
00103   // cout << "Remove " << p << ", " << nr << " in " << st << "\n";
00104   ASSERT (!is_nil (p), "nil path");
00105   if (is_atom (p) || (p->item != 2)) bridge_rep::notify_remove (p, nr);
00106   else {
00107     // bool mp_flag= is_multi_paragraph (st);
00108     body->notify_remove (p->next, nr);
00109     st= substitute (st, 2, body->st);
00110     // if (mp_flag != is_multi_paragraph (st)) initialize ();
00111   }
00112   status= CORRUPTED;
00113 }
00114 
00115 bool
00116 bridge_surround_rep::notify_macro (int tp, string var, int l, path p, tree u) {
00117   /*
00118   cout << "Macro argument " << var << " [action=" << tp
00119        << ", level=" << l << "] " << p << ", " << u << " in " << st << "\n";
00120   */
00121 
00122   bool flag= env->depends (st[0], var, l) || env->depends (st[1], var, l);
00123   if (flag) initialize ();
00124   flag= body->notify_macro (tp, var, l, p, u) || flag;
00125   if (flag) status= CORRUPTED;
00126   return flag;
00127 }
00128 
00129 void
00130 bridge_surround_rep::notify_change () {
00131   status= CORRUPTED;
00132   corrupted= true;
00133   body->notify_change ();
00134 }
00135 
00136 /******************************************************************************
00137 * Typesetting
00138 ******************************************************************************/
00139 
00140 void
00141 bridge_surround_rep::my_clean_links () {
00142   if (corrupted || (N(ttt->old_patch) != 0))
00143     link_env= link_repository (true);
00144 }
00145 
00146 void
00147 bridge_surround_rep::my_exec_until (path p) {
00148   if (p->item == 2) {
00149     env->patch_env (changes_before);
00150     body->exec_until (p->next);
00151   }
00152   else env->exec_until (st, p);
00153 }
00154 
00155 bool
00156 bridge_surround_rep::my_typeset_will_be_complete () {
00157   if (status != CORRUPTED) return false;
00158   return body->my_typeset_will_be_complete ();
00159 }
00160 
00161 void
00162 bridge_surround_rep::my_typeset (int desired_status) {
00163   if (corrupted || (N(ttt->old_patch) != 0)) {
00164     hashmap<string,tree> prev_back (UNINIT);
00165     env->local_start (prev_back);
00166     /*
00167     cout << st[0] << "\n";
00168     cout << st[1] << "\n";
00169     cout << "-------------------------------------------------------------\n";
00170     */
00171     a= typeset_concat (env, st[0], descend (ip, 0));
00172     b= typeset_concat (env, st[1], descend (ip, 1));
00173     env->local_update (ttt->old_patch, changes_before);
00174     env->local_end (prev_back);
00175     corrupted= false;
00176   }
00177   else env->monitored_patch_env (changes_before);
00178 
00179   ttt->insert_marker (st, ip);
00180   ttt->insert_surround (a, b);
00181   body->typeset (desired_status);
00182 }