Back to index

texmacs  1.0.7.15
tree_position.cpp
Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003 * MODULE     : tree_position.cpp
00004 * DESCRIPTION: Persistently attach cursor positions to trees
00005 * COPYRIGHT  : (C) 2005  Joris van der Hoeven
00006 *******************************************************************************
00007 * An inverse path observer maintains the inverse path of the position
00008 * of the corresponding tree with respect to the global meta-tree.
00009 *******************************************************************************
00010 * This software falls under the GNU general public license version 3 or later.
00011 * It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
00012 * in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
00013 ******************************************************************************/
00014 
00015 #include "tree.hpp"
00016 #include "path.hpp"
00017 
00018 #define DETACHED (-5)
00019 
00020 /******************************************************************************
00021 * Definition of the tree_position_rep class
00022 ******************************************************************************/
00023 
00024 class tree_position_rep: public observer_rep {
00025   tree_rep* ptr;
00026   int index;
00027 
00028 public:
00029   tree_position_rep (tree ref, int index2): ptr (ref.rep), index (index2) {}
00030   int get_type () { return OBSERVER_POSITION; }
00031   tm_ostream& print (tm_ostream& out) { return out << " " << index; }
00032 
00033   void notify_assign      (tree& ref, tree t);
00034   void notify_insert      (tree& ref, int pos, int nr);
00035   void notify_remove      (tree& ref, int pos, int nr);
00036   void notify_split       (tree& ref, int pos, tree prev);
00037   void notify_var_split   (tree& ref, tree t1, tree t2);
00038   void notify_join        (tree& ref, int pos, tree next);
00039   void notify_var_join    (tree& ref, tree t, int offset);
00040   void notify_assign_node (tree& ref, tree_label op);
00041   void notify_insert_node (tree& ref, int pos);
00042   void notify_remove_node (tree& ref, int pos);
00043   void notify_detach      (tree& ref, tree closest, bool right);
00044 
00045   bool get_position (tree& t, int& index);
00046   bool set_position (tree t, int index);
00047 };
00048 
00049 /******************************************************************************
00050 * Re-attaching the position to another tree
00051 ******************************************************************************/
00052 
00053 bool
00054 tree_position_rep::get_position (tree& t, int& index2) {
00055   t     = tree (ptr);
00056   index2= index;
00057   return true;
00058 }
00059 
00060 bool
00061 tree_position_rep::set_position (tree t, int index2) {
00062   tree ref (ptr);
00063   detach_observer (ref, observer (this));
00064   ptr  = t.rep;
00065   index= index2;
00066   attach_observer (t, observer (this));
00067   return true;
00068 }
00069 
00070 void
00071 reattach_at (tree_position_rep* rep, tree t, int index) {
00072   rep->set_position (t, index);
00073 }
00074 
00075 void reattach_left (tree_position_rep* rep, tree t) {
00076   reattach_at (rep, t, 0); }
00077 void reattach_right (tree_position_rep* rep, tree t) {
00078   reattach_at (rep, t, right_index (t)); }
00079 
00080 /******************************************************************************
00081 * Call back routines for modifications
00082 ******************************************************************************/
00083 
00084 void
00085 tree_position_rep::notify_assign (tree& ref, tree t) {
00086   // cout << "Notify assign " << ref << ", " << t << "\n";
00087   bool left=
00088     (is_atomic (ref) && (index <= (N(ref->label) >> 1))) || (index == 0);
00089   if (left) reattach_left (this, t);
00090   else reattach_right (this, t);
00091   // cout << "position -> " << obtain_position (observer (this)) << "\n";
00092 }
00093 
00094 void
00095 tree_position_rep::notify_insert (tree& ref, int pos, int nr) {
00096   // cout << "Notify insert " << ref << ", " << pos << ", " << nr << "\n";
00097   if (is_atomic (ref) && index >= pos)
00098     index += nr;
00099   // cout << "position -> " << obtain_position (observer (this)) << "\n";
00100 }
00101 
00102 void
00103 tree_position_rep::notify_remove (tree& ref, int pos, int nr) {
00104   // cout << "Notify remove " << ref << ", " << pos << ", " << nr << "\n";
00105   if (is_atomic (ref)) {
00106     if (index >= pos)
00107       index= max (pos, index - nr);
00108   }
00109   // cout << "position -> " << obtain_position (observer (this)) << "\n";
00110 }
00111 
00112 void
00113 tree_position_rep::notify_split (tree& ref, int pos, tree prev) {
00114   (void) ref; (void) pos; (void) prev;
00115 }
00116 
00117 void
00118 tree_position_rep::notify_var_split (tree& ref, tree t1, tree t2) {
00119   // cout << "Notify var split " << ref << ", " << t1 << ", " << t2 << "\n";
00120   if (is_atomic (ref)) {
00121     if (index <= N(t1->label)) reattach_at (this, t1, index);
00122     else reattach_at (this, t2, index - N(t1->label));
00123   }
00124   else {
00125     if (index == 0) reattach_left (this, t1);
00126     else reattach_right (this, t2);
00127   }
00128   // cout << "position -> " << obtain_position (observer (this)) << "\n";
00129 }
00130 
00131 void
00132 tree_position_rep::notify_join (tree& ref, int pos, tree next) {
00133   (void) ref; (void) pos; (void) next;
00134 }
00135 
00136 void
00137 tree_position_rep::notify_var_join (tree& ref, tree t, int offset) {
00138   // cout << "Notify var join " << ref << ", " << t << ", " << offset << "\n";
00139   if (is_atomic (ref))
00140     reattach_at (this, t, index + offset);
00141   else {
00142     if (index != 0) reattach_right (this, t);
00143     else if (offset > 0) reattach_right (this, t[offset-1]);
00144     else if (N(t) != 0) reattach_left (this, t[0]);
00145     else reattach_left (this, t);
00146   }
00147   // cout << "position -> " << obtain_position (observer (this)) << "\n";
00148 }
00149 
00150 void
00151 tree_position_rep::notify_assign_node (tree& ref, tree_label op) {
00152   // cout << "Notify assign node " << ref << ", " << as_string (op) << "\n";
00153   (void) ref; (void) op;
00154   // cout << "position -> " << obtain_position (observer (this)) << "\n";
00155 }
00156 
00157 void
00158 tree_position_rep::notify_insert_node (tree& ref, int pos) {
00159   // cout << "Notify insert node " << ref << ", " << pos << "\n";
00160   (void) ref; (void) pos;
00161   // cout << "position -> " << obtain_position (observer (this)) << "\n";
00162 }
00163 
00164 void
00165 tree_position_rep::notify_remove_node (tree& ref, int pos) {
00166   // cout << "Notify remove node " << ref << ", " << pos << "\n";
00167   if (index == 0) reattach_left (this, ref[pos]);
00168   else reattach_right (this, ref[pos]);
00169   // cout << "position -> " << obtain_position (observer (this)) << "\n";
00170 }
00171 
00172 void
00173 tree_position_rep::notify_detach (tree& ref, tree closest, bool right) {
00174   (void) ref;
00175   // cout << "Notify detach " << ref << ", " << closest <<", "<< right << "\n";
00176   if (right) reattach_right (this, closest);
00177   else reattach_left (this, closest);
00178   // cout << "position -> " << obtain_position (observer (this)) << "\n";
00179 }
00180 
00181 /******************************************************************************
00182 * Public interface
00183 ******************************************************************************/
00184 
00185 observer
00186 tree_position (tree ref, int index) {
00187   return tm_new<tree_position_rep> (ref, index);
00188 }
00189 
00190 path
00191 obtain_position (observer o) {
00192   tree t;
00193   int  index;
00194   if (!o->get_position (t, index)) return path ();
00195   path ip= obtain_ip (t);
00196   if (ip == path (DETACHED)) return path ();
00197   return reverse (ip) * index;
00198 }