Fix Xcode warnings, part I
[texmacs.git] / src / src / Data / Observers / ip_observer.cpp
blob4572cc684ac35f016ad9719bc1fd1589665ee548
2 /******************************************************************************
3 * MODULE : ip_observer.cpp
4 * DESCRIPTION: Persistently attach inverse paths to trees
5 * COPYRIGHT : (C) 1999 Joris van der Hoeven
6 *******************************************************************************
7 * An inverse path observer maintains the inverse path of the position
8 * of the corresponding tree with respect to the global meta-tree.
9 *******************************************************************************
10 * This software falls under the GNU general public license version 3 or later.
11 * It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
12 * in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
13 ******************************************************************************/
15 #include "modification.hpp"
17 #define DETACHED (-5)
18 extern tree the_et;
20 /******************************************************************************
21 * Definition of the ip_observer_rep class
22 ******************************************************************************/
24 class ip_observer_rep: public observer_rep {
25 path ip;
26 public:
27 ip_observer_rep (path ip2): ip (ip2) {}
28 int get_type () { return OBSERVER_IP; }
29 tm_ostream& print (tm_ostream& out) { return out << " " << ip; }
31 void announce (tree& ref, modification mod);
32 void done (tree& ref, modification mod);
34 void notify_assign (tree& ref, tree t);
35 void notify_insert (tree& ref, int pos, int nr);
36 void notify_remove (tree& ref, int pos, int nr);
37 void notify_split (tree& ref, int pos, tree prev);
38 void notify_var_split (tree& ref, tree t1, tree t2);
39 void notify_join (tree& ref, int pos, tree next);
40 void notify_var_join (tree& ref, tree t, int offset);
41 void notify_assign_node (tree& ref, tree_label op);
42 void notify_insert_node (tree& ref, int pos);
43 void notify_remove_node (tree& ref, int pos);
44 void notify_detach (tree& ref, tree closest, bool right);
46 bool get_ip (path& ip);
47 bool set_ip (path ip);
50 /******************************************************************************
51 * Call back routines for announcements
52 ******************************************************************************/
54 bool
55 has_parent (path ip) {
56 return !is_nil (ip) && last_item (ip) != DETACHED;
59 void
60 ip_observer_rep::announce (tree& ref, modification mod) {
61 (void) ref;
62 //cout << "Announce " << ip << ", " << p << "\n";
63 if (!has_parent (ip)) return;
64 tree& parent (subtree (the_et, reverse (ip->next)));
65 parent->obs->announce (parent, ip->item * mod);
68 void
69 ip_observer_rep::done (tree& ref, modification mod) {
70 (void) ref;
71 //cout << "Done " << ip << ", " << p << "\n";
72 if (!has_parent (ip)) return;
73 tree& parent (subtree (the_et, reverse (ip->next)));
74 parent->obs->done (parent, ip->item * mod);
77 /******************************************************************************
78 * Call back routines for modifications
79 ******************************************************************************/
81 void
82 ip_observer_rep::notify_assign (tree& ref, tree t) {
83 // cout << "Notify assign " << ref << ", " << t << "\n";
84 path temp_ip= obtain_ip (ref);
85 temp_ip= path (temp_ip->item, temp_ip->next); // prevents overriding temp_ip
86 detach_ip (ref);
87 attach_ip (t, temp_ip);
90 void
91 ip_observer_rep::notify_insert (tree& ref, int pos, int nr) {
92 // cout << "Notify insert " << ref << ", " << pos << ", " << nr << "\n";
93 (void) nr;
94 if (is_compound (ref)) {
95 int i, n= N(ref);
96 for (i=pos; i<n; i++)
97 attach_ip (ref[i], path (i, ip));
101 void
102 ip_observer_rep::notify_remove (tree& ref, int pos, int nr) {
103 // cout << "Notify remove " << ref << ", " << pos << ", " << nr << "\n";
104 (void) nr;
105 if (is_compound (ref)) {
106 int i, n= N(ref);
107 for (i=pos; i<(pos+nr); i++)
108 detach_ip (ref[i]);
109 for (; i<n; i++)
110 attach_ip (ref[i], path (i-nr, ip));
114 void
115 ip_observer_rep::notify_split (tree& ref, int pos, tree prev) {
116 // cout << "Notify split " << ref << ", " << pos << ", " << prev << "\n";
117 int i, n= N(ref);
118 detach_ip (prev);
119 for (i=pos; i<n; i++)
120 attach_ip (ref[i], path (i, ip));
123 void
124 ip_observer_rep::notify_var_split (tree& ref, tree t1, tree t2) {
125 (void) ref; (void) t1; (void) t2;
128 void
129 ip_observer_rep::notify_join (tree& ref, int pos, tree next) {
130 // cout << "Notify join " << ref << ", " << pos << ", " << next << "\n";
131 int i, n= N(ref);
132 detach_ip (ref[pos]);
133 detach_ip (ref[pos+1]);
134 for (i=pos+2; i<n; i++)
135 attach_ip (ref[i], path (i-1, ip));
136 attach_ip (next, path (pos, ip));
139 void
140 ip_observer_rep::notify_var_join (tree& ref, tree t, int offset) {
141 (void) ref; (void) t; (void) offset;
144 void
145 ip_observer_rep::notify_assign_node (tree& ref, tree_label op) {
146 // cout << "Notify assign node " << ref << ", " << as_string (op) << "\n";
147 (void) ref; (void) op;
150 void
151 ip_observer_rep::notify_insert_node (tree& ref, int pos) {
152 // cout << "Notify insert node " << ref << ", " << pos << "\n";
153 ip= path (pos, ip);
154 attach_ip (ref[pos], ip); // updates children's ips
155 attach_ip (ref, ip->next);
158 void
159 ip_observer_rep::notify_remove_node (tree& ref, int pos) {
160 // cout << "Notify remove node " << ref << ", " << pos << "\n";
161 for (int i=0; i<N(ref); i++)
162 if (i != pos)
163 detach_ip (ref[i]);
164 if ((!is_nil (ip)) && (ip->item>=0)) attach_ip (ref[pos], ip);
165 else detach_ip (ref[pos]);
166 ip= DETACHED; // detach_ip (ref);
169 void
170 ip_observer_rep::notify_detach (tree& ref, tree closest, bool right) {
171 (void) ref; (void) closest; (void) right;
174 /******************************************************************************
175 * Setting and getting inverse paths
176 ******************************************************************************/
178 bool
179 ip_observer_rep::get_ip (path& ip2) {
180 ip2= ip;
181 return true;
184 bool
185 ip_observer_rep::set_ip (path ip2) {
186 if (is_nil (ip) || is_nil (ip2))
187 FAILED ("cannot alter global root");
188 ip->item= ip2->item;
189 ip->next= ip2->next;
190 return true;
193 void
194 attach_ip (tree& ref, path ip) {
195 // cout << "Set ip of " << ref << " to " << ip << "\n";
196 if (is_nil (ref->obs) || !ref->obs->set_ip (ip)) {
197 // cout << "Create ip observer " << ip << " for " << ref << "\n";
198 ref->obs= list_observer (ip_observer (ip), ref->obs);
200 if (is_compound (ref)) {
201 int i, n= N(ref);
202 for (i=0; i<n; i++) {
203 path old_ip= obtain_ip (ref[i]);
204 if ((old_ip->item != i) || (!strong_equal (old_ip->next, ip))) {
205 attach_ip (ref[i], path (i, ip));
211 void
212 detach_ip (tree& ref) {
213 // cout << "Detach ip of " << ref << "\n";
214 if (!is_nil (ref->obs))
215 (void) ref->obs->set_ip (DETACHED);
218 path
219 obtain_ip (tree& ref) {
220 path ip;
221 if (is_nil (ref->obs)) return DETACHED;
222 if (!ref->obs->get_ip (ip)) return DETACHED;
223 return ip;
226 bool
227 ip_attached (path ip) {
228 return is_nil (ip) || last_item (ip) != DETACHED;
231 /******************************************************************************
232 * Setting and getting inverse paths
233 ******************************************************************************/
235 observer
236 ip_observer (path ip) {
237 return tm_new<ip_observer_rep> (ip);