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