1 // Copyright (C) 2000-2002, Luca Padovani <luca.padovani@cs.unibo.it>.
3 // This file is part of GtkMathView, a Gtk widget for MathML.
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.
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.
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.
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>
30 #include <gdome-util.h>
32 #include <GdomeSmartDOM.hh>
36 #define MATHML_NS_URI "http://www.w3.org/1998/Math/MathML"
38 namespace DOM = GdomeSmartDOM;
41 findElementById(const DOM::Element& el,
42 const DOM::GdomeString& ns, const DOM::GdomeString& name,
43 const DOM::GdomeString& id)
46 if (el.getAttributeNS(ns, name) == id)
49 for (DOM::Node p = el.get_firstChild(); p; p = p.get_nextSibling())
50 if (p.get_nodeType() == DOM::Node::ELEMENT_NODE)
51 if (DOM::Element res = findElementById(p, ns, name, id))
53 return DOM::Element();
57 getDepth(const DOM::Element& elem)
60 DOM::Element p = elem;
64 p = p.get_parentNode();
72 findCommonAncestor(const DOM::Element& first, const DOM::Element& last)
74 if (!first || !last) return DOM::Element(0);
76 DOM::Element p(first);
81 unsigned pDepth = getDepth(p);
82 unsigned qDepth = getDepth(q);
84 while (p && pDepth > qDepth)
86 p = p.get_parentNode();
90 while (q && qDepth > pDepth)
92 q = q.get_parentNode();
96 assert(pDepth == qDepth);
98 while (p && q && p != q)
100 p = p.get_parentNode();
101 q = q.get_parentNode();
109 findCommonSiblings(const DOM::Element& first, const DOM::Element& last,
110 DOM::Element& firstS, DOM::Element& lastS)
112 DOM::Element p(first);
113 DOM::Element q(last);
117 unsigned pDepth = getDepth(p);
118 unsigned qDepth = getDepth(q);
120 while (p && pDepth > qDepth)
122 p = p.get_parentNode();
126 while (q && qDepth > pDepth)
128 q = q.get_parentNode();
132 assert(pDepth == qDepth);
134 while (p && q && p.get_parentNode() != q.get_parentNode())
136 p = p.get_parentNode();
137 q = q.get_parentNode();
146 leftmostChild(const DOM::Node& node)
148 if (!node) return node;
150 DOM::Node firstChild = node.get_firstChild();
151 if (!firstChild) return node;
153 return leftmostChild(firstChild);
157 rightmostChild(const DOM::Node& node)
159 if (!node) return node;
161 DOM::Node lastChild = node.get_lastChild();
162 if (!lastChild) return node;
164 return rightmostChild(lastChild);
168 leftSibling(const DOM::Node& node)
174 while (p.get_parentNode() && p.get_parentNode().get_firstChild() == p)
175 p = p.get_parentNode();
177 if (!p.get_parentNode()) return DOM::Node(0);
179 DOM::Node prevSibling = p.get_previousSibling();
182 return rightmostChild(prevSibling);
186 rightSibling(const DOM::Node& node)
192 DOM::Node firstChild = p.get_firstChild();
193 if (firstChild) return firstChild;
195 while (p.get_parentNode() && p.get_parentNode().get_lastChild() == p)
196 p = p.get_parentNode();
198 if (!p.get_parentNode()) return DOM::Node(0);
200 DOM::Node nextSibling = p.get_nextSibling();
203 return leftmostChild(nextSibling);
206 extern "C" GdomeElement*
207 find_common_ancestor(GdomeElement* first, GdomeElement* last)
209 DOM::Element p(first);
210 DOM::Element q(last);
211 return gdome_cast_el(findCommonAncestor(p, q).gdome_object());
214 extern "C" GdomeElement*
215 find_self_or_ancestor(GdomeElement* elem, const char* uri, const char* name)
217 DOM::Element el(elem);
219 while (el && (el.get_namespaceURI() != uri || el.get_localName() != name))
220 el = el.get_parentNode();
222 return gdome_cast_el(el.gdome_object());
226 action_toggle(GdomeElement* elem)
228 DOM::Element el(elem);
229 if (el.get_namespaceURI() != MATHML_NS_URI || el.get_localName() != "maction") return;
232 if (el.hasAttribute("selection"))
233 idx = atoi(std::string(el.getAttribute("selection")).c_str());
238 std::ostringstream os;
240 el.setAttribute("selection", os.str());
244 find_common_siblings(GdomeElement* first, GdomeElement* last,
245 GdomeElement** firstS, GdomeElement** lastS)
250 findCommonSiblings(DOM::Element(first), DOM::Element(last), fs, ls);
252 if (firstS != NULL) *firstS = gdome_cast_el(fs.gdome_object());
253 if (lastS != NULL) *lastS = gdome_cast_el(ls.gdome_object());
257 findElementWithAttribute(const DOM::Element& elem, const std::string& name)
259 DOM::Element el(elem);
260 while (el && !el.hasAttribute(name)) el = el.get_parentNode();
265 findElementWithAttributeNS(const DOM::Element& elem, const std::string& ns_uri, const std::string& name)
267 DOM::Element el(elem);
268 while (el && !el.hasAttributeNS(ns_uri, name)) el = el.get_parentNode();
272 extern "C" GdomeElement*
273 find_xref_element(GdomeElement* elem)
275 DOM::Element el = findElementWithAttribute(DOM::Element(elem), "xref");
276 return gdome_cast_el(el.gdome_object());
279 extern "C" GdomeDOMString*
280 find_hyperlink(GdomeElement* elem)
282 DOM::Element el = findElementWithAttribute(DOM::Element(elem),"href");
283 if (el) return el.getAttribute("href").gdome_str();
287 extern "C" GdomeElement*
288 find_element_by_id(GdomeElement* root, GdomeDOMString* ns_uri, GdomeDOMString* name,
291 DOM::Element el = findElementById(DOM::Element(root),
292 DOM::GdomeString(ns_uri), DOM::GdomeString(name),
293 DOM::GdomeString(id));
294 return gdome_cast_el(el.gdome_object());