lyx_mirror/src/mathed/array.C

386 lines
6.3 KiB
C++
Raw Normal View History

#include <config.h>
#ifdef __GNUG__
#pragma implementation
#endif
#include "debug.h"
#include "array.h"
#include "math_iter.h"
#include "math_inset.h"
#include "math_macro.h"
#include "support/LOstream.h"
using std::ostream;
using std::endl;
#ifndef CXX_GLOBAL_CSTD
using std::memmove;
#endif
namespace {
inline
void * my_memcpy(void * ps_in, void const * pt_in, size_t n)
{
char * ps = static_cast<char *>(ps_in);
char const * pt = static_cast<char const *>(pt_in);
while (n--) *ps++ = *pt++;
return ps_in;
}
} // namespace anon
MathedArray::MathedArray()
: bf_(1, '\0'), last_(0)
{}
MathedArray::~MathedArray()
{
// deep destruction
// let's leak for a while...
/*
MathedIter it;
it.SetData(this);
while (it.OK()) {
if (it.IsInset()) {
MathedInset * inset = it.GetInset();
delete inset;
}
it.Next();
}
*/
}
MathedArray::MathedArray(MathedArray const & array)
{
// this "implementation" is obviously wrong: MathedIter should be
// implemented by MathedArray (not the other way round) but I think
// getting the _interface_ of MathedArray right is more important right
// now (Andre')
// shallow copy
bf_ = array.bf_;
last_ = array.last_;
// deep copy
deep_copy();
}
void MathedArray::deep_copy()
{
MathedIter it(this);
while (it.OK()) {
if (it.IsInset()) {
MathedInset * inset = it.GetInset();
inset = inset->Clone();
raw_pointer_insert(inset, it.getPos() + 1);
}
it.Next();
}
}
void MathedArray::substitute(MathMacro * m)
{
if (m->nargs() == 0)
return;
MathedIter it(this);
while (it.OK()) {
if (it.IsInset()) {
MathedInset * inset = it.GetInset();
if (inset->GetType() == LM_OT_MACRO_ARG) {
int n = static_cast<MathMacroArgument *>(inset)->number() - 1;
//lyxerr << "substituting an argument inset: " << n << "\n";
inset = m->arg(n)->Clone();
} else {
inset->substitute(m);
/*
if (it.IsActive()) {
MathParInset * pinset = static_cast<MathParInset *>(inset);
int n = pinset->getMaxArgumentIdx();
int idx = pinset->getArgumentIdx();
for (int i = 0; i <= n; ++i) {
pinset->setArgumentIdx(i);
pinset->GetData().substitute(m);
}
pinset->setArgumentIdx(idx);
}
*/
//lyxerr << "substituting in an ordinary inset\n";
}
raw_pointer_insert(inset, it.getPos() + 1);
}
it.Next();
}
}
MathedArray & MathedArray::operator=(MathedArray const & array)
{
MathedArray tmp(array);
swap(tmp);
return *this;
}
void MathedArray::push_back(MathedInset * inset, int t)
{
MathedIter it(this);
while (it.Next())
;
it.insertInset(inset, t);
}
void MathedArray::push_back(byte b, MathedTextCodes c)
{
MathedIter it(this);
while (it.Next())
;
it.insert(b, c);
}
void MathedArray::clear()
{
last_ = 0;
bf_.resize(1);
bf_[0] = 0;
}
void MathedArray::swap(MathedArray & array)
{
if (this != &array) {
bf_.swap(array.bf_);
std::swap(last_, array.last_);
}
}
MathedArray::iterator MathedArray::begin()
{
return bf_.begin();
}
MathedArray::iterator MathedArray::end()
{
return bf_.end();
}
MathedArray::const_iterator MathedArray::begin() const
{
return bf_.begin();
}
MathedArray::const_iterator MathedArray::end() const
{
return bf_.end();
}
int MathedArray::empty() const
{
return (last_ == 0);
}
int MathedArray::last() const
{
return last_;
}
void MathedArray::last(int l)
{
last_ = l;
}
void MathedArray::need_size(int needed)
{
if (needed >= static_cast<int>(bf_.size()))
resize(needed);
}
void MathedArray::resize(int newsize)
{
// still a bit smelly...
++newsize;
bf_.resize(newsize + 1);
if (last_ >= newsize)
last_ = newsize - 1;
bf_[last_] = 0;
}
void MathedArray::move(int p, int shift)
{
if (p <= last_) {
need_size(last_ + shift);
memmove(&bf_[p + shift], &bf_[p], last_ - p);
last_ += shift;
bf_[last_] = 0;
}
}
void MathedArray::shrink(int pos1, int pos2)
{
if (pos1 == 0 && pos2 >= last())
return;
short fc = 0;
if (pos1 > 0 && bf_[pos1] > ' ') {
for (int p = pos1; p >= 0; --p) {
if (MathIsFont(bf_[p])) {
if (p != pos1 - 1)
fc = bf_[p];
else
--pos1;
break;
}
}
}
if (pos2 > 0 && bf_[pos2] >= ' ' && MathIsFont(bf_[pos2 - 1]))
--pos2;
int dx = pos2 - pos1;
MathedArray a;
a.resize(dx + 1);
strange_copy(&a, (fc) ? 1 : 0, pos1, dx);
if (fc) {
a[0] = fc;
++dx;
}
a.last(dx);
a[dx] = '\0';
swap(a);
deep_copy();
}
#if 0
void MathedArray::insert(MathedArray::iterator pos,
MathedArray::const_iterator beg,
MathedArray::const_iterator end)
{
bf_.insert(pos, beg, end);
last_ = bf_.size() - 1;
}
#else
void MathedArray::merge(MathedArray const & a, int p)
{
my_memcpy(&bf_[p], &a.bf_[0], a.last());
}
#endif
void MathedArray::raw_pointer_copy(MathedInset ** p, int pos) const
{
my_memcpy(p, &bf_[pos], sizeof(MathedInset*));
}
#if 0
void MathedArray::insertInset(int pos, MathedInset * p, int type)
{
//bf_.insert(pos, type);
InsetTable tmp(pos, p);
insetList_.push_back(tmp);
}
MathedInset * MathedArray::getInset(int pos)
{
InsetList::const_iterator cit = insetList_.begin();
InsetList::const_iterator end = insetList_.end();
for (; cit != end; ++cit) {
if ((*cit).pos == pos)
return (*cit).inset;
}
// not found
return 0;
// We would really like to throw an exception instead... (Lgb)
// throw inset_not_found();
}
#else
void MathedArray::raw_pointer_insert(void * p, int pos)
{
my_memcpy(&bf_[pos], &p, sizeof(p));
}
#endif
void MathedArray::strange_copy(MathedArray * dest, int dpos,
int spos, int len)
{
my_memcpy(&dest->bf_[dpos], &bf_[spos], len);
}
byte MathedArray::operator[](int i) const
{
return bf_[i];
}
byte & MathedArray::operator[](int i)
{
return bf_[i];
}
void MathedArray::dump2(ostream & os) const
{
buffer_type::const_iterator cit = bf_.begin();
buffer_type::const_iterator end = bf_.end();
for (; cit != end; ++cit) {
os << (*cit);
}
os << endl;
}
void MathedArray::dump(ostream & os) const
{
MathedIter it( const_cast<MathedArray*>(this) );
while (it.OK()) {
if (it.IsInset()) {
MathedInset * inset = it.GetInset();
os << "<inset: " << inset << ">";
}
else if (it.IsTab())
os << "<tab>";
else if (it.IsCR())
os << "<cr>";
else if (it.IsScript())
os << "<script>";
else if (it.IsFont())
os << "<font: " << int(it.at()) << ">";
else if (it.at() >= 32 && it.at() < 127)
os << it.at();
else
os << "<unknown: " << int(it.at()) << ">";
it.Next();
}
}