]> matita.cs.unibo.it Git - helm.git/blob - helm/DEVEL/mathml_editor/src/TDocument.cc
ocaml 3.09 transition
[helm.git] / helm / DEVEL / mathml_editor / src / TDocument.cc
1 /* This file is part of EdiTeX, an editor of mathematical
2  * expressions based on TeX syntax.
3  * 
4  * Copyright (C) 2002-2003 Luca Padovani <lpadovan@cs.unibo.it>,
5  *                    2003 Paolo Marinelli <pmarinel@cs.unibo.it>.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  *
21  * For more information, please visit the project's home page
22  * http://helm.cs.unibo.it/editex/
23  * or send an email to <lpadovan@cs.unibo.it>
24  */
25
26 #include <sstream>
27 #include <cassert>
28
29 #include "globals.hh"
30 #include "dom.hh"
31 #include "TDocument.hh"
32
33 TDocument::TDocument()
34 {
35   DOM::DOMImplementation di;
36   DOM::DocumentType dt;
37   doc = di.createDocument(TML_NS_URI, "tml:tex", dt);
38   DOM::Element root = doc.get_documentElement();
39   assert(root);
40   root.setAttributeNS(XMLNS_NS_URI, "xmlns:tml", TML_NS_URI);
41
42   DOM::EventTarget et(doc);
43   assert(et);
44   et.addEventListener("DOMSubtreeModified", *this, false);
45 }
46
47 TDocument::~TDocument()
48 {
49   //DOM::Element root = doc.get_documentElement();
50   DOM::EventTarget et(doc);
51   assert(doc);
52   et.removeEventListener("DOMSubtreeModified", *this, false);
53 }
54
55 void
56 TDocument::reset()
57 {
58   DOM::Element root = doc.createElementNS(TML_NS_URI, "tml:tex");
59   root.setAttributeNS(XMLNS_NS_URI, "xmlns:tml", TML_NS_URI);
60   doc.replaceChild(root, doc.get_documentElement());
61   clearDirty();
62 }
63
64 void
65 TDocument::serialize(const char* filename) const
66 {
67   DOM::DOMImplementation di;
68   di.saveDocumentToFile(doc, filename, GDOME_SAVE_LIBXML_INDENT);
69 }
70
71 std::string
72 TDocument::makeId(unsigned id)
73 {
74   std::ostringstream os;
75   os << "I" << id;
76   return os.str();
77 }
78
79 TNode
80 TDocument::create(const std::string& name, unsigned id) const
81 {
82   DOM::Element elem = doc.createElementNS(TML_NS_URI, "tml:" + name);
83   if (id > 0) elem.setAttribute("id", makeId(id));
84   return elem;
85 }
86
87 TNode
88 TDocument::createC(const std::string& name, unsigned id) const
89 {
90   TNode m = create("c", id);
91   m["name"] = name;
92   return m;
93 }
94
95 TNode
96 TDocument::createT(const std::string& name, const std::string& text, unsigned id) const
97 {
98   TNode t = create(name, id);
99   t["val"] = text;
100   return t;
101 }
102
103 unsigned
104 TDocument::nodeDepth(const DOM::Node& node)
105 {
106   DOM::Node n = node;
107
108   unsigned depth = 0;
109   while (n)
110     {
111       depth++;
112       n = n.get_parentNode();
113     }
114   return depth;
115 }
116
117 DOM::Node
118 TDocument::findCommonAncestor(const DOM::Node& node1, const DOM::Node& node2)
119 {
120   DOM::Node n1 = node1;
121   DOM::Node n2 = node2;
122
123   unsigned d1 = nodeDepth(n1);
124   unsigned d2 = nodeDepth(n2);
125
126   // cout << "finding common ancestor " << d1 << " " << d2 << endl;
127
128   while (d1 < d2)
129     {
130       assert(n2);
131       n2 = n2.get_parentNode();
132       d2--;
133     }
134
135   while (d1 > d2)
136     {
137       assert(n1);
138       n1 = n1.get_parentNode();
139       d1--;
140     }
141
142   while (n1 != n2)
143     {
144       assert(n1);
145       assert(n2);
146       n1 = n1.get_parentNode();
147       n2 = n2.get_parentNode();
148     }
149
150   return n1;
151 }
152
153 DOM::Node
154 TDocument::findIdNode(const DOM::Node& node)
155 {
156   DOM::Node n = node;
157   while (n)
158     {
159       if (n.get_nodeType() == DOM::Node::ELEMENT_NODE)
160         {
161           DOM::Element el = n;
162           if (el.hasAttribute("id")) return el;
163         }
164       n = n.get_parentNode();
165     }
166
167   return DOM::Node(0);
168 }
169
170 TNode
171 TDocument::getNodeByIdAux(const TNode& node, const std::string& id)
172 {
173   if (node.hasId(id)) return node;
174   else
175     for (TNode p = node.first(); p; p = p.next())
176       if (TNode res = getNodeByIdAux(p, id)) return res;
177   return TNode();
178 }
179
180 TNode
181 TDocument::getNodeById(unsigned id) const
182 {
183   DOM::Element root = doc.get_documentElement();
184   assert(root);
185   return getNodeByIdAux(root, makeId(id));
186 }
187
188 void
189 TDocument::handleEvent(const DOM::Event& ev)
190 {
191   DOM::MutationEvent me(ev);
192   assert(me);
193
194 #if 0
195   if (dirty)
196     cout << "TDocument::handleEvent DIRTY BEFORE = " << dirty.getAttribute("id") << endl;
197   else
198     cout << "TDocument::handleEvent DIRTY BEFORE = (nil)" << endl;
199 #endif
200
201   if (DOM::Node node = me.get_target())
202     if (dirty)
203       dirty = findIdNode(findCommonAncestor(dirty, node));
204     else
205       dirty = findIdNode(node);
206   else
207     assert(0);
208
209 #if 0
210   cout << "TDocument::handleEvent target = " << DOM::Node(me.get_target()).get_nodeName() << " DIRTY AFTER = "
211        << dirty.getAttribute("id") << " ME = " << DOM::Node(me.get_target()).get_nodeName() << endl;
212 #endif
213 }