Systematic use of tm_ostream class instead of ostream (removing dependency on std)
[texmacs.git] / src / src / Data / Observers / tree_position.cpp
blobd8b07fc1bc80d1f7e391c20c6e9e1b1ebbc67640
2 /******************************************************************************
3 * MODULE : tree_position.cpp
4 * DESCRIPTION: Persistently attach cursor positions to trees
5 * COPYRIGHT : (C) 2005 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 "tree.hpp"
16 #include "path.hpp"
18 #define DETACHED (-5)
20 /******************************************************************************
21 * Definition of the tree_position_rep class
22 ******************************************************************************/
24 class tree_position_rep: public observer_rep {
25 tree_rep* ptr;
26 int index;
28 public:
29 tree_position_rep (tree ref, int index2): ptr (ref.rep), index (index2) {}
30 int get_type () { return OBSERVER_POSITION; }
31 tm_ostream& print (tm_ostream& out) { return out << " " << index; }
33 void notify_assign (tree& ref, tree t);
34 void notify_insert (tree& ref, int pos, int nr);
35 void notify_remove (tree& ref, int pos, int nr);
36 void notify_split (tree& ref, int pos, tree prev);
37 void notify_var_split (tree& ref, tree t1, tree t2);
38 void notify_join (tree& ref, int pos, tree next);
39 void notify_var_join (tree& ref, tree t, int offset);
40 void notify_assign_node (tree& ref, tree_label op);
41 void notify_insert_node (tree& ref, int pos);
42 void notify_remove_node (tree& ref, int pos);
43 void notify_detach (tree& ref, tree closest, bool right);
45 bool get_position (tree& t, int& index);
46 bool set_position (tree t, int index);
49 /******************************************************************************
50 * Re-attaching the position to another tree
51 ******************************************************************************/
53 bool
54 tree_position_rep::get_position (tree& t, int& index2) {
55 t = tree (ptr);
56 index2= index;
57 return true;
60 bool
61 tree_position_rep::set_position (tree t, int index2) {
62 tree ref (ptr);
63 detach_observer (ref, observer (this));
64 ptr = t.rep;
65 index= index2;
66 attach_observer (t, observer (this));
67 return true;
70 void
71 reattach_at (tree_position_rep* rep, tree t, int index) {
72 rep->set_position (t, index);
75 void reattach_left (tree_position_rep* rep, tree t) {
76 reattach_at (rep, t, 0); }
77 void reattach_right (tree_position_rep* rep, tree t) {
78 reattach_at (rep, t, right_index (t)); }
80 /******************************************************************************
81 * Call back routines for modifications
82 ******************************************************************************/
84 void
85 tree_position_rep::notify_assign (tree& ref, tree t) {
86 // cout << "Notify assign " << ref << ", " << t << "\n";
87 bool left=
88 (is_atomic (ref) && (index <= (N(ref->label) >> 1))) || (index == 0);
89 if (left) reattach_left (this, t);
90 else reattach_right (this, t);
91 // cout << "position -> " << obtain_position (observer (this)) << "\n";
94 void
95 tree_position_rep::notify_insert (tree& ref, int pos, int nr) {
96 // cout << "Notify insert " << ref << ", " << pos << ", " << nr << "\n";
97 if (is_atomic (ref) && index >= pos)
98 index += nr;
99 // cout << "position -> " << obtain_position (observer (this)) << "\n";
102 void
103 tree_position_rep::notify_remove (tree& ref, int pos, int nr) {
104 // cout << "Notify remove " << ref << ", " << pos << ", " << nr << "\n";
105 if (is_atomic (ref)) {
106 if (index >= pos)
107 index= max (pos, index - nr);
109 // cout << "position -> " << obtain_position (observer (this)) << "\n";
112 void
113 tree_position_rep::notify_split (tree& ref, int pos, tree prev) {
114 (void) ref; (void) pos; (void) prev;
117 void
118 tree_position_rep::notify_var_split (tree& ref, tree t1, tree t2) {
119 // cout << "Notify var split " << ref << ", " << t1 << ", " << t2 << "\n";
120 if (is_atomic (ref)) {
121 if (index <= N(t1->label)) reattach_at (this, t1, index);
122 else reattach_at (this, t2, index - N(t1->label));
124 else {
125 if (index == 0) reattach_left (this, t1);
126 else reattach_right (this, t2);
128 // cout << "position -> " << obtain_position (observer (this)) << "\n";
131 void
132 tree_position_rep::notify_join (tree& ref, int pos, tree next) {
133 (void) ref; (void) pos; (void) next;
136 void
137 tree_position_rep::notify_var_join (tree& ref, tree t, int offset) {
138 // cout << "Notify var join " << ref << ", " << t << ", " << offset << "\n";
139 if (is_atomic (ref))
140 reattach_at (this, t, index + offset);
141 else {
142 if (index == 0) reattach_right (this, t[offset-1]);
143 else reattach_right (this, t);
145 // cout << "position -> " << obtain_position (observer (this)) << "\n";
148 void
149 tree_position_rep::notify_assign_node (tree& ref, tree_label op) {
150 // cout << "Notify assign node " << ref << ", " << as_string (op) << "\n";
151 (void) ref; (void) op;
152 // cout << "position -> " << obtain_position (observer (this)) << "\n";
155 void
156 tree_position_rep::notify_insert_node (tree& ref, int pos) {
157 // cout << "Notify insert node " << ref << ", " << pos << "\n";
158 (void) ref; (void) pos;
159 // cout << "position -> " << obtain_position (observer (this)) << "\n";
162 void
163 tree_position_rep::notify_remove_node (tree& ref, int pos) {
164 // cout << "Notify remove node " << ref << ", " << pos << "\n";
165 if (index == 0) reattach_left (this, ref[pos]);
166 else reattach_right (this, ref[pos]);
167 // cout << "position -> " << obtain_position (observer (this)) << "\n";
170 void
171 tree_position_rep::notify_detach (tree& ref, tree closest, bool right) {
172 // cout << "Notify detach " << ref << ", " << closest <<", "<< right << "\n";
173 if (right) reattach_right (this, closest);
174 else reattach_left (this, closest);
175 // cout << "position -> " << obtain_position (observer (this)) << "\n";
178 /******************************************************************************
179 * Public interface
180 ******************************************************************************/
182 observer
183 tree_position (tree ref, int index) {
184 return tm_new<tree_position_rep> (ref, index);
187 path
188 obtain_position (observer o) {
189 tree t;
190 int index;
191 if (!o->get_position (t, index)) return path ();
192 path ip= obtain_ip (t);
193 if (ip == path (DETACHED)) return path ();
194 return reverse (ip) * index;