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