3 * Purpose: Implementation of insets for mathed
4 * Author: Alejandro Aguilar Sierra <asierra@servidor.unam.mx>
5 * Created: January 1996
8 * Dependencies: Xlib, XForms
10 * Copyright: 1996, Alejandro Aguilar Sierra
14 * You are free to use and modify this code under the terms of
15 * the GNU General Public Licence version 2 or later.
21 #pragma implementation
24 #include "math_iter.h"
26 #include "math_inset.h"
27 #include "symbol_def.h"
28 #include "support/lstrings.h"
30 #include "mathed/support.h"
34 const int SizeInset = sizeof(char*) + 2;
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 &);
41 MathedIter::MathedIter()
42 : flags(0), fcode_(0), pos(0), row(0), col(0), ncols(0), array(0)
46 void MathedIter::SetData(MathedArray * a)
52 MathedArray * MathedIter::GetData() const
57 short MathedIter::fcode() const
62 void MathedIter::fcode(short c) const
68 int MathedIter::Empty() const
70 return array->last() <= 1;
74 int MathedIter::OK() const
76 return array && (pos < array->last());
80 void MathedIter::Reset()
82 if (array->last() > 0 && MathIsFont((*array)[0])) {
94 byte MathedIter::GetChar() const
100 return (*array)[pos];
104 string const MathedIter::GetString() const
107 fcode((*array)[++pos]);
112 for (; (*array)[pos] >= ' ' && pos < array->last(); ++pos)
119 MathedInset * MathedIter::GetInset() const
123 array->raw_pointer_copy(&p, pos + 1);
126 lyxerr << "Math Error: This is not an inset["
127 << (*array)[pos] << "]" << endl;
133 // An active math inset MUST be derived from MathParInset because it
134 // must have at least one paragraph to edit
135 MathParInset * MathedIter::GetActiveInset() const
138 return reinterpret_cast<MathParInset*>(GetInset());
140 lyxerr << "Math Error: This is not an active inset" << endl;
145 bool MathedIter::Next()
150 if ((*array)[pos] < ' ') {
161 pos += sizeof(char*) + 2;
166 fcode((*array)[pos++]);
172 bool MathedIter::goNextCode(MathedTextCodes code)
175 if ((*array)[pos] == code)
183 void MathedIter::goPosAbs(int p)
186 while (pos < p && Next())
191 void MathedIter::insert(byte c, MathedTextCodes t)
196 if (t == LM_TC_TAB && col >= ncols - 1)
199 // Never more than one space // array->bf[pos-1] gives error from purify:
200 // Reading 1 byte from 0x47b857 in the heap.
202 // Address 0x47b857 is 1 byte before start of malloc'd block at
203 // 0x47b858 of 16 bytes.
205 if (c == ' ' && ((*array)[pos] == ' ' || (*array)[pos - 1] == ' '))
208 if (IsFont() && (*array)[pos] == t) {
212 if (t != fcode() && pos > 0 && MathIsFont((*array)[pos - 1])) {
215 for (; k >= 0 && (*array)[k] >= ' '; --k)
217 fcode( (k >= 0 && MathIsFont((*array)[k])) ? (*array)[k] : -1 );
221 short const f = ((*array)[pos] < ' ') ? 0 : fcode();
222 int shift = (t == fcode()) ? 1 : ((f) ? 3 : 2);
224 if (t == LM_TC_TAB || t == LM_TC_CR) {
234 if (pos < array->last())
235 array->move(pos, shift);
237 array->need_size(array->last() + shift);
238 array->last(array->last() + shift);
239 (*array)[array->last()] = '\0';
244 (*array)[pos + shift - 1] = fcode();
257 // Prepare to insert a non-char object
258 void MathedIter::split(int shift)
260 if (pos < array->last()) {
263 if ((*array)[pos] >= ' ') {
264 if (pos> 0 && MathIsFont((*array)[pos - 1]))
272 array->move(pos, shift);
275 (*array)[pos + shift - 1] = fcode();
279 array->need_size(array->last() + shift);
280 array->last(array->last() + shift);
283 (*array)[array->last()] = '\0';
287 // I assume that both pos and pos2 are legal positions
288 void MathedIter::join(int pos2)
290 if (!OK() || pos2 <= pos)
294 if (pos > 0 && (*array)[pos] >= ' ' && MathIsFont((*array)[pos - 1]))
297 if (MathIsFont((*array)[pos2 - 1]))
300 if ((*array)[pos2] >= ' ') {
301 for (int p = pos2; p > 0; --p) {
302 if (MathIsFont((*array)[p])) {
310 array->move(pos2, pos - pos2);
314 void MathedIter::insertInset(MathedInset * p, int type)
317 if (!MathIsInset(type))
320 array->insertInset(pos, p, type);
324 int const shift = SizeInset;
326 if (!MathIsInset(type))
331 (*array)[pos] = type;
332 array->raw_pointer_insert(p, pos + 1, sizeof(p));
334 (*array)[pos - 1] = type;
335 (*array)[array->last()] = '\0';
341 bool MathedIter::Delete()
350 if (MathIsFont((*array)[pos - 1]) && (*array)[pos + 1] < ' ') {
354 for (; i > 0 && !MathIsFont((*array)[i]); --i)
356 if (i > 0 && MathIsFont((*array)[i]))
363 if (MathIsInset((*array)[pos]))
364 shift = sizeof(char*) + 2;
365 else if (c == LM_TC_TAB || c == LM_TC_CR) {
367 // lyxerr <<"Es un tab.";
369 lyxerr << "Math Warning: expected inset." << endl;
375 array->move(pos + shift, -shift);
376 if (pos >= array->last())
377 pos = (array->last() > 0) ? array->last() : 0;
384 MathedArray * MathedIter::Copy()
387 return Copy(0, 10000);
390 // lyxerr << "Math error: Attempting to copy a void array." << endl;
394 return new MathedArray(*array);
399 MathedArray * MathedIter::Copy(int pos1, int pos2)
402 // lyxerr << "Math error: Attempting to copy a void array." << endl;
407 MathedArray * t = array;
410 if (pos1 > 0 || pos2 <= array->last()) {
412 if (pos1 > 0 && (*array)[pos1] > ' ') {
413 for (int p = pos1; p >= 0; --p) {
414 if (MathIsFont((*array)[p])) {
424 if (pos2 > 0 && (*array)[pos2] >= ' '
425 && MathIsFont((*array)[pos2 - 1]))
428 int dx = pos2 - pos1;
431 // lyxerr << "VA " << pos2 << " " << pos2 << " " << dx << endl;
432 array->strange_copy(a, (fc) ? 1 : 0, pos1, dx);
440 a = new MathedArray(*array);
442 // this should be unnecessary and leak in some (most?) cases since
443 // a = new MathedArray(*array); makes already a deep copy...
444 // I guess it'll go soon... (Andre')
449 MathedInset * inset = GetInset();
450 inset = inset->Clone();
451 array->raw_pointer_insert(inset, pos + 1, sizeof(inset));
461 void MathedIter::Clear()
464 lyxerr << "Math error: Attempting to clean a void array." << endl;
471 MathedInset * inset = GetInset();
472 if (inset->GetType()!= LM_OT_MACRO_ARG)
481 // Check consistency of tabs and crs
482 void MathedIter::checkTabs()
486 // MathedIter:Reset();
488 if ((IsTab() && col >= ncols - 1) || (IsCR() && !(MthIF_CR & flags))) {
493 if (IsCR() && col < ncols - 2)
494 insert(' ', LM_TC_TAB);
500 insert(' ', LM_TC_TAB);
506 // Try to adjust tabs in the expected place, as used in eqnarrays
508 // - If there are a relation operator, put tabs around it
509 // - If tehre are not a relation operator, put everything in the
511 void MathedIter::adjustTabs()
515 bool MathedIter::IsInset() const
517 return MathIsInset((*array)[pos]);
521 bool MathedIter::IsActive() const
523 return MathIsActive((*array)[pos]);
527 bool MathedIter::IsFont() const
529 return MathIsFont((*array)[pos]);
533 bool MathedIter::IsScript() const
535 return MathIsScript((*array)[pos]);
539 bool MathedIter::IsTab() const
541 return ((*array)[pos] == LM_TC_TAB);
545 bool MathedIter::IsCR() const
547 return ((*array)[pos] == LM_TC_CR);
551 MathedIter::MathedIter(MathedArray * d)
557 fcode( (array && IsFont()) ? (*array)[0] : 0 );
561 void MathedIter::ipush()
563 stck.fcode = fcode();
570 void MathedIter::ipop()