]> git.lyx.org Git - lyx.git/blob - src/mathed/math_iter.C
remove cruft
[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 void MathedIter::SetData(MathedArray * a)
47 {
48         array = a; Reset();
49 }
50
51
52 MathedArray * MathedIter::GetData() const
53 {
54         return array;
55 }
56
57
58 int MathedIter::Empty() const
59 {
60         return array->last() <= 1;
61 }
62
63
64 int MathedIter::OK() const
65 {
66         return array && (pos < array->last());
67 }
68
69
70 void MathedIter::Reset()
71 {
72         if (array->last() > 0 && MathIsFont((*array)[0])) {
73                 fcode = (*array)[0];
74                 pos   = 1;
75         } else {
76                 fcode = -1;
77                 pos   = 0;
78         }
79         col = 0;
80         row = 0;
81 }
82
83
84 byte MathedIter::GetChar() const
85 {
86         if (IsFont()) {
87                 fcode = (*array)[pos];
88                 ++pos;
89         }
90         return (*array)[pos];
91 }
92
93
94 string const MathedIter::GetString() const
95 {
96         if (IsFont()) {
97                 fcode = (*array)[++pos];
98                 ++pos;
99         }
100
101         string s;
102         for (; (*array)[pos] >= ' ' && pos < array->last(); ++pos)
103                 s += (*array)[pos];
104
105         return s;
106 }
107
108
109 MathedInset * MathedIter::GetInset() const
110 {
111         if (IsInset()) {
112                 MathedInset * p;
113                 array->raw_pointer_copy(&p, pos + 1);
114                 return p;
115         } else {
116                 lyxerr << "Math Error: This is not an inset["
117                        << (*array)[pos] << "]" << endl;
118                 return 0;
119         }
120 }
121
122
123 // An active math inset MUST be derived from MathParInset because it
124 // must have at least one paragraph to edit
125 MathParInset * MathedIter::GetActiveInset() const
126 {
127         if (IsActive()) 
128                 return reinterpret_cast<MathParInset*>(GetInset());
129
130         lyxerr << "Math Error: This is not an active inset" << endl;
131         return 0;
132 }
133
134
135 bool MathedIter::Next()
136 {
137         if (!OK())
138                 return false;
139
140         if ((*array)[pos] < ' ') {
141                 fcode = -1;
142                 if (IsTab())
143                         ++col;
144                 if (IsCR()) {
145                         col = 0;
146                         ++row;
147                 }
148         }
149
150         if (IsInset())
151                 pos += sizeof(char*) + 2;
152         else
153                 ++pos;
154
155         if (IsFont()) 
156                 fcode = (*array)[pos++];
157
158         return true;
159 }
160
161
162 bool MathedIter::goNextCode(MathedTextCodes code)
163 {
164         while (Next()) {
165                 if ((*array)[pos] == code)
166                         return true;
167         }
168
169         return false;
170 }
171
172
173 void MathedIter::goPosAbs(int p)
174 {
175         Reset();
176         while (pos < p && Next())
177                 ;
178 }
179
180
181 void MathedIter::goPosRel(int dp)
182 {
183         int const posx = pos + dp;
184
185         // is posx a valid position?
186         if (dp < 0)
187                 Reset();
188
189         while (pos < posx && Next())
190                 ;
191 }
192
193
194 void MathedIter::Insert(byte c, MathedTextCodes t)
195 {
196         if (c < ' ')
197                 return;
198
199         if (t == LM_TC_TAB && col >= ncols - 1)
200                 return;
201
202         // Never more than one space // array->bf[pos-1] gives error from purify:
203         // Reading 1 byte from 0x47b857 in the heap.
204         //
205         // Address 0x47b857 is 1 byte before start of malloc'd block at
206         // 0x47b858 of 16 bytes.
207
208         if (c == ' ' && ((*array)[pos] == ' ' || (*array)[pos - 1] == ' '))
209                 return;
210
211         if (IsFont() && (*array)[pos] == t) {
212                 fcode = t;
213                 ++pos;
214         } else {
215                 if (t != fcode && pos > 0 && MathIsFont((*array)[pos - 1])) {
216                         --pos;
217                         int k = pos - 1;
218                         for (; k >= 0 && (*array)[k] >= ' '; --k)
219                                 ;
220                         fcode = (k >= 0 && MathIsFont((*array)[k])) ? (*array)[k] : -1;
221                 }
222         }
223
224         short const f = ((*array)[pos] < ' ') ? 0 : fcode;
225         int shift = (t == fcode) ? 1 : ((f) ? 3 : 2);
226
227         if (t == LM_TC_TAB || t == LM_TC_CR) {
228                 --shift;
229                 c = t;
230                 if (t == LM_TC_CR) {
231                         ++row;
232                         col = 0;
233                 } else
234                         ++col;
235         }
236
237         if (pos < array->last())
238                 array->move(pos, shift);
239         else {
240                 array->need_size(array->last() + shift);
241                 array->last(array->last() + shift);
242                 (*array)[array->last()] = '\0';
243         }
244
245         if (t != fcode) {
246                 if (f)
247                         (*array)[pos + shift - 1] = fcode;
248
249                 if (c >= ' ') {
250                         (*array)[pos++] = t;
251                         fcode = t;
252                 } else 
253                         fcode = 0;
254         }
255
256         (*array)[pos++] = c;
257 }
258
259
260 // Prepare to insert a non-char object
261 void MathedIter::split(int shift)
262 {
263         if (pos < array->last()) {
264
265                 bool fg = false;
266                 if ((*array)[pos] >= ' ') {
267                         if (pos> 0 && MathIsFont((*array)[pos - 1]))
268                                 --pos;
269                         else {
270                                 fg = true;
271                                 ++shift;
272                         }
273                 }
274
275                 array->move(pos, shift);
276
277                 if (fg)
278                         (*array)[pos + shift - 1] = fcode;
279
280         } else {
281
282                 array->need_size(array->last() + shift);
283                 array->last(array->last() + shift);
284         }
285
286         (*array)[array->last()] = '\0';
287 }
288
289
290 // I assume that both pos and pos2 are legal positions
291 void MathedIter::join(int pos2)
292 {
293         if (!OK() || pos2 <= pos)
294                 return;
295
296         short f = fcode;
297         if (pos > 0 && (*array)[pos] >= ' ' && MathIsFont((*array)[pos - 1]))
298                 --pos;  
299
300         if (MathIsFont((*array)[pos2 - 1]))
301                 --pos2;
302
303         if ((*array)[pos2] >= ' ') {
304                 for (int p = pos2; p > 0; --p) {
305                         if (MathIsFont((*array)[p])) {
306                                 f = (*array)[p];
307                                 break;
308                         }
309                 }
310                 (*array)[pos++] = f;
311         }
312
313         array->move(pos2, pos - pos2);
314 }
315
316
317 void MathedIter::Insert(MathedInset * p, int type)
318 {
319         int const shift = SizeInset;
320
321         if (!MathIsInset(type))
322                 type = LM_TC_INSET;
323
324         split(shift);
325
326         (*array)[pos] = type;
327         array->raw_pointer_insert(p, pos + 1, sizeof(p));
328         pos += SizeInset;
329         (*array)[pos - 1] = type;
330         (*array)[array->last()] = '\0';
331         fcode = -1;
332 }
333
334
335 bool MathedIter::Delete()
336 {
337         if (!OK())
338                 return false;
339
340         int shift = 0;
341         byte c = GetChar();
342         if (c >= ' ') {
343
344                 if (MathIsFont((*array)[pos - 1]) && (*array)[pos + 1] < ' ') {
345                         shift = 2;
346                         pos--;
347                         int i = pos - 1;
348                         for (; i > 0 && !MathIsFont((*array)[i]); --i)
349                                 ;
350                         if (i > 0 && MathIsFont((*array)[i]))
351                         fcode = (*array)[i];
352                 } else
353                         shift = 1;
354
355         } else {
356
357                 if (MathIsInset((*array)[pos]))
358                         shift = sizeof(char*) + 2;
359                 else if (c == LM_TC_TAB || c == LM_TC_CR) {
360                         ++shift;
361                 //       lyxerr <<"Es un tab.";
362                 } else {
363                         lyxerr << "Math Warning: expected inset." << endl;
364                 }
365
366         }
367
368         if (shift != 0) {
369                 array->move(pos + shift, -shift);
370                 if (pos >= array->last())
371                         pos = (array->last() > 0) ? array->last() : 0;
372                 return true;
373         } else
374                 return false;
375 }
376
377
378 MathedArray * MathedIter::Copy(int pos1, int pos2)
379 {
380         if (!array) {
381         //      lyxerr << "Math error: Attempting to copy a void array." << endl;
382                 return 0;
383         }
384
385         ipush();
386         MathedArray * t = array;
387         MathedArray * a;
388
389         if (pos1 > 0 || pos2 <= array->last()) {
390                 short fc = 0;
391                 if (pos1 > 0 && (*array)[pos1] > ' ') {
392                         for (int p = pos1; p >= 0; --p) {
393                                 if (MathIsFont((*array)[p])) {
394                                 if (p != pos1 - 1)
395                                 fc = (*array)[p];
396                                 else
397                                 --pos1;
398                                 break;
399                                 }
400                         }
401                 }
402
403                 if (pos2 > 0 && (*array)[pos2] >= ' '
404                              && MathIsFont((*array)[pos2 - 1]))
405                         --pos2;
406
407                 int dx = pos2 - pos1;
408                 a = new MathedArray(dx + MathedArray::ARRAY_MIN_SIZE);
409                 //       lyxerr << "VA " << pos2 << " " << pos2 << " " << dx << endl;
410                 array->strange_copy(a, (fc) ? 1 : 0, pos1, dx);
411                 if (fc) {
412                         (*a)[0] = fc;
413                         ++dx;
414                 }
415                 a->last(dx);
416                 (*a)[dx] = '\0';
417         } else
418                 a = new MathedArray(*array);
419
420         SetData(a);
421         while (OK()) {
422                 if (IsInset()) {
423                         MathedInset * inset = GetInset();
424                         inset = inset->Clone();
425                         array->raw_pointer_insert(inset, pos + 1, sizeof(inset));
426                 }
427                 Next();
428         }
429         array = t;
430         ipop();
431         return a;
432 }
433
434
435 void MathedIter::Clear()
436 {
437         if (!array) {
438                 lyxerr << "Math error: Attempting to clean a void array." << endl;
439                 return;
440         }
441
442         Reset();
443         while (OK()) {
444                 if (IsInset()) {
445                         MathedInset * inset = GetInset();
446                         if (inset->GetType()!= LM_OT_MACRO_ARG)
447                         delete inset;
448                         Delete();
449                 } else
450                         Next();
451         }
452 }
453
454
455 // Check consistency of tabs and crs
456 void MathedIter::checkTabs()
457 {
458         ipush();
459
460         // MathedIter:Reset();
461         while (OK()) {
462                 if ((IsTab() && col >= ncols - 1) || (IsCR() && !(MthIF_CR & flags))) {
463                         Delete();
464                         continue;
465                 }
466
467                 if (IsCR() && col < ncols - 2) 
468                         Insert(' ', LM_TC_TAB);
469
470                 MathedIter::Next();
471         }
472
473         if (col < ncols - 2)
474                 Insert(' ', LM_TC_TAB);
475         
476         ipop();
477 }
478
479
480 //  Try to adjust tabs in the expected place, as used in eqnarrays
481 //  Rules:
482 //   - If there are a relation operator, put tabs around it
483 //   - If tehre are not a relation operator, put everything in the
484 //     3rd column.
485 void MathedIter::adjustTabs()
486 {}
487
488
489 bool MathedIter::IsInset() const
490 {
491         return MathIsInset((*array)[pos]);
492 }
493
494
495 bool MathedIter::IsActive() const
496 {
497         return MathIsActive((*array)[pos]);
498 }
499
500
501 bool MathedIter::IsFont() const
502 {
503         return MathIsFont((*array)[pos]);
504 }
505
506
507 bool MathedIter::IsScript() const
508 {
509         return MathIsScript((*array)[pos]);
510 }
511
512
513 bool MathedIter::IsTab() const
514 {
515         return ((*array)[pos] == LM_TC_TAB);
516 }
517
518
519 bool MathedIter::IsCR() const
520 {
521         return ((*array)[pos] == LM_TC_CR);
522 }
523
524
525 MathedIter::MathedIter(MathedArray * d)
526         : array(d)
527 {
528         pos = 0;
529         row = 0;
530         col = 0;
531         fcode = (array && IsFont()) ? (*array)[0]: 0;
532 }
533
534
535 void MathedIter::ipush()
536 {
537         stck.fcode = fcode;
538         stck.pos = pos;
539         stck.row = row;
540         stck.col = col;
541 }
542
543
544 void MathedIter::ipop()
545 {
546         fcode = stck.fcode;
547         pos = stck.pos;
548         row = stck.row;
549         col = stck.col;
550 }