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>
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.
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.
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
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>
31 #include <gdome-util.h>
33 #include <GdomeSmartDOM.hh>
37 #define MATHML_NS_URI "http://www.w3.org/1998/Math/MathML"
39 namespace DOM = GdomeSmartDOM;
42 findElementById(const DOM::Element& el,
43 const DOM::GdomeString& ns, const DOM::GdomeString& name,
44 const DOM::GdomeString& id)
47 if (el.getAttributeNS(ns, name) == id)
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))
54 return DOM::Element();
58 getDepth(const DOM::Element& elem)
61 DOM::Element p = elem;
65 p = p.get_parentNode();
73 findCommonAncestor(const DOM::Element& first, const DOM::Element& last)
75 if (!first || !last) return DOM::Element(0);
77 DOM::Element p(first);
82 unsigned pDepth = getDepth(p);
83 unsigned qDepth = getDepth(q);
85 while (p && pDepth > qDepth)
87 p = p.get_parentNode();
91 while (q && qDepth > pDepth)
93 q = q.get_parentNode();
97 assert(pDepth == qDepth);
99 while (p && q && p != q)
101 p = p.get_parentNode();
102 q = q.get_parentNode();
110 findCommonSiblings(const DOM::Element& first, const DOM::Element& last,
111 DOM::Element& firstS, DOM::Element& lastS)
113 DOM::Element p(first);
114 DOM::Element q(last);
118 unsigned pDepth = getDepth(p);
119 unsigned qDepth = getDepth(q);
121 while (p && pDepth > qDepth)
123 p = p.get_parentNode();
127 while (q && qDepth > pDepth)
129 q = q.get_parentNode();
133 assert(pDepth == qDepth);
135 while (p && q && p.get_parentNode() != q.get_parentNode())
137 p = p.get_parentNode();
138 q = q.get_parentNode();
147 leftmostChild(const DOM::Node& node)
149 if (!node) return node;
151 DOM::Node firstChild = node.get_firstChild();
152 if (!firstChild) return node;
154 return leftmostChild(firstChild);
158 rightmostChild(const DOM::Node& node)
160 if (!node) return node;
162 DOM::Node lastChild = node.get_lastChild();
163 if (!lastChild) return node;
165 return rightmostChild(lastChild);
169 leftSibling(const DOM::Node& node)
175 while (p.get_parentNode() && p.get_parentNode().get_firstChild() == p)
176 p = p.get_parentNode();
178 if (!p.get_parentNode()) return DOM::Node(0);
180 DOM::Node prevSibling = p.get_previousSibling();
183 return rightmostChild(prevSibling);
187 rightSibling(const DOM::Node& node)
193 DOM::Node firstChild = p.get_firstChild();
194 if (firstChild) return firstChild;
196 while (p.get_parentNode() && p.get_parentNode().get_lastChild() == p)
197 p = p.get_parentNode();
199 if (!p.get_parentNode()) return DOM::Node(0);
201 DOM::Node nextSibling = p.get_nextSibling();
204 return leftmostChild(nextSibling);
207 extern "C" GdomeElement*
208 find_common_ancestor(GdomeElement* first, GdomeElement* last)
210 DOM::Element p(first);
211 DOM::Element q(last);
212 return gdome_cast_el(findCommonAncestor(p, q).gdome_object());
215 extern "C" GdomeElement*
216 find_self_or_ancestor(GdomeElement* elem, const gchar* uri, const gchar* name)
218 DOM::Element el(elem);
220 while (el && (el.get_namespaceURI() != uri || el.get_localName() != name))
221 el = el.get_parentNode();
223 return gdome_cast_el(el.gdome_object());
227 action_toggle(GdomeElement* elem)
229 DOM::Element el(elem);
230 if (el.get_namespaceURI() != MATHML_NS_URI || el.get_localName() != "maction") return;
233 if (el.hasAttribute("selection"))
234 idx = atoi(std::string(el.getAttribute("selection")).c_str());
239 std::ostringstream os;
241 el.setAttribute("selection", os.str());
245 find_common_siblings(GdomeElement* first, GdomeElement* last,
246 GdomeElement** firstS, GdomeElement** lastS)
251 findCommonSiblings(DOM::Element(first), DOM::Element(last), fs, ls);
253 if (firstS != NULL) *firstS = gdome_cast_el(fs.gdome_object());
254 if (lastS != NULL) *lastS = gdome_cast_el(ls.gdome_object());
258 findElementWithAttribute(const DOM::Element& elem, const std::string& name)
260 DOM::Element el(elem);
261 while (el && !el.hasAttribute(name)) el = el.get_parentNode();
266 findElementWithAttributeNS(const DOM::Element& elem, const std::string& ns_uri, const std::string& name)
268 DOM::Element el(elem);
269 while (el && !el.hasAttributeNS(ns_uri, name)) el = el.get_parentNode();
273 extern "C" GdomeElement*
274 find_element_with_id(GdomeElement* elem, GdomeDOMString* ns_uri, GdomeDOMString* name)
276 assert(name != NULL);
279 el = findElementWithAttributeNS(DOM::Element(elem), DOM::GdomeString(ns_uri), DOM::GdomeString(name));
281 el = findElementWithAttribute(DOM::Element(elem), DOM::GdomeString(name));
282 return gdome_cast_el(el.gdome_object());
285 extern "C" GdomeDOMString*
286 find_hyperlink(GdomeElement* elem)
288 DOM::Element el = findElementWithAttribute(DOM::Element(elem),"href");
289 if (el) return el.getAttribute("href").gdome_str();
293 extern "C" GdomeElement*
294 find_element_by_id(GdomeElement* root, GdomeDOMString* ns_uri, GdomeDOMString* name,
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());