]> matita.cs.unibo.it Git - helm.git/blob - helm/DEVEL/mathml_editor/src/TDocument.cc
C++ 3.2 aware changes
[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
28 #include "globals.hh"
29 #include "dom.hh"
30 #include "TDocument.hh"
31
32 TDocument::TDocument()
33 {
34   DOM::DOMImplementation di;
35   DOM::DocumentType dt;
36   doc = di.createDocument(TML_NS_URI, "tml:tex", dt);
37   DOM::Element root = doc.get_documentElement();
38   assert(root);
39   root.setAttributeNS(XMLNS_NS_URI, "xmlns:tml", TML_NS_URI);
40
41   DOM::EventTarget et(doc);
42   assert(et);
43   et.addEventListener("DOMSubtreeModified", *this, false);
44 }
45
46 TDocument::~TDocument()
47 {
48   //DOM::Element root = doc.get_documentElement();
49   DOM::EventTarget et(doc);
50   assert(doc);
51   et.removeEventListener("DOMSubtreeModified", *this, false);
52 }
53
54 void
55 TDocument::reset()
56 {
57   DOM::Element root = doc.createElementNS(TML_NS_URI, "tml:tex");
58   root.setAttributeNS(XMLNS_NS_URI, "xmlns:tml", TML_NS_URI);
59   doc.replaceChild(root, doc.get_documentElement());
60   clearDirty();
61 }
62
63 void
64 TDocument::serialize(const char* filename) const
65 {
66   DOM::DOMImplementation di;
67   di.saveDocumentToFile(doc, filename, GDOME_SAVE_LIBXML_INDENT);
68 }
69
70 std::string
71 TDocument::makeId(unsigned id)
72 {
73   std::ostringstream os;
74   os << "I" << id;
75   return os.str();
76 }
77
78 TNode
79 TDocument::create(const std::string& name, unsigned id) const
80 {
81   DOM::Element elem = doc.createElementNS(TML_NS_URI, "tml:" + name);
82   if (id > 0) elem.setAttribute("id", makeId(id));
83   return elem;
84 }
85
86 TNode
87 TDocument::createC(const std::string& name, unsigned id) const
88 {
89   TNode m = create("c", id);
90   m["name"] = name;
91   return m;
92 }
93
94 TNode
95 TDocument::createT(const std::string& name, const std::string& text, unsigned id) const
96 {
97   TNode t = create(name, id);
98   t["val"] = text;
99   return t;
100 }
101
102 unsigned
103 TDocument::nodeDepth(const DOM::Node& node)
104 {
105   DOM::Node n = node;
106
107   unsigned depth = 0;
108   while (n)
109     {
110       depth++;
111       n = n.get_parentNode();
112     }
113   return depth;
114 }
115
116 DOM::Node
117 TDocument::findCommonAncestor(const DOM::Node& node1, const DOM::Node& node2)
118 {
119   DOM::Node n1 = node1;
120   DOM::Node n2 = node2;
121
122   unsigned d1 = nodeDepth(n1);
123   unsigned d2 = nodeDepth(n2);
124
125   // cout << "finding common ancestor " << d1 << " " << d2 << endl;
126
127   while (d1 < d2)
128     {
129       assert(n2);
130       n2 = n2.get_parentNode();
131       d2--;
132     }
133
134   while (d1 > d2)
135     {
136       assert(n1);
137       n1 = n1.get_parentNode();
138       d1--;
139     }
140
141   while (n1 != n2)
142     {
143       assert(n1);
144       assert(n2);
145       n1 = n1.get_parentNode();
146       n2 = n2.get_parentNode();
147     }
148
149   return n1;
150 }
151
152 DOM::Node
153 TDocument::findIdNode(const DOM::Node& node)
154 {
155   DOM::Node n = node;
156   while (n)
157     {
158       if (n.get_nodeType() == DOM::Node::ELEMENT_NODE)
159         {
160           DOM::Element el = n;
161           if (el.hasAttribute("id")) return el;
162         }
163       n = n.get_parentNode();
164     }
165
166   return DOM::Node(0);
167 }
168
169 TNode
170 TDocument::getNodeByIdAux(const TNode& node, const std::string& id)
171 {
172   if (node.hasId(id)) return node;
173   else
174     for (TNode p = node.first(); p; p = p.next())
175       if (TNode res = getNodeByIdAux(p, id)) return res;
176   return TNode();
177 }
178
179 TNode
180 TDocument::getNodeById(unsigned id) const
181 {
182   DOM::Element root = doc.get_documentElement();
183   assert(root);
184   return getNodeByIdAux(root, makeId(id));
185 }
186
187 void
188 TDocument::handleEvent(const DOM::Event& ev)
189 {
190   DOM::MutationEvent me(ev);
191   assert(me);
192
193 #if 0
194   if (dirty)
195     cout << "TDocument::handleEvent DIRTY BEFORE = " << dirty.getAttribute("id") << endl;
196   else
197     cout << "TDocument::handleEvent DIRTY BEFORE = (nil)" << endl;
198 #endif
199
200   if (DOM::Node node = me.get_target())
201     if (dirty)
202       dirty = findIdNode(findCommonAncestor(dirty, node));
203     else
204       dirty = findIdNode(node);
205   else
206     assert(0);
207
208 #if 0
209   cout << "TDocument::handleEvent target = " << DOM::Node(me.get_target()).get_nodeName() << " DIRTY AFTER = "
210        << dirty.getAttribute("id") << " ME = " << DOM::Node(me.get_target()).get_nodeName() << endl;
211 #endif
212 }