]> git.lyx.org Git - lyx.git/blob - src/mathed/math_iter.C
fix "make dist" target
[lyx.git] / src / mathed / math_iter.C
1 /*
2  *  File:        math_inset.C
3  *  Purpose:     Implementation of insets for mathed
4  *  Author:      Alejandro Aguilar Sierra <asierra@servidor.unam.mx>
5  *  Created:     January 1996
6  *  Description:
7  *
8  *  Dependencies: Xlib, XForms
9  *
10  *  Copyright: 1996, Alejandro Aguilar Sierra
11  *
12  *   Version: 0.8beta.
13  *
14  *   You are free to use and modify this code under the terms of
15  *   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_iter.h"
25 #include "array.h"
26 #include "math_inset.h"
27 #include "symbol_def.h"
28 #include "support/lstrings.h"
29 #include "debug.h"
30 #include "mathed/support.h"
31
32 using std::endl;
33
34 const int SizeInset = sizeof(char*) + 2;
35
36 //extern int mathed_char_width(short type, int style, byte c);
37 //extern int mathed_string_width(short type, int style, string const & s);
38 //extern int mathed_char_height(short, int, byte, int &, int &);
39
40
41 MathedIter::MathedIter()
42         : flags(0), fcode_(0), pos(0), row(0), col(0), ncols(0), array(0)
43 {}
44
45
46 MathedArray * MathedIter::GetData() const
47 {
48         return array;
49 }
50
51
52 short MathedIter::fcode() const
53 {
54         return fcode_; 
55 }
56
57
58 void MathedIter::fcode(short c) const
59 {
60         fcode_ = c; 
61 }
62
63 byte MathedIter::at() const
64 {
65         return (*array)[pos]; 
66 }
67
68 byte MathedIter::at(int p) const
69 {
70         return (*array)[p]; 
71 }
72
73 byte & MathedIter::at(int p)
74 {
75         return (*array)[p]; 
76 }
77
78 int MathedIter::Empty() const
79 {
80         return array->last() <= 1;
81 }
82
83
84 int MathedIter::OK() const
85 {
86         return array && (pos < array->last());
87 }
88
89
90 void MathedIter::Reset()
91 {
92         if (array->last() > 0 && MathIsFont(at(0))) {
93                 fcode(at(0));
94                 pos   = 1;
95         } else {
96                 fcode(-1);
97                 pos   = 0;
98         }
99         col = 0;
100         row = 0;
101 }
102
103
104 byte MathedIter::GetChar() const
105 {
106         if (IsFont()) {
107                 fcode(at(pos));
108                 ++pos;
109         }
110         return at(pos);
111 }
112
113
114 string const MathedIter::GetString() const
115 {
116         if (IsFont()) {
117                 fcode(at(++pos));
118                 ++pos;
119         }
120
121         string s;
122         for (; at(pos) >= ' ' && pos < array->last(); ++pos)
123                 s += at(pos);
124
125         return s;
126 }
127
128
129 MathedInset * MathedIter::GetInset() const
130 {
131         if (IsInset()) {
132                 MathedInset * p;
133                 array->raw_pointer_copy(&p, pos + 1);
134                 return p;
135         } else {
136                 lyxerr << "Math Error: This is not an inset["
137                        << at(pos) << "]" << endl;
138                 return 0;
139         }
140 }
141
142
143 // An active math inset MUST be derived from MathParInset because it
144 // must have at least one paragraph to edit
145 MathParInset * MathedIter::GetActiveInset() const
146 {
147         if (IsActive()) 
148                 return reinterpret_cast<MathParInset*>(GetInset());
149
150         lyxerr << "Math Error: This is not an active inset" << endl;
151         return 0;
152 }
153
154
155 bool MathedIter::Next()
156 {
157         if (!OK())
158                 return false;
159
160         if (at(pos) < ' ') {
161                 fcode(-1);
162                 if (IsTab())
163                         ++col;
164                 if (IsCR()) {
165                         col = 0;
166                         ++row;
167                 }
168         }
169
170         if (IsInset())
171                 pos += sizeof(char*) + 2;
172         else
173                 ++pos;
174
175         if (IsFont()) 
176                 fcode(at(pos++));
177
178         return true;
179 }
180
181
182 bool MathedIter::goNextCode(MathedTextCodes code)
183 {
184         while (Next()) {
185                 if (at(pos) == code)
186                         return true;
187         }
188
189         return false;
190 }
191
192
193 void MathedIter::goPosAbs(int p)
194 {
195         Reset();
196         while (pos < p && Next())
197                 ;
198 }
199
200
201 void MathedIter::insert(byte c, MathedTextCodes t)
202 {
203         if (c < ' ')
204                 return;
205
206         if (t == LM_TC_TAB && col >= ncols - 1)
207                 return;
208
209         // Never more than one space // array->bf[pos-1] gives error from purify:
210         // Reading 1 byte from 0x47b857 in the heap.
211         //
212         // Address 0x47b857 is 1 byte before start of malloc'd block at
213         // 0x47b858 of 16 bytes.
214
215         if (c == ' ' && (at(pos) == ' ' || at(pos - 1) == ' '))
216                 return;
217
218         if (IsFont() && at(pos) == t) {
219                 fcode(t);
220                 ++pos;
221         } else {
222                 if (t != fcode() && pos > 0 && MathIsFont(at(pos - 1))) {
223                         --pos;
224                         int k = pos - 1;
225                         for (; k >= 0 && at(k) >= ' '; --k)
226                                 ;
227                         fcode( (k >= 0 && MathIsFont(at(k))) ? at(k) : -1 );
228                 }
229         }
230
231         short const f = (at(pos) < ' ') ? 0 : fcode();
232         int shift = (t == fcode()) ? 1 : ((f) ? 3 : 2);
233
234         if (t == LM_TC_TAB || t == LM_TC_CR) {
235                 --shift;
236                 c = t;
237                 if (t == LM_TC_CR) {
238                         ++row;
239                         col = 0;
240                 } else
241                         ++col;
242         }
243
244         if (pos < array->last())
245                 array->move(pos, shift);
246         else {
247                 array->need_size(array->last() + shift);
248                 array->last(array->last() + shift);
249                 at(array->last()) = '\0';
250         }
251
252         if (t != fcode()) {
253                 if (f)
254                         at(pos + shift - 1) = fcode();
255
256                 if (c >= ' ') {
257                         at(pos++) = t;
258                         fcode(t);
259                 } else 
260                         fcode(0);
261         }
262
263         at(pos++) = c;
264 }
265
266
267 // Prepare to insert a non-char object
268 void MathedIter::split(int shift)
269 {
270         if (pos < array->last()) {
271
272                 bool fg = false;
273                 if (at(pos) >= ' ') {
274                         if (pos> 0 && MathIsFont(at(pos - 1)))
275                                 --pos;
276                         else {
277                                 fg = true;
278                                 ++shift;
279                         }
280                 }
281
282                 array->move(pos, shift);
283
284                 if (fg)
285                         at(pos + shift - 1) = fcode();
286
287         } else {
288
289                 array->need_size(array->last() + shift);
290                 array->last(array->last() + shift);
291         }
292
293         at(array->last()) = '\0';
294 }
295
296
297 // I assume that both pos and pos2 are legal positions
298 void MathedIter::join(int pos2)
299 {
300         if (!OK() || pos2 <= pos)
301                 return;
302
303         short f = fcode();
304         if (pos > 0 && at(pos) >= ' ' && MathIsFont(at(pos - 1)))
305                 --pos;  
306
307         if (MathIsFont(at(pos2 - 1)))
308                 --pos2;
309
310         if (at(pos2) >= ' ') {
311                 for (int p = pos2; p > 0; --p) {
312                         if (MathIsFont(at(p))) {
313                                 f = at(p);
314                                 break;
315                         }
316                 }
317                 at(pos++) = f;
318         }
319
320         array->move(pos2, pos - pos2);
321 }
322
323
324 void MathedIter::insertInset(MathedInset * p, int type)
325 {
326 #if 0
327         if (!MathIsInset(type))
328                 type = LM_TC_INSET;
329
330         array->insertInset(pos, p, type);
331         ++pos;
332         fcode(-1);
333 #else
334         int const shift = SizeInset;
335
336         if (!MathIsInset(type))
337                 type = LM_TC_INSET;
338
339         split(shift);
340
341         at(pos) = type;
342         array->raw_pointer_insert(p, pos + 1);
343         pos += SizeInset;
344         at(pos - 1) = type;
345         at(array->last()) = '\0';
346         fcode(-1);
347 #endif
348 }
349
350
351 bool MathedIter::Delete()
352 {
353         if (!OK())
354                 return false;
355
356         int shift = 0;
357         byte const c = GetChar();
358         if (c >= ' ') {
359
360                 if (MathIsFont(at(pos - 1)) && at(pos + 1) < ' ') {
361                         shift = 2;
362                         pos--;
363                         int i = pos - 1;
364                         for (; i > 0 && !MathIsFont(at(i)); --i)
365                                 ;
366                         if (i > 0 && MathIsFont(at(i)))
367                         fcode(at(i));
368                 } else
369                         shift = 1;
370
371         } else {
372
373                 if (MathIsInset(at(pos)))
374                         shift = sizeof(char*) + 2;
375                 else if (c == LM_TC_TAB || c == LM_TC_CR) {
376                         ++shift;
377                 //       lyxerr <<"Es un tab.";
378                 } else {
379                         lyxerr << "Math Warning: expected inset." << endl;
380                 }
381
382         }
383
384         if (shift != 0) {
385                 array->move(pos + shift, -shift);
386                 if (pos >= array->last())
387                         pos = (array->last() > 0) ? array->last() : 0;
388                 return true;
389         } else
390                 return false;
391 }
392
393 // Check consistency of tabs and crs
394 void MathedIter::checkTabs()
395 {
396         ipush();
397
398         // MathedIter:Reset();
399         while (OK()) {
400                 if ((IsTab() && col >= ncols - 1) || (IsCR() && !(MthIF_CR & flags))) {
401                         Delete();
402                         continue;
403                 }
404
405                 if (IsCR() && col < ncols - 2) 
406                         insert(' ', LM_TC_TAB);
407
408                 MathedIter::Next();
409         }
410
411         if (col < ncols - 2)
412                 insert(' ', LM_TC_TAB);
413         
414         ipop();
415 }
416
417
418 //  Try to adjust tabs in the expected place, as used in eqnarrays
419 //  Rules:
420 //   - If there are a relation operator, put tabs around it
421 //   - If tehre are not a relation operator, put everything in the
422 //     3rd column.
423 void MathedIter::adjustTabs()
424 {}
425
426
427 bool MathedIter::IsInset() const
428 {
429         return MathIsInset(at(pos));
430 }
431
432
433 bool MathedIter::IsActive() const
434 {
435         return MathIsActive(at(pos));
436 }
437
438
439 bool MathedIter::IsFont() const
440 {
441         return MathIsFont(at(pos));
442 }
443
444
445 bool MathedIter::IsScript() const
446 {
447         return MathIsScript(at(pos));
448 }
449
450
451 bool MathedIter::IsTab() const
452 {
453         return (at(pos) == LM_TC_TAB);
454 }
455
456
457 bool MathedIter::IsCR() const
458 {
459         return (at(pos) == LM_TC_CR);
460 }
461
462
463 MathedIter::MathedIter(MathedArray * d)
464         : array(d)
465 {
466         pos = 0;
467         row = 0;
468         col = 0;
469         fcode( (array && IsFont()) ? at(0) : 0 );
470 }
471
472
473 void MathedIter::ipush()
474 {
475         stck.fcode = fcode();
476         stck.pos = pos;
477         stck.row = row;
478         stck.col = col;
479 }
480
481
482 void MathedIter::ipop()
483 {
484         fcode(stck.fcode);
485         pos = stck.pos;
486         row = stck.row;
487         col = stck.col;
488 }