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