]> matita.cs.unibo.it Git - helm.git/blob - helm/gtkmathview-bonobo/src/aux.cc
select and click signal added
[helm.git] / helm / gtkmathview-bonobo / src / aux.cc
1 // Copyright (C) 2000-2002, Luca Padovani <luca.padovani@cs.unibo.it>.
2 //
3 // This file is part of GtkMathView, a Gtk widget for MathML.
4 // 
5 // GtkMathView is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License
7 // as published by the Free Software Foundation; either version 2
8 // of the License, or (at your option) any later version.
9 //
10 // GtkMathView is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with GtkMathView; if not, write to the Free Software
17 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18 // 
19 // For details, see the GtkMathView World-Wide-Web page,
20 // http://www.cs.unibo.it/helm/mml-widget, or send a mail to
21 // <luca.padovani@cs.unibo.it>
22
23 #include <config.h>
24 #include <assert.h>
25
26 #include <sstream>
27
28 #include <gdome.h>
29 #include <gdome-util.h>
30
31 #include <GdomeSmartDOM.hh>
32
33 #define MATHML_NS_URI "http://www.w3.org/1998/Math/MathML"
34
35 namespace DOM = GdomeSmartDOM;
36
37 static unsigned
38 getDepth(const DOM::Element& elem)
39 {
40   unsigned length = 0;
41   DOM::Element p = elem;
42
43   while (p)
44     {
45       p = p.get_parentNode();
46       length++;
47     }
48
49   return length;
50 }
51
52 static DOM::Element
53 findCommonAncestor(const DOM::Element& first, const DOM::Element& last)
54 {
55   if (!first || !last) return DOM::Element(0);
56
57   DOM::Element p(first);
58   DOM::Element q(last);
59
60   if (p != q)
61     {
62       unsigned pDepth = getDepth(p);
63       unsigned qDepth  = getDepth(q);
64
65       while (p && pDepth > qDepth)
66         {
67           p = p.get_parentNode();
68           pDepth--;
69         }
70
71       while (q && qDepth > pDepth)
72         {
73           q = q.get_parentNode();
74           qDepth--;
75         }
76
77       assert(pDepth == qDepth);
78
79       while (p && q && p != q)
80         {
81           p = p.get_parentNode();
82           q = q.get_parentNode();
83         }
84     }
85   
86   return p;
87 }
88
89 static void
90 findCommonSiblings(const DOM::Element& first, const DOM::Element& last,
91                    DOM::Element& firstS, DOM::Element& lastS)
92 {
93   DOM::Element p(first);
94   DOM::Element q(last);
95
96   if (p != q)
97     {
98       unsigned pDepth = getDepth(p);
99       unsigned qDepth  = getDepth(q);
100
101       while (p && pDepth > qDepth)
102         {
103           p = p.get_parentNode();
104           pDepth--;
105         }
106
107       while (q && qDepth > pDepth)
108         {
109           q = q.get_parentNode();
110           qDepth--;
111         }
112
113       assert(pDepth == qDepth);
114
115       while (p && q && p.get_parentNode() != q.get_parentNode())
116         {
117           p = p.get_parentNode();
118           q = q.get_parentNode();
119         }
120     }
121
122   firstS = p;
123   lastS = q;
124 }
125
126 static DOM::Node
127 leftmostChild(const DOM::Node& node)
128 {
129   if (!node) return node;
130
131   DOM::Node firstChild = node.get_firstChild();
132   if (!firstChild) return node;
133
134   return leftmostChild(firstChild);
135 }
136
137 static DOM::Node
138 rightmostChild(const DOM::Node& node)
139 {
140   if (!node) return node;
141
142   DOM::Node lastChild = node.get_lastChild();
143   if (!lastChild) return node;
144
145   return rightmostChild(lastChild);
146 }
147
148 static DOM::Node
149 leftSibling(const DOM::Node& node)
150 {
151   DOM::Node p = node;
152
153   if (!p) return p;
154
155   while (p.get_parentNode() && p.get_parentNode().get_firstChild() == p)
156     p = p.get_parentNode();
157
158   if (!p.get_parentNode()) return DOM::Node(0);
159
160   DOM::Node prevSibling = p.get_previousSibling();
161   assert(prevSibling);
162
163   return rightmostChild(prevSibling);
164 }
165
166 static DOM::Node
167 rightSibling(const DOM::Node& node)
168 {
169   DOM::Node p = node;
170
171   if (!p) return p;
172
173   DOM::Node firstChild = p.get_firstChild();
174   if (firstChild) return firstChild;
175
176   while (p.get_parentNode() && p.get_parentNode().get_lastChild() == p)
177     p = p.get_parentNode();
178
179   if (!p.get_parentNode()) return DOM::Node(0);
180
181   DOM::Node nextSibling = p.get_nextSibling();
182   assert(nextSibling);
183
184   return leftmostChild(nextSibling);
185 }
186
187 extern "C" GdomeElement*
188 find_common_ancestor(GdomeElement* first, GdomeElement* last)
189 {
190   DOM::Element p(first);
191   DOM::Element q(last);
192   return gdome_cast_el(findCommonAncestor(p, q).gdome_object());
193 }
194
195 extern "C" GdomeElement*
196 find_self_or_ancestor(GdomeElement* elem, const char* uri, const char* name)
197 {
198   DOM::Element el(elem);
199
200   while (el && (el.get_namespaceURI() != uri || el.get_localName() != name))
201     el = el.get_parentNode();
202
203   return gdome_cast_el(el.gdome_object());
204 }
205
206 extern "C" void
207 action_toggle(GdomeElement* elem)
208 {
209   DOM::Element el(elem);
210   if (el.get_namespaceURI() != MATHML_NS_URI || el.get_localName() != "maction") return;
211
212   guint idx;
213   if (el.hasAttribute("selection"))
214     idx = atoi(std::string(el.getAttribute("selection")).c_str());
215   else idx = 1;
216
217   idx++;
218
219   std::ostringstream os;
220   os << idx;
221   el.setAttribute("selection", os.str());
222 }
223
224 extern "C" void
225 find_common_siblings(GdomeElement* first, GdomeElement* last,
226                      GdomeElement** firstS, GdomeElement** lastS)
227 {
228   DOM::Element fs(0);
229   DOM::Element ls(0);
230
231   findCommonSiblings(DOM::Element(first), DOM::Element(last), fs, ls);
232
233   if (firstS != NULL) *firstS = gdome_cast_el(fs.gdome_object());
234   if (lastS != NULL) *lastS = gdome_cast_el(ls.gdome_object());
235 }
236
237 static DOM::Element
238 findElementWithAttribute(const DOM::Element& elem, const std::string& name)
239 {
240   DOM::Element el(elem);
241   while (el && !el.hasAttribute(name)) el = el.get_parentNode();
242   return el;
243 }
244
245 static DOM::Element
246 findElementWithAttributeNS(const DOM::Element& elem, const std::string& ns_uri, const std::string& name)
247 {
248   DOM::Element el(elem);
249   while (el && !el.hasAttributeNS(ns_uri, name)) el = el.get_parentNode();
250   return el;
251 }
252
253 extern "C" GdomeElement*
254 find_xref_element(GdomeElement* elem)
255 {
256   DOM::Element el = findElementWithAttribute(DOM::Element(elem), "xref");
257   return gdome_cast_el(el.gdome_object());
258 }
259
260 extern "C" GdomeDOMString*
261 find_hyperlink(GdomeElement* elem)
262 {
263       DOM::Element el = findElementWithAttribute(DOM::Element(elem),"href");
264       if (el) return el.getAttribute("href").gdome_str();
265       else return NULL;
266 }
267
268
269 extern "C" void
270 delete_element(GdomeElement* elem)
271 {
272   DOM::Element p(elem);
273
274   DOM::Element parent = p.get_parentNode();
275   assert(parent);
276
277   parent.removeChild(p);
278 }
279