]> git.lyx.org Git - lyx.git/blob - src/mathed/MacroTable.cpp
b2e50d119168f0d3698199faa22f68428779c6d4
[lyx.git] / src / mathed / MacroTable.cpp
1 /**
2  * \file MacroTable.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author André Pönitz
7  *
8  * Full author contact details are available in file CREDITS.
9  */
10
11 #include <config.h>
12
13 #include "InsetMathSqrt.h"
14 #include "MacroTable.h"
15 #include "MathMacroTemplate.h"
16 #include "MathMacroArgument.h"
17 #include "MathStream.h"
18 #include "MathSupport.h"
19 #include "InsetMathNest.h"
20
21 #include "Buffer.h"
22 #include "BufferList.h"
23 #include "DocIterator.h"
24 #include "InsetList.h"
25 #include "Text.h"
26
27 #include "support/debug.h"
28 #include "support/FileName.h"
29 #include "support/lassert.h"
30
31 #include <sstream>
32
33 using namespace std;
34 using namespace lyx::support;
35
36 namespace lyx {
37
38
39 /////////////////////////////////////////////////////////////////////
40 //
41 // MacroData
42 //
43 /////////////////////////////////////////////////////////////////////
44
45 MacroData::MacroData()
46         : queried_(true), numargs_(0), optionals_(0), lockCount_(0),
47           redefinition_(false), type_(MacroTypeNewcommand)
48 {}
49
50         
51         
52 MacroData::MacroData(Buffer const & buf, DocIterator const & pos)
53         : buffer_(&buf), pos_(pos), queried_(false), numargs_(0),
54           optionals_(0), lockCount_(0), redefinition_(false),
55           type_(MacroTypeNewcommand)
56 {
57 }
58         
59         
60 MacroData::MacroData(MathMacroTemplate const & macro)
61         : queried_(false), numargs_(0), optionals_(0), lockCount_(0),
62           redefinition_(false), type_(MacroTypeNewcommand)
63 {
64         queryData(macro);
65 }
66
67
68 void MacroData::expand(vector<MathData> const & args, MathData & to) const
69 {
70         updateData();
71
72         // Hack. Any inset with a cell would do.
73         static Buffer * buffer = 0;
74         if (!buffer) {
75                 buffer = theBufferList().newBuffer(
76                 FileName::tempName().absFilename() + "_macrodata.internal");
77                 buffer->setUnnamed(true);
78         }
79         static InsetMathSqrt inset;
80
81         // FIXME UNICODE
82         asArray(display_.empty() ? definition_ : display_, inset.cell(0));
83         //lyxerr << "MathData::expand: args: " << args << endl;
84         //lyxerr << "MathData::expand: ar: " << inset.cell(0) << endl;
85         for (DocIterator it = doc_iterator_begin(buffer, &inset); it; it.forwardChar()) {
86                 if (!it.nextInset())
87                         continue;
88                 if (it.nextInset()->lyxCode() != MATHMACROARG_CODE)
89                         continue;
90                 //it.cell().erase(it.pos());
91                 //it.cell().insert(it.pos(), it.nextInset()->asInsetMath()
92                 size_t n = static_cast<MathMacroArgument*>(it.nextInset())->number();
93                 if (n <= args.size()) {
94                         it.cell().erase(it.pos());
95                         it.cell().insert(it.pos(), args[n - 1]);
96                 }
97         }
98         //lyxerr << "MathData::expand: res: " << inset.cell(0) << endl;
99         to = inset.cell(0);
100 }
101
102
103 size_t MacroData::optionals() const
104 {
105         updateData();
106         return optionals_;
107 }
108
109
110 vector<docstring> const &  MacroData::defaults() const
111 {
112         updateData();
113         return defaults_;
114 }
115
116
117 void MacroData::unlock() const
118 {
119         --lockCount_;
120         LASSERT(lockCount_ >= 0, /**/);
121 }
122
123
124 void MacroData::queryData(MathMacroTemplate const & macro) const
125 {
126         if (queried_)
127                 return;
128
129         queried_ = true;
130         definition_ = macro.definition();
131         numargs_ = macro.numArgs();
132         display_ = macro.displayDefinition();
133         redefinition_ = macro.redefinition();
134         type_ = macro.type();
135         optionals_ = macro.numOptionals();
136         
137         macro.getDefaults(defaults_);
138 }
139
140
141 void MacroData::updateData() const
142 {
143         if (queried_)
144                 return;
145
146         LASSERT(buffer_ != 0, /**/);
147         
148         // Try to fix position DocIterator. Should not do anything in theory.
149         pos_.fixIfBroken();
150         
151         // find macro template
152         Inset * inset = pos_.nextInset();
153         if (inset == 0 || inset->lyxCode() != MATHMACRO_CODE) {
154                 lyxerr << "BUG: No macro template found by MacroData" << endl;
155                 return;
156         }
157         
158         // query the data from the macro template
159         queryData(static_cast<MathMacroTemplate const &>(*inset));      
160 }
161         
162
163 void MacroData::write(odocstream & os, bool overwriteRedefinition) const
164 {
165         updateData();
166
167         // find macro template
168         Inset * inset = pos_.nextInset();
169         if (inset == 0 || inset->lyxCode() != MATHMACRO_CODE) {
170                 lyxerr << "BUG: No macro template found by MacroData" << endl;
171                 return;
172         }
173                 
174         // output template
175         MathMacroTemplate const & tmpl =
176                 static_cast<MathMacroTemplate const &>(*inset);
177         WriteStream wi(os, false, true, false);
178         tmpl.write(wi, overwriteRedefinition);
179 }
180
181
182 /////////////////////////////////////////////////////////////////////
183 //
184 // The global table of macros
185 //
186 /////////////////////////////////////////////////////////////////////
187
188 MacroTable & MacroTable::globalMacros()
189 {
190         static MacroTable theGlobalMacros;
191         return theGlobalMacros;
192 }
193
194
195 MacroData const * MacroTable::get(docstring const & name) const
196 {
197         const_iterator it = find(name);
198         return it == end() ? 0 : &it->second;
199 }
200
201
202 void MacroTable::insert(docstring const & name, MacroData const & data)
203 {
204         //lyxerr << "MacroTable::insert: " << to_utf8(name) << endl;
205         operator[](name) = data;
206 }
207
208
209 void MacroTable::insert(docstring const & def, string const & requires)
210 {
211         //lyxerr << "MacroTable::insert, def: " << to_utf8(def) << endl;
212         MathMacroTemplate mac(def);
213         MacroData data(mac);
214         data.requires() = requires;
215         insert(mac.name(), data);
216 }
217
218
219 void MacroTable::getMacroNames(std::set<docstring> & names) const
220 {
221         for (const_iterator it = begin(); it != end(); ++it)
222                 names.insert(it->first);
223 }
224
225
226 void MacroTable::dump()
227 {
228         lyxerr << "\n------------------------------------------" << endl;
229         for (const_iterator it = begin(); it != end(); ++it)
230                 lyxerr << to_utf8(it->first)
231                         << " [" << to_utf8(it->second.definition()) << "] : "
232                         << " [" << to_utf8(it->second.display()) << "] : "
233                         << endl;
234         lyxerr << "------------------------------------------" << endl;
235 }
236
237
238 /////////////////////////////////////////////////////////////////////
239 //
240 // MacroContext
241 //
242 /////////////////////////////////////////////////////////////////////
243
244 MacroContext::MacroContext(Buffer const & buf, DocIterator const & pos)
245         : buf_(buf), pos_(pos)
246 {
247 }
248
249
250 MacroData const * MacroContext::get(docstring const & name) const
251 {
252         return buf_.getMacro(name, pos_);
253 }
254
255 } // namespace lyx