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