]> git.lyx.org Git - lyx.git/blob - src/mathed/math_macro.C
450dd970cd2d6f74ed5e5d26aa596b50bf242a0e
[lyx.git] / src / mathed / math_macro.C
1 /*
2  *  File:        math_macro.C
3  *  Purpose:     Implementation of macro class for mathed 
4  *  Author:      Alejandro Aguilar Sierra <asierra@servidor.unam.mx> 
5  *  Created:     November 1996
6  *  Description: WYSIWYG math macros
7  *
8  *  Dependencies: Mathed
9  *
10  *  Copyright: 1996, 1997 Alejandro Aguilar Sierra
11  *
12  *  Version: 0.2, Mathed & Lyx project.
13  *
14  *  This code is under the GNU General Public Licence version 2 or later.
15  */
16
17 #include <config.h>
18
19 #ifdef __GNUG__
20 #pragma implementation
21 #endif
22
23 #include "math_macro.h"
24 #include "array.h"
25 #include "math_iter.h"
26 #include "math_inset.h"
27 #include "math_accentinset.h"
28 #include "math_deliminset.h"
29 #include "math_fracinset.h"
30 #include "math_rowst.h"
31 #include "support/lstrings.h"
32 #include "debug.h"
33 #include "mathed/support.h"
34 #include "math_macrotemplate.h"
35 #include "macro_support.h"
36 #include "Painter.h"
37
38 using namespace std;
39
40 ostream & operator<<(ostream & o, MathedTextCodes mtc)
41 {
42         return o << int(mtc);
43 }
44
45
46 MathMacro::MathMacro(MathMacroTemplate const & t)
47         : MathParInset(LM_ST_TEXT, t.GetName(), LM_OT_MACRO),
48           tmplate_(const_cast<MathMacroTemplate *>(&t)),
49                 args_(t.nargs()),
50                 idx_(t.nargs() ? 0 : -1)
51 {
52         array = tmplate_->GetData();
53         for (int i = 0; i < nargs(); ++i) 
54                 args_[i].reset(new MathParInset);
55 }
56
57
58 MathedInset * MathMacro::Clone()
59 {
60         return new MathMacro(*this);
61 }
62
63
64 void MathMacro::expand()
65 {
66         expanded_.reset(static_cast<MathParInset *>(tmplate_->Clone()));
67         expanded_->substitute(this);
68 }
69
70
71
72 MathParInset const * MathMacro::arg(int i) const
73 {
74         if (i < 0 || i >= nargs()) {
75                 lyxerr << "Illegal index " << i << " max: " << nargs() << endl;
76                 lyx::Assert(0);
77                 return 0;
78         }
79         return i >= 0 ? args_[i].get() : static_cast<MathParInset const *>(this);
80 }
81
82
83 MathParInset * MathMacro::arg(int i) 
84 {
85         if (i < 0 || i >= nargs()) {
86                 lyxerr << "Illegal index " << i << " max: " << nargs() << endl;
87                 lyx::Assert(0);
88                 return 0;
89         }
90         return i >= 0 ? args_[i].get() : static_cast<MathParInset *>(this);
91 }
92
93
94 MathMacroTemplate * MathMacro::tmplate() const
95 {
96         return const_cast<MathMacroTemplate *>(tmplate_);
97 }
98
99
100 extern bool is_mathcursor_inside(MathParInset *);
101
102 void MathMacro::Metrics()
103 {
104         if (is_mathcursor_inside(this)) {
105                 tmplate_->Metrics();
106                 width   = tmplate_->Width()   + 4;
107                 ascent  = tmplate_->Ascent()  + 2;
108                 descent = tmplate_->Descent() + 2;
109
110                 width +=  mathed_string_width(LM_TC_TEXTRM, size(), GetName()) + 10;
111
112                 for (int i = 0; i < nargs(); ++i) {
113                         MathParInset * p = arg(i);
114                         p->Metrics();
115                         if (p->Width() + 30 > width) 
116                                 width = p->Width() + 30;
117                         descent += p->Height() + 10;
118                 }
119         } else {
120                 expand();
121                 expanded_->Metrics();
122                 width   = expanded_->Width()   + 6;
123                 ascent  = expanded_->Ascent()  + 3;
124                 descent = expanded_->Descent() + 3;
125         }
126 }
127
128
129 void MathMacro::draw(Painter & pain, int x, int y)
130 {
131         LColor::color col;
132
133         if (is_mathcursor_inside(this)) {
134                 int h = y + Descent() - 2;
135                 for (int i = nargs() - 1; i >= 0; --i) {
136                         MathParInset * p = arg(i);
137                         h -= p->Descent() + 5;
138                         p->draw(pain, x + 30, h);
139                         char str[] = "#1:";
140                         str[1] += i;
141                         drawStr(pain, LM_TC_TEX, size(), x + 3, h, str);
142                         h -= p->Ascent() + 5;
143                 }
144
145                 h -= tmplate_->Descent();
146                 int w =  mathed_string_width(LM_TC_TEXTRM, size(), GetName());
147                 drawStr(pain, LM_TC_TEXTRM, size(), x + 3, h, GetName());
148                 tmplate_->draw(pain, x + w + 12, h);
149
150                 col = LColor::red;
151         } else {
152                 expanded_->draw(pain, x + 3, y);
153                 col = LColor::black;
154         }
155
156         int w = Width();
157         int a = Ascent();
158         int h = Height();
159         pain.rectangle(x + 1, y - a + 1, w - 2, h - 2, col);
160 }
161
162
163 bool MathMacro::setArgumentIdx(int i)
164 {
165         if (i >= 0 && 0 < (nargs() - i)) {
166                 idx_ = i;
167                 return true;
168         } else
169                 return false;
170         idx_ = i;
171         return true;
172 }
173
174
175 int MathMacro::getArgumentIdx() const 
176
177         //lyxerr << "MathMacro::getArgumentIdx: res: " << idx_ << endl;
178         return idx_;
179 }
180
181
182 int MathMacro::getMaxArgumentIdx() const 
183
184         return nargs() - 1;
185 }
186
187
188
189 int MathMacro::nargs() const 
190
191         return args_.size();
192
193
194
195 MathedArray & MathMacro::GetData() 
196
197         //lyxerr << "MathMacro::GetData: " << *this << endl;
198         return idx_ >= 0 ? arg(idx_)->GetData() : MathParInset::GetData(); 
199
200
201
202 MathedArray const & MathMacro::GetData() const
203
204         //lyxerr << "MathMacro::GetData: " << *this << endl;
205         return idx_ >= 0 ? arg(idx_)->GetData() : MathParInset::GetData(); 
206
207
208
209 int MathMacro::GetColumns() const
210 {
211         return idx_ >= 0 ? arg(idx_)->GetColumns() : MathParInset::GetColumns();
212 }
213
214
215 void MathMacro::GetXY(int & x, int & y) const
216 {
217         if (idx_ >= 0)
218                 arg(idx_)->GetXY(x, y);
219         else
220                 MathParInset::GetXY(x, y);
221 }
222
223
224 bool MathMacro::Permit(short f) const
225 {
226         return idx_ >= 0 ? arg(idx_)->Permit(f) : MathParInset::Permit(f);
227 }
228
229
230 void MathMacro::SetFocus(int x, int y)
231 {
232         idx_ = -1;
233         for (int i = 0; i < nargs(); ++i) {
234                 if (arg(i)->Inside(x, y)) {
235                         idx_ = i;
236                         break;
237                 }
238         }
239 }
240
241 void MathMacro::setData(MathedArray const & a, int i)
242 {
243         arg(i)->setData(a);
244 }
245
246
247 void MathMacro::setData(MathedArray const & a)
248 {
249         if (idx_ >= 0)
250                 arg(idx_)->setData(a);
251         else
252                 array = a;
253 }
254
255
256 MathedTextCodes MathMacro::getTCode() const
257 {
258         return nargs() ? LM_TC_ACTIVE_INSET : LM_TC_INSET;
259         //return LM_TC_INSET;
260 }
261         
262 void MathMacro::dump(ostream & os) const
263 {
264         os << "\n macro: '" << this << "'\n";
265         os << " name: '" << name << "'\n";
266         os << " idx: '" << idx_ << "'\n";
267         os << " data: '" << array << "'\n";
268         os << " nargs: '" << nargs() << "'\n";
269         for (int i = 0; i < nargs(); ++i)
270                 os << "  " << arg(i) << ": " << arg(i)->GetData() << endl;
271         os << endl;
272 }
273
274 void MathMacro::Write(ostream & os, bool fragile)
275 {
276         os << '\\' << name;
277         for (int i = 0; i < nargs(); ++i) {
278                 os << '{';
279                 arg(i)->Write(os, fragile);
280                 os << '}';
281         }
282         if (nargs() == 0) 
283                 os << ' ';
284 }
285
286
287 void MathMacro::WriteNormal(ostream & os)
288 {
289         os << "[macro " << name << " ";
290         for (int i = 0; i < nargs(); ++i) {
291                 arg(i)->WriteNormal(os);
292                 os << ' ';
293         }
294         os << "] ";
295 }