/* * File: math_inset.C * Purpose: Implementation of insets for mathed * Author: Alejandro Aguilar Sierra <asierra@servidor.unam.mx> * Created: January 1996 * Description: * * Dependencies: Xlib, XForms * * Copyright: (c) 1996, Alejandro Aguilar Sierra * * Version: 0.8beta. * * You are free to use and modify this code under the terms of * the GNU General Public Licence version 2 or later.
*/
byte* MathedIter::GetString(int& len)
{ if (IsFont()) {
fcode = array->bf[++pos];
pos++;
}
byte *s = &array->bf[pos];
len = pos; while (array->bf[pos]>=' ' && pos<array->last) pos++;
len = pos-len;
return s;
}
MathedInset* MathedIter::GetInset()
{ if (IsInset()) {
MathedInset* p;
memcpy(&p, &array->bf[pos+1], sizeof(p)); return p;
} else {
fprintf(stderr,"Math Error: This is not an inset[%d]\n", array->bf[pos]); return 0;
}
}
// An active math inset MUST be derived from MathParInset because it // must have at least one paragraph to edit
MathParInset* MathedIter::GetActiveInset()
{ if (IsActive()) { return (MathParInset*)GetInset();
}
fprintf(stderr,"Math Error: This is not an active inset\n"); return 0;
}
bool MathedIter::Next()
{ if (!OK()) returnfalse;
if (array->bf[pos]<' ') {
fcode = -1; if (IsTab()) col++; if (IsCR()) {
col = 0;
row++;
}
}
if (IsInset())
pos += sizeof(char*) + 2; else
pos++;
if (IsFont()) {
fcode = array->bf[pos++];
}
returntrue;
}
bool MathedIter::goNextCode(MathedTextCodes code)
{ while (Next()) { if (array->bf[pos]==code) returntrue;
}
returnfalse;
}
void MathedIter::goPosAbs(int p)
{
Reset(); while (pos<p && Next());
}
void MathedIter::goPosRel(int dp)
{ int posx = pos+dp;
// is posx a valid position? if (dp<0)
Reset(); while (pos<posx && Next());
}
void MathedIter::Insert(byte c, MathedTextCodes t)
{ if (c<' ') return;
if (t==LM_TC_TAB && col>=ncols-1) return;
// Never more than one space // array->bf[pos-1] gives error from purify: // Reading 1 byte from 0x47b857 in the heap. // Address 0x47b857 is 1 byte before start of malloc'd block at 0x47b858 of 16 bytes. if (c==' ' && (array->bf[pos]==' ' || array->bf[pos-1]==' ')) return;
if (IsFont() && array->bf[pos]==t) {
fcode = t;
pos++;
} else if (t!=fcode && pos>0 && MathIsFont(array->bf[pos-1])) {
pos--; int k; for (k=pos-1; k>=0 && array->bf[k]>=' '; k--);
fcode = (k >= 0 && MathIsFont(array->bf[k])) ? array->bf[k]: -1;
} short f = (array->bf[pos]<' ') ? 0: fcode; int shift = (t==fcode) ? 1: ((f) ? 3: 2);
if (t==LM_TC_TAB || t==LM_TC_CR) {
shift--;
c = t; if (t==LM_TC_CR) {
row++;
col = 0;
} else
col++;
}
// Prepare to insert a non-char object void MathedIter::split(int shift)
{ if (pos < array->last) { bool fg = false; if (array->bf[pos]>=' ') { if (pos> 0 && MathIsFont(array->bf[pos-1]))
pos--; else {
fg = true;
shift++;
}
}
array->Move(pos, shift); if (fg) array->bf[pos+shift-1] = fcode;
} else { if (array->last+shift>=array->maxsize) {
array->Resize(array->last+shift);
}
array->last += shift;
}
array->bf[array->last] = '\0';
}
// I assume that both pos and pos2 are legal positions void MathedIter::join(int pos2)
{ if (!OK() || pos2<=pos) return;
short f=fcode; if (pos>0 && array->bf[pos]>=' ' && MathIsFont(array->bf[pos-1]))
pos--;
if (MathIsFont(array->bf[pos2-1]))
pos2--;
if (array->bf[pos2]>=' ') { for (int p=pos2; p>0; p--) if (MathIsFont(array->bf[p])) {
f = array->bf[p]; break;
}
array->bf[pos++] = f;
}
array->Move(pos2, pos-pos2);
}
void MathedIter::Insert(MathedInset* p, int type)
{ int shift = SizeInset; if (!MathIsInset(type))
type = LM_TC_INSET;
split(shift);
array->bf[pos] = type;
memcpy(&array->bf[pos+1], &p, sizeof(p));
pos += SizeInset;
array->bf[pos-1] = type;
array->bf[array->last] = '\0';
fcode = -1;
}
bool MathedIter::Delete()
{ if (!OK()) returnfalse;
int shift = 0;
byte c = GetChar(); if (c>=' ') { if (MathIsFont(array->bf[pos-1]) && array->bf[pos+1]<' ') { int i;
shift = 2;
pos--; for (i=pos-1; i>0 && !MathIsFont(array->bf[i]); i--); if (i>0 && MathIsFont(array->bf[i]))
fcode = array->bf[i];
} else
shift = 1;
} else { if (MathIsInset(array->bf[pos]))
shift = sizeof(char*) + 2; else if (c==LM_TC_TAB || c==LM_TC_CR) {
shift++; // fprintf(stderr, "Es un tab.");
} else {
fprintf(stderr, "Math Warning: expected inset.");
fflush(stderr);
}
}
if (shift!=0) {
array->Move(pos+shift, -shift); if (pos>=array->last)
pos = (array->last>0) ? array->last: 0; returntrue;
} else returnfalse;
}
LyxArrayBase *MathedIter::Copy(int pos1, int pos2)
{ if (!array) { // fprintf(stderr, "Math error: Attempting to copy a void array.\n"); return 0;
}
// int posx = pos;
ipush();
LyxArrayBase *t=array, *a;
if (pos1>0 || pos2<=array->last) { short fc=0; if (pos1>0 && array->bf[pos1]>' ') { for (int p=pos1; p>=0; p--) if (MathIsFont(array->bf[p])) { if (p!=pos1-1)
fc = array->bf[p]; else
pos1--; break;
}
}
if (pos2>0 && array->bf[pos2]>=' ' && MathIsFont(array->bf[pos2-1]))
pos2--;
int dx = pos2 - pos1;
a = new LyxArrayBase(dx+LyxArrayBase::ARRAY_MIN_SIZE); // fprintf(stderr, "VA %d %d %d ", pos1, pos2, dx); fflush(stderr);
memcpy(&a->bf[(fc) ? 1: 0], &array->bf[pos1], dx); if (fc) {
a->bf[0] = fc;
dx++;
}
a->last = dx;
a->bf[dx] = '\0';
} else
a = new LyxArrayBase(*array);
SetData(a); while (OK()) { if (IsInset()) {
MathedInset* inset = GetInset();
inset = inset->Clone();
memcpy(&array->bf[pos+1], &inset, sizeof(inset));
}
Next();
} // pos = posx;
array = t;
ipop(); return a;
}
void MathedIter::Clear()
{ if (!array) {
fprintf(stderr, "Math error: Attempting to clean a void array.\n"); return;
}
Reset(); while (OK()) { if (IsInset()) {
MathedInset* inset = GetInset(); if (inset->GetType()!=LM_OT_MACRO_ARG) delete inset; Delete();
} else
Next();
}
}
// Check consistency of tabs and crs void MathedIter::checkTabs()
{
ipush();
// MathedIter:Reset(); while (OK()) { if ((IsTab() && col>=ncols-1) || (IsCR() && !(MthIF_CR&flags))) { Delete(); continue;
} if (IsCR() && col<ncols-2) {
Insert(' ', LM_TC_TAB);
}
MathedIter::Next();
} if (col<ncols-2) {
Insert(' ', LM_TC_TAB);
}
ipop();
}
// Try to adjust tabs in the expected place, as used in eqnarrays // Rules: // - If there are a relation operator, put tabs around it // - If tehre are not a relation operator, put everything in the // 3rd column. void MathedIter::adjustTabs()
{
}
void MathedXIter::Clean(int pos2)
{ if (!array) {
fprintf(stderr, "Math error: Attempting to clean a void array.\n"); return;
}
int pos1 = pos;
if (pos2<pos1) {
GoBegin(); while (pos<pos2 && OK()) { Next();
}
pos2 = pos1;
pos1 = pos;
}
ipush(); while (OK() && pos<pos2) { if (IsInset()) {
MathedInset* inset = GetInset();
Next(); if (inset->GetType()!=LM_OT_MACRO_ARG) delete inset; continue;
} if (IsCR()) { if (crow) {
MathedRowSt *r = crow->next; if (r) {
crow->next = r->next; delete r;
}
}
}
Next();
}
ipop();
if (pos2<=array->Last()) {
pos = pos1;
join(pos2);
checkTabs();
}
}
void MathedXIter::Merge(LyxArrayBase *a0)
{ if (!a0) {
lyxerr.debug("Math error: Attempting to merge a void array.",
Error::MATHED); return;
} // All insets must be clonned
MathedIter it(a0);
LyxArrayBase *a = it.Copy();
// make rom for the data
split(a->Last());
array->MergeF(a, pos, a->Last());
void MathedXIter::SetData(MathParInset *pp)
{
p = pp;
x = y = 0;
array = p->GetData();
ncols = p->GetColumns();
crow = p->getRowSt(); if (p->Permit(LMPF_ALLOW_CR))
flags |= MthIF_CR; if (p->Permit(LMPF_ALLOW_TAB))
flags |= MthIF_Tabs;
if (crow) {
x = crow->getTab(0);
y = crow->getBaseline();
} if (!array) {
array = new LyxArrayBase; // this leaks
p->SetData(array);
}
size = p->GetStyle();
Reset();
}
int pos2 = pos; // pos1
GoBegin(); do {
ipush();
Next();
} while (pos<pos2);
ipop();
return (!IsCR());
}
bool MathedXIter::goNextColumn()
{ int rowp = row, colp=col; while (Next() && col==colp);
return (col!=colp+1 || rowp!=row);
}
bool MathedXIter::Up()
{ if (row==0) returnfalse; int xp = x, rowp = row, colp=col;
GoBegin(); while (row<rowp-1) Next(); while (x<xp && OK() && !IsCR()) {
ipush();
Next();
} if (col>colp) // || (stck.col==colp && stck.x<=xp && x>xp))
ipop();
returntrue;
}
bool MathedXIter::Down()
{ int xp = x, colp=col; // ,rowp = row
bool res = (IsCR()) ? true: goNextCode(LM_TC_CR); if (res) {
Next();
ipush(); while (x<xp && OK()) {
ipush();
Next();
} if (col>colp || (stck.col==colp && stck.x<=xp && x>xp))
ipop(); returntrue;
} returnfalse;
}
void MathedXIter::addRow()
{ if (!crow) {
lyxerr.debug(LString("MathErr: Attempt to insert new" " line in a subparagraph. ")
+ long(this), Error::MATHED); return;
} // Create new item for the structure
MathedRowSt *r = new MathedRowSt(ncols+1); if (crow) {
r->next = crow->next;
crow->next = r;
} else {
crow = r;
r->next = 0;
} // Fill missed tabs in current row while (col<ncols-1)
Insert('T', LM_TC_TAB); //newline
Insert('K', LM_TC_CR);
ipush(); if (!IsCR())
goNextCode(LM_TC_CR);
// Fill missed tabs in new row while (col<ncols-1)
Insert('T', LM_TC_TAB);
ipop();
}
void MathedXIter::delRow()
{ if (!crow) {
lyxerr.debug("MathErr: Attempt to delete a line in a subparagraph.",
Error::MATHED); return;
} bool line_empty = true;
ipush(); // while (Next()) { do { if (IsCR()){ break;
} elseif (!IsTab()) {
line_empty = false;
}
} while (Next()); int p1 = getPos();
ipop();
void MathedXIter::ipop()
{
MathedIter::ipop();
x = stck.x;
y = stck.y; if (p) {
crow = p->getRowSt(); if (crow) for (int i=0; i<row; i++)
crow = crow->next;
}
}
void MathedXIter::fitCoord(int/*xx*/, int yy)
{ int xo = 0, yo = 0;
GoBegin(); if (p)
p->GetXY(xo, yo); // first fit vertically while (crow && OK()) { if (yy>=yo+y-crow->asc && yy<= yo+y+crow->desc) break;
goNextCode(LM_TC_CR);
Next();
} // now horizontally // while (x<xx && Next());
}
void MathedXIter::setTab(int tx, int tab)
{ if (crow && tab<=ncols) {
crow->w[tab] = tx;
} else
fprintf(stderr, "MathErr: No tabs allowed here");
}
void MathedXIter::subMetrics(int a, int d)
{ if (!crow) { // fprintf(stderr, "MathErr: Attempt to submetric a subparagraph."); return;
}
crow->asc = a;
crow->desc = d;
}
// This function is not recursive, as MathPar::Metrics is void MathedXIter::IMetrics(int pos2, int& width, int& ascent, int& descent)
{
byte cx, cxp=0;// *s; int x1;// ls; int asc=0, des=0; bool limits = false;
descent = ascent = width = 0; if (!array) return; if (array->Empty()) return; // if (pos2 > array->last) return;
x1 = x; while (pos<pos2) {
cx = GetChar(); if (cx >= ' ') {
mathed_char_height(FCode(), size, cx, asc, des); if (asc > ascent) ascent = asc; if (des > descent) descent = des;
limits = false;
} else if (MathIsInset(cx)) {
MathedInset *pp = GetInset(); if (cx==LM_TC_UP) { if (!asc && p) { int xx, yy;
p->GetXY(xx, yy);
((MathParInset*)pp)->GetXY(xx, asc);
asc = yy - asc;
}
asc += ((limits) ? pp->Height()+4: pp->Ascent());
} else if (cx==LM_TC_DOWN) { if (!des && p) { int xx, yy;
p->GetXY(xx, yy);
((MathParInset*)pp)->GetXY(xx, des); if (des-pp->Height()<yy && !asc)
asc = yy - (des-pp->Height());
des -= yy;
}
des += ((limits) ? pp->Height()+4: pp->Height()-pp->Ascent()/2);
} else {
asc = pp->Ascent();
des = pp->Descent();
} if (asc > ascent) ascent = asc; if (des > descent) descent = des; if (cx!=LM_TC_UP && cx!=LM_TC_DOWN)
limits = pp->GetLimits();
} else if (cx==LM_TC_TAB) {
limits = false;
} else {
lyxerr.debug(LString("Mathed Sel-Error: Unrecognized code[")
+ int(cx) + ']', Error::MATHED); break;
} if (pos<pos2) Next();
cxp = cx;
}
width = x - x1;
}
bool MathedXIter::setNumbered(bool numb)
{ if (crow) {
crow->setNumbered(numb); returntrue;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.