#include "warning.h"
#include "length.h"
#include "terminal.h"
#include "exc.H"
#include "axis.h"
#include <iostream>
#include <new>
#include <cmath>
#include <cstdio>
#include <stdlib.h>
namespace blop
{
int &length::initializer::count()
{
static int c = 0;
return c;
}
length::initializer::initializer()
{
if(count()++ == 0)
{
new(&ZERO) length(base_id_t(terminal::ZERO));
new(&PW) length(base_id_t(terminal::PW));
new(&PH) length(base_id_t(terminal::PH));
new(&PS) length(base_id_t(terminal::PS));
new(&LW) length(base_id_t(terminal::LW));
new(&CM) length(base_id_t(terminal::CM));
new(&MM) length(base_id_t(terminal::MM));
new(&PT) length(base_id_t(terminal::PT));
new(&EM) length(base_id_t(terminal::EM));
new(&EX) length(base_id_t(terminal::EX));
}
}
length::initializer::~initializer()
{
if(--count() == 0)
{
}
}
std::vector<length::base_t *> length::registered_entries_;
int &length::base_t::count()
{
static int c = 0;
return c;
}
ostream &operator<<(ostream &out,const length::base_t &l)
{
l.print(out);
return out;
}
length::base_t::base_t()
: termspecific_id_(0),reference_count(0)
{
++count();
}
length::base_t::base_t(const length::base_t &other)
: termspecific_id_(other.termspecific_id_), reference_count(0)
{
++count();
}
length::base_t::~base_t()
{
--count();
}
void length::base_t::reset() {termspecific_id_ = 0;}
bool length::base_t::specialized() const
{
return termspecific_id_ != 0;
}
terminal::id length::base_t::termspecific_id() const {return termspecific_id_;}
void length::base_t::termspecific_id(int i) {termspecific_id_ = i;}
length::base_max_t::~base_max_t()
{
for(unsigned int i=0; i<lengths_.size(); ++i)
{
if(--(lengths_[i]->reference_count) == 0)
{
(const_cast<length::base_t *>(lengths_[i]))->~base_t();
length::deallocate(lengths_[i]);
}
}
}
length::base_max_t::base_max_t(const length::base_max_t &o)
{
for(unsigned int i=0; i<o.lengths_.size(); ++i)
{
void *ptr = length::allocate();
length::base_t *p = o.lengths_[i]->clone(ptr);
p->reference_count = 1;
lengths_.push_back(p);
}
}
void length::base_max_t::print(ostream &out) const
{
out<<"max(";
for(unsigned int i=0; i<lengths_.size(); ++i)
{
if(i > 0) out<<",";
lengths_[i]->print(out);
}
out<<")";
}
length::base_t *length::base_max_t::clone(void *ptr) const
{
return new(ptr) length::base_max_t(lengths_);
}
length::base_max_t::base_max_t(const std::vector<blop::length::base_t *> &v)
{
for(unsigned int i=0; i<v.size(); ++i)
{
void *ptr = length::allocate();
length::base_t *p = v[i]->clone(ptr);
p->reference_count = 1;
lengths_.push_back(p);
}
}
void length::base_max_t::dependencies(std::vector<blop::length::base_t *> *v) const
{
for(unsigned int c=0; c<lengths_.size(); ++c)
{
bool found = false;
for(unsigned int i=0; i<v->size(); ++i)
{
if((*v)[i] == lengths_[c])
{
found = true;
break;
}
}
if(!found) v->push_back(lengths_[c]);
}
}
bool length::base_max_t::depends_on(length::base_t *l) const
{
for(unsigned int i=0; i<lengths_.size(); ++i)
{
if(lengths_[i] == l) return true;
if(lengths_[i]->depends_on(l)) return true;
}
return false;
}
bool length::base_max_t::specialize(terminal *term)
{
if(lengths_.empty())
{
termspecific_id(terminal::ZERO);
return true;
}
vector<terminal::id> length_ids;
for(unsigned int i=0; i<lengths_.size(); ++i)
{
if(lengths_[i] == 0)
{
warning::print("0 pointer","length::base_max_t::specialize");
continue;
}
if(!lengths_[i]->specialized())
{
if(!lengths_[i]->specialize(term)) return false;
}
length_ids.push_back(lengths_[i]->termspecific_id());
}
termspecific_id(term->maxlength(length_ids));
return true;
}
length::base_min_t::~base_min_t()
{
for(unsigned int i=0; i<lengths_.size(); ++i)
{
if(--(lengths_[i]->reference_count) == 0)
{
(const_cast<length::base_t *>(lengths_[i]))->~base_t();
length::deallocate(lengths_[i]);
}
}
}
length::base_min_t::base_min_t(const length::base_min_t &o)
{
for(unsigned int i=0; i<o.lengths_.size(); ++i)
{
void *ptr = length::allocate();
length::base_t *p = o.lengths_[i]->clone(ptr);
p->reference_count = 1;
lengths_.push_back(p);
}
}
void length::base_min_t::print(ostream &out) const
{
out<<"min(";
for(unsigned int i=0; i<lengths_.size(); ++i)
{
if(i > 0) out<<",";
lengths_[i]->print(out);
}
out<<")";
}
length::base_t *length::base_min_t::clone(void *ptr) const
{
return new(ptr) length::base_min_t(lengths_);
}
length::base_min_t::base_min_t(const std::vector<blop::length::base_t *> &v)
{
for(unsigned int i=0; i<v.size(); ++i)
{
void *ptr = length::allocate();
length::base_t *p = v[i]->clone(ptr);
p->reference_count = 1;
lengths_.push_back(p);
}
}
void length::base_min_t::dependencies(std::vector<blop::length::base_t *> *v) const
{
for(unsigned int c=0; c<lengths_.size(); ++c)
{
bool found = false;
for(unsigned int i=0; i<v->size(); ++i)
{
if((*v)[i] == lengths_[c])
{
found = true;
break;
}
}
if(!found) v->push_back(lengths_[c]);
}
}
bool length::base_min_t::depends_on(length::base_t *l) const
{
for(unsigned int i=0; i<lengths_.size(); ++i)
{
if(lengths_[i] == l) return true;
if(lengths_[i]->depends_on(l)) return true;
}
return false;
}
bool length::base_min_t::specialize(terminal *term)
{
if(lengths_.empty())
{
termspecific_id(terminal::ZERO);
return true;
}
vector<terminal::id> length_ids;
for(unsigned int i=0; i<lengths_.size(); ++i)
{
if(lengths_[i] == 0)
{
warning::print("0 pointer","length::base_min_t::specialize");
continue;
}
if(!lengths_[i]->specialized())
{
if(!lengths_[i]->specialize(term)) return false;
}
length_ids.push_back(lengths_[i]->termspecific_id());
}
termspecific_id(term->minlength(length_ids));
return true;
}
length::base_axis_t::base_axis_t(axis *a,double v1,double v2)
{
axis_ = a;
value1_ = v1;
value2_ = v2;
}
bool length::base_axis_t::specialize(terminal *t)
{
if(axis_->begin().specialized() == false && axis_->begin().specialize(t) == false) return false;
if(axis_->end() .specialized() == false && axis_->end() .specialize(t) == false) return false;
double d;
if(value2_ != unset)
{
d = axis_->map_point(value2_) - axis_->map_point(value1_);
}
else
{
d = axis_->map_point(value1_);
}
termspecific_id(t->lincombi(-d,axis_->begin().termspecific_id(),
d,axis_->end().termspecific_id()));
return true;
}
length::base_t *length::base_axis_t::clone(void *ptr) const
{
return new(ptr) length::base_axis_t(axis_,value1_,value2_);
}
void length::base_axis_t::print(ostream &out) const
{
if(value2_ != unset)
{
out<<"SOMEAXIS("<<value1_<<","<<value2_<<")";
}
else
{
out<<"SOMEAXIS("<<value1_<<")";
}
}
void length::base_axis_t::dependencies(std::vector<blop::length::base_t *> *v) const
{
v->push_back(axis_->begin().length_base_ptr_);
v->push_back(axis_->end().length_base_ptr_);
}
bool length::base_axis_t::depends_on(length::base_t *l) const
{
if(l == axis_->begin().length_base_ptr_ ||
l == axis_->end().length_base_ptr_) return true;
if(axis_->begin().length_base_ptr_->depends_on(l)) return true;
if(axis_->end().length_base_ptr_->depends_on(l)) return true;
return false;
}
void length::base_ref_t::dependencies
(std::vector<blop::length::base_t *> *v) const
{
bool found = false;
for(unsigned int i=0; i<v->size(); ++i)
{
if((*v)[i] == the_length_)
{
found = true;
break;
}
}
if(!found) v->push_back(the_length_);
}
bool length::base_ref_t::depends_on(length::base_t *l) const
{
if(l == the_length_) return true;
if(the_length_->depends_on(l)) return true;
return false;
}
length::base_ref_t::base_ref_t(const length::base_ref_t &other)
: the_length_(other.the_length_)
{
++(the_length_->reference_count);
}
length::base_ref_t::base_ref_t(length::base_t *o)
: the_length_(o)
{
++(o->reference_count);
}
length::base_ref_t::~base_ref_t()
{
if(--(the_length_->reference_count) == 0)
{
(const_cast<length::base_t *>(the_length_))->~base_t();
length::deallocate(the_length_);
}
}
bool length::base_ref_t::specialized() const
{
return the_length_->specialized();
}
terminal::id length::base_ref_t::termspecific_id() const
{
return the_length_->termspecific_id();
}
bool length::base_ref_t::specialize(terminal *t)
{
return the_length_->specialize(t);
}
length::base_t *length::base_ref_t::clone(void *ptr) const
{
return new(ptr) length::base_ref_t(*this);
}
void length::base_ref_t::print(ostream &out) const
{
the_length_->print(out);
}
void length::base_scaleable_t::dependencies(std::vector<blop::length::base_t *> *v) const
{
if(the_length_) v->push_back(the_length_);
}
bool length::base_scaleable_t::depends_on(length::base_t *l) const
{
if(the_length_ == 0) return false;
if(l == the_length_) return true;
if(the_length_->depends_on(l)) return true;
return false;
}
length::base_scaleable_t::base_scaleable_t(double factor)
{
factor_ = factor;
the_length_ = 0;
}
length::base_scaleable_t::base_scaleable_t(const length::base_scaleable_t &o)
{
factor_ = o.factor_;
if(o.the_length_)
{
void *ptr = length::allocate();
the_length_ = o.the_length_->clone(ptr);
}
else
{
the_length_ = 0;
}
}
length::base_scaleable_t::~base_scaleable_t()
{
if(the_length_)
{
(const_cast<length::base_t *>(the_length_))->~base_t();
length::deallocate(the_length_);
}
}
bool length::base_scaleable_t::specialize(terminal *t)
{
if(the_length_ == 0)
{
warning::print("The scale is not set for a scaleable length",
"length::base_scaleable_t::specialize(...)");
termspecific_id(terminal::ZERO);
return true;
}
if(!the_length_->specialized())
{
if(the_length_->specialize(t) == false)
{
return false;
}
}
termspecific_id(t->lincombi(factor_,the_length_->termspecific_id()));
return true;
}
length::base_t *length::base_scaleable_t::clone(void *ptr) const
{
base_t *result = new(ptr) length::base_scaleable_t(*this);
return result;
}
void length::base_scaleable_t::print(ostream &out) const
{
out<<factor_<<"*(";
if(the_length_ == 0) out<<"NULL";
else the_length_->print(out);
out<<")";
}
void length::base_scaleable_t::set_scale(length::base_t *s)
{
if(the_length_ == 0)
{
void *ptr = length::allocate();
the_length_ = s->clone(ptr);
}
else
{
if(s->depends_on(the_length_))
{
warning::print("Recursive definition of a length",
"base_scaleable_t::set_scale(length::base_t *)");
return;
}
(const_cast<length::base_t *>(the_length_))->~base_t();
s->clone(the_length_);
}
}
length::base_id_t::base_id_t(const length::base_id_t &o)
{
termspecific_id_ = o.termspecific_id_;
}
length::base_id_t::base_id_t(int i)
{
termspecific_id_ = i;
if(termspecific_id_ < terminal::ZERO ||
termspecific_id_ >= terminal::NOF_UNITS)
{
warning::print("Bad id","length::base_id_t::base_id_t(int)");
termspecific_id_ = terminal::ZERO;
}
}
length::base_t *length::base_id_t::clone(void *placement) const
{
return new(placement) length::base_id_t(*this);
}
void length::base_id_t::print(ostream &out) const
{
const char *unitname[terminal::NOF_UNITS];
for(int i=0; i<terminal::NOF_UNITS; ++i) unitname[i] = "???";
unitname[terminal::ZERO] = "ZERO";
unitname[terminal::PW ] = "PW";
unitname[terminal::PH ] = "PH";
unitname[terminal::PS ] = "PS";
unitname[terminal::LW ] = "LW";
unitname[terminal::CM ] = "CM";
unitname[terminal::MM ] = "MM";
unitname[terminal::PT ] = "PT";
unitname[terminal::EM ] = "EM";
unitname[terminal::EX ] = "EX";
if(termspecific_id_ < terminal::ZERO ||
termspecific_id_ >= terminal::NOF_UNITS)
{
out<<"["<<termspecific_id_<<"]";
}
else
{
out<<unitname[termspecific_id_];
}
}
length::base_textsize_t::base_textsize_t(
const length::base_textsize_t &other)
{
angle_ = other.angle_;
text_ = other.text_;
direction_ = other.direction_;
termspecific_id_ = other.termspecific_id_;
}
length::base_textsize_t::base_textsize_t(const string &s,
int dir,double an)
: angle_(an),text_(s), direction_(dir) {}
bool length::base_textsize_t::specialize(terminal *t)
{
if(direction_ == horizontal)
termspecific_id(t->textwidth (text_,angle_));
if(direction_ == vertical )
termspecific_id(t->textheight(text_,angle_));
return true;
}
void length::base_textsize_t::text(const string &s)
{
text_ = s;
}
void length::base_textsize_t::angle(double a)
{
angle_ = a;
}
void length::base_textsize_t::print(ostream &out) const
{
if(direction_ == horizontal) out<<"width(\""<<text_<<"\")";
else out<<"height(\""<<text_<<"\")";
}
length::base_textwidth_t::base_textwidth_t(const string &s,
double angle)
: base_textsize_t(s,horizontal,angle) {}
length::base_t *length::base_textwidth_t::clone(void *placement) const
{
return new(placement) length::base_textwidth_t(text_,angle_);
}
length::base_textheight_t::base_textheight_t(const string &s,
double angle)
: base_textsize_t(s,vertical,angle) {}
length::base_t *length::base_textheight_t::clone(void *placement) const
{
return new(placement) length::base_textheight_t(text_,angle_);
}
length_temporary width(const var &s,double angle)
{
return length::base_textwidth_t(s.str(),angle);
}
length_temporary height(const var &s,double angle)
{
return length::base_textheight_t(s.str(),angle);
}
void length::base_max_textsize_t::add(const string &s)
{
texts_.push_back(s);
}
length::base_max_textsize_t::base_max_textsize_t(
const length::base_max_textsize_t &other)
: texts_(other.texts_)
{
}
length::base_max_textsize_t::base_max_textsize_t(const std::vector<std::string> &v)
: texts_(v)
{
termspecific_id_ = 0;
}
void length::base_max_textsize_t::clear()
{
texts_.clear();
}
length::base_max_textwidth_t::base_max_textwidth_t() {}
length::base_max_textwidth_t::base_max_textwidth_t(const base_max_textwidth_t &other)
: base_max_textsize_t(other)
{
}
length::base_max_textwidth_t::base_max_textwidth_t (const vector<string> &s)
: base_max_textsize_t(s)
{
}
bool length::base_max_textwidth_t::specialize(terminal *t)
{
termspecific_id(t->max_textwidth(texts_));
return true;
}
length::base_t *length::base_max_textwidth_t::clone(void *ptr) const
{
return new(ptr) length::base_max_textwidth_t(*this);
}
void length::base_max_textwidth_t::print(ostream &out) const
{
out<<"maxwidth(";
for(vector<var>::size_type i=0; i<texts_.size(); ++i)
{
if(i > 0) out<<",";
out<<"\""<<texts_[i]<<"\"";
}
out<<")";
}
length::base_max_textheight_t::base_max_textheight_t() {}
length::base_max_textheight_t::base_max_textheight_t(const base_max_textheight_t &other)
: base_max_textsize_t(other)
{
}
length::base_max_textheight_t::base_max_textheight_t (const vector<string> &s)
: base_max_textsize_t(s)
{
}
bool length::base_max_textheight_t::specialize(terminal *t)
{
termspecific_id(t->max_textheight(texts_));
return true;
}
length::base_t *length::base_max_textheight_t::clone(void *ptr) const
{
return new(ptr) length::base_max_textheight_t(*this);
}
void length::base_max_textheight_t::print(ostream &out) const
{
out<<"maxheight(";
for(vector<string>::size_type i=0; i<texts_.size(); ++i)
{
if(i > 0) out<<",";
out<<"\""<<texts_[i]<<"\"";
}
out<<")";
return;
}
length::base_max_textlheight_t::base_max_textlheight_t() {}
length::base_max_textlheight_t::base_max_textlheight_t(const base_max_textlheight_t &other)
: base_max_textsize_t(other)
{
}
length::base_max_textlheight_t::base_max_textlheight_t (const vector<string> &s)
: base_max_textsize_t(s)
{
}
bool length::base_max_textlheight_t::specialize(terminal *t)
{
termspecific_id(t->max_textlheight(texts_));
return true;
}
length::base_t *length::base_max_textlheight_t::clone(void *ptr) const
{
return new(ptr) length::base_max_textlheight_t(*this);
}
void length::base_max_textlheight_t::print(ostream &out) const
{
out<<"maxlheight(";
for(vector<string>::size_type i=0; i<texts_.size(); ++i)
{
if(i > 0) out<<",";
out<<"\""<<texts_[i]<<"\"";
}
out<<")";
return;
}
length_temporary maxwidth (const std::vector<std::string> &s)
{
length::base_max_textwidth_t mmm(s);
return mmm;
}
length_temporary maxwidth (const std::vector<blop::var> &s)
{
vector<string> v;
for(unsigned int i=0; i<s.size(); ++i) v.push_back(s[i].str());
length::base_max_textwidth_t mmm(v);
return mmm;
}
length_temporary maxwidth (const std::vector<blop::tic> &s)
{
vector<string> v;
for(unsigned int i=0; i<s.size(); ++i) v.push_back(s[i].label().str());
length::base_max_textwidth_t mmm(v);
return mmm;
}
length_temporary maxheight(const vector<var> &s)
{
vector<string> v;
for(unsigned int i=0; i<s.size(); ++i) v.push_back(s[i].str());
length::base_max_textheight_t mmm(v);
return mmm;
}
length_temporary maxlheight(const vector<var> &s)
{
vector<string> v;
for(unsigned int i=0; i<s.size(); ++i) v.push_back(s[i].str());
length::base_max_textlheight_t mmm(v);
return mmm;
}
length_temporary length::max(vector<blop::length> &v)
{
vector<blop::length::base_t *> vv;
for(unsigned int i=0; i<v.size(); ++i)
{
vv.push_back(v[i].length_base_ptr_);
}
length::base_max_t mmm(vv);
return mmm;
}
length_temporary length::max(const length &l1, const length &l2)
{
vector<blop::length> v;
v.push_back(l1);
v.push_back(l2);
return length::max(v);
}
length_temporary length::max(const length &l1, const length &l2, const length &l3)
{
vector<blop::length> v;
v.push_back(l1);
v.push_back(l2);
v.push_back(l3);
return length::max(v);
}
length_temporary length::min(vector<blop::length> &v)
{
vector<blop::length::base_t *> vv;
for(unsigned int i=0; i<v.size(); ++i)
{
vv.push_back(v[i].length_base_ptr_);
}
length::base_min_t mmm(vv);
return mmm;
}
length_temporary length::min(const length &l1, const length &l2)
{
vector<blop::length> v;
v.push_back(l1);
v.push_back(l2);
return length::min(v);
}
length_temporary length::min(const length &l1, const length &l2, const length &l3)
{
vector<blop::length> v;
v.push_back(l1);
v.push_back(l2);
v.push_back(l3);
return length::min(v);
}
void length::base_lincombi_t::set_scale(length::base_t *s)
{
for(unsigned int i=0; i<lengths_.size(); ++i)
{
lengths_[i]->set_scale(s);
}
}
void length::base_lincombi_t::dependencies(
vector<length::base_t *> *v) const
{
for(unsigned int c=0; c<lengths_.size(); ++c)
{
bool found = false;
for(unsigned int i=0; i<v->size(); ++i)
{
if((*v)[i] == lengths_[c])
{
found = true;
break;
}
}
if(!found) v->push_back(lengths_[c]);
}
}
bool length::base_lincombi_t::depends_on(length::base_t *l) const
{
for(unsigned int i=0; i<lengths_.size(); ++i)
{
if(l == lengths_[i]) return true;
if(lengths_[i]->depends_on(l)) return true;
}
return false;
}
length::base_lincombi_t::base_lincombi_t() {}
length::base_lincombi_t::base_lincombi_t(const length::base_lincombi_t &other)
{
factors_ = other.factors_;
lengths_ = other.lengths_;
for(vector<const length::base_t *>::size_type i=0; i<lengths_.size(); ++i)
{
++(lengths_[i]->reference_count);
}
termspecific_id_ = other.termspecific_id_;
reference_count = 0;
}
length::base_lincombi_t::base_lincombi_t(double factor, length::base_t *b)
{
factors_.push_back(factor);
lengths_.push_back(b);
++(b->reference_count);
termspecific_id_ = 0;
reference_count = 0;
}
void length::base_lincombi_t::print(ostream &out) const
{
if(factors_.empty())
{
out<<"ZERO";
return;
}
for(vector<double>::size_type i=0; i<factors_.size(); ++i)
{
bool lincombi = (dynamic_cast<const length::base_lincombi_t*>(lengths_[i]) != 0 ||
dynamic_cast<const length::base_ref_t *>(lengths_[i]) != 0 );
if(factors_[i] != 1)
{
if(i>0)
{
if(factors_[i] >= 0) out<<" + "<<factors_[i];
else out<<" - "<<-factors_[i];
}
else
{
out<<factors_[i];
}
out<<"*";
}
else
{
if(i > 0) out<<" + ";
}
if(factors_[i] != 1 && lincombi) out<<"(";
lengths_[i]->print(out);
if(factors_[i] != 1 && lincombi) out<<")";
}
}
bool length::base_lincombi_t::specialize(terminal *t)
{
if(lengths_.empty())
{
termspecific_id(terminal::ZERO);
return true;
}
vector<terminal::id> length_ids;
for(vector<double>::size_type i = 0; i<lengths_.size(); ++i)
{
if(lengths_[i] == 0)
{
warning::print("0 pointer","length_lincombi::specialize");
exit(0);
}
if(!lengths_[i]->specialized())
{
if(!lengths_[i]->specialize(t)) return false;
}
length_ids.push_back(lengths_[i]->termspecific_id());
}
termspecific_id(t->lincombi(factors_,length_ids));
return true;
}
void length::base_lincombi_t::add(double f,length::base_t *l)
{
if(::fabs(f) < 0.001) return;
if(dynamic_cast<base_id_t *>(l))
{
if(l->termspecific_id() == terminal::ZERO) return;
}
for(unsigned int i=0; i<lengths_.size(); ++i)
{
if(lengths_[i] == l)
{
factors_[i] += f;
return;
}
}
factors_.push_back(f);
lengths_.push_back(l);
++(l->reference_count);
}
void length::base_lincombi_t::multiply(double f)
{
for(vector<double>::size_type i=0; i<factors_.size(); ++i)
{
factors_[i] *= f;
}
}
length::base_lincombi_t::~base_lincombi_t()
{
for(vector<double>::size_type i=0; i<lengths_.size(); ++i)
{
if(--(lengths_[i]->reference_count) == 0)
{
(const_cast<length::base_t *>(lengths_[i]))->~base_t();
length::deallocate(lengths_[i]);
}
}
}
length::base_t *length::base_lincombi_t::clone(void *placement) const
{
return new(placement) length::base_lincombi_t(*this);
}
length::~length()
{
--(length_base_ptr_->reference_count);
if(length_base_ptr_->reference_count == 0)
{
length_base_ptr_->~base_t();
deallocate(length_base_ptr_);
}
}
length::length(const char *)
{
locked_ = false;
}
length::length(length::base_t *l)
{
length_base_ptr_ = l;
++(length_base_ptr_->reference_count);
locked_ = false;
}
length::length(const length::base_t &l)
{
void *ptr = allocate();
length_base_ptr_ = l.clone(ptr);
length_base_ptr_ -> reference_count = 1;
locked_ = false;
}
length::length(double factor)
{
void *ptr = allocate();
if(factor == 0)
{
length_base_ptr_ = new(ptr) length::base_id_t(terminal::ZERO);
}
else if(factor == unset)
{
length_base_ptr_ = new(ptr) length::base_unset_t;
}
else
{
length_base_ptr_ = new(ptr) length::base_scaleable_t(factor);
}
length_base_ptr_->reference_count = 1;
locked_ = false;
}
length::length(const length &l)
{
void *ptr = allocate();
length_base_ptr_ = l.length_base_ptr_->clone(ptr);
length_base_ptr_->reference_count = 1;
locked_ = false;
}
void length::set_scale(const length &scale)
{
if(length_base_ptr_ == 0)
{
warning::print("0 pointer","length::set_scale");
return;
}
length_base_ptr_->set_scale(scale.length_base_ptr_);
locked_ = false;
}
const length &length::operator= (const length &l)
{
if(&l == this) return *this;
if(locked_)
{
warning::print("Length locked","length::operator=(const length &)");
return *this;
}
if(l.length_base_ptr_->depends_on(length_base_ptr_))
{
warning::print("Recursive definition of a length",
"length::operator=(const length &)");
return *this;
}
int ref_count = length_base_ptr_->reference_count;
length_base_ptr_->~base_t();
l.length_base_ptr_->clone(length_base_ptr_);
length_base_ptr_->reference_count = ref_count;
return *this;
}
const length &length::operator= (double factor)
{
if(locked_)
{
warning::print("Length locked","length::operator=(double)");
return *this;
}
int ref_count = length_base_ptr_ -> reference_count;
length_base_ptr_ -> ~base_t();
if(factor != 0)
{
new(length_base_ptr_) base_scaleable_t(factor);
}
else
{
new(length_base_ptr_) base_id_t(terminal::ZERO);
}
length_base_ptr_ -> reference_count = ref_count;
return *this;
}
void length::operator+= (const length &l)
{
if(locked_)
{
warning::print("Length locked","length::operator+=(const length &)");
return;
}
if(l.length_base_ptr_->depends_on(length_base_ptr_))
{
warning::print("Recursive definition of a length",
"length::operator+= (const length &)");
return;
}
if(base_lincombi_t *t
= dynamic_cast<base_lincombi_t *>(length_base_ptr_))
{
t->add(1,l.clone_base());
}
else
{
void *ptr = allocate();
base_t *old = length_base_ptr_->clone(ptr);
length_base_ptr_->~base_t();
base_lincombi_t *new_lincombi = new(length_base_ptr_) base_lincombi_t;
new_lincombi->add(1.0,old);
new_lincombi->add(1.0,l.clone_base());
}
}
void length::operator-= (const length &l)
{
if(locked_)
{
warning::print("Length locked","length::operator-=(const length &)");
return;
}
if(l.length_base_ptr_->depends_on(length_base_ptr_))
{
warning::print("Recursive definition of a length",
"length::operator-= (const length &)");
return;
}
if(base_lincombi_t *t
= dynamic_cast<base_lincombi_t *>(length_base_ptr_))
{
t->add(-1,l.clone_base());
}
else
{
void *ptr = allocate();
base_t *old = length_base_ptr_->clone(ptr);
length_base_ptr_->~base_t();
base_lincombi_t *new_lincombi = new(length_base_ptr_) base_lincombi_t;
new_lincombi->add(1.0,old);
new_lincombi->add(-1.0,l.clone_base());
}
}
void length::operator*= (double f)
{
if(locked_)
{
warning::print("Length locked","length::operator*=(const length &)");
return;
}
if(base_lincombi_t *t = dynamic_cast<base_lincombi_t *>(length_base_ptr_))
{
t->multiply(f);
}
else if(base_scaleable_t *t = dynamic_cast<base_scaleable_t *>(length_base_ptr_))
{
t->factor_ *= f;
}
else
{
void *ptr = allocate();
base_t *old = length_base_ptr_->clone(ptr);
length_base_ptr_->~base_t();
base_lincombi_t *new_lincombi = new(length_base_ptr_) base_lincombi_t;
new_lincombi->add(f,old);
}
}
void length::operator /= (double f)
{
if(locked_)
{
warning::print("Length locked","length::operator/=(const length &)");
return;
}
if(base_lincombi_t *t = dynamic_cast<base_lincombi_t *>(length_base_ptr_))
{
t->multiply(1.0/f);
}
else if(base_scaleable_t *t = dynamic_cast<base_scaleable_t *>(length_base_ptr_))
{
t->factor_ *= 1.0/f;
}
else
{
void *ptr = allocate();
base_t *old = length_base_ptr_->clone(ptr);
length_base_ptr_->~base_t();
base_lincombi_t *new_lincombi = new(length_base_ptr_) base_lincombi_t;
new_lincombi->add(1.0/f,old);
}
}
int length::specialize(terminal *t) const
{
length::base_t *ppp = const_cast<base_t *>(length_base_ptr_);
return ppp->specialize(t);
}
bool length::specialized() const
{
return length_base_ptr_->specialized();
}
terminal::id length::termspecific_id() const
{
return length_base_ptr_->termspecific_id();
}
length::base_t *length::clone_base() const
{
void *ptr = allocate();
base_t *result = length_base_ptr_->clone(ptr);
return result;
}
bool length::initialized() const
{
return (dynamic_cast<base_unset_t *>(length_base_ptr_) == 0);
}
length_temporary::length_temporary(const length::base_t &l)
{
l.clone(length_base_ptr_);
length_base_ptr_->reference_count = 1;
}
length_temporary::length_temporary(length::base_t *l)
: length(l)
{
}
length_temporary::length_temporary(const length &l)
{
length *ll = const_cast<length *>(&l);
ll->length_base_ptr_->clone(length_base_ptr_);
length_base_ptr_->reference_count = 1;
}
length::base_t *length_temporary::clone_base() const
{
return length_base_ptr_;
}
length length::operator! () const
{
return base_ref_t(length_base_ptr_);
}
void length::print(ostream &out) const
{
if(length_base_ptr_ == 0) out<<"!NULLPOINTER!";
length_base_ptr_->print(out);
}
ostream &operator<< (ostream &out, const length &l)
{
l.print(out);
return out;
}
length ZERO("do nothing");
length PW ("do nothing");
length PH ("do nothing");
length PS ("do nothing");
length LW ("do nothing");
length CM ("do nothing");
length MM ("do nothing");
length PT ("do nothing");
length EM ("do nothing");
length EX ("do nothing");
void *length::allocate()
{
static unsigned int s = 0;
if(s == 0)
{
if(s < sizeof(length::base_ref_t)) s = sizeof(length::base_ref_t);
if(s < sizeof(length::base_textwidth_t)) s = sizeof(length::base_textwidth_t);
if(s < sizeof(length::base_textheight_t)) s = sizeof(length::base_textheight_t);
if(s < sizeof(length::base_max_textwidth_t)) s = sizeof(length::base_max_textwidth_t);
if(s < sizeof(length::base_max_textheight_t)) s = sizeof(length::base_max_textheight_t);
if(s < sizeof(length::base_lincombi_t)) s = sizeof(length::base_lincombi_t);
if(s < sizeof(length::base_id_t)) s = sizeof(length::base_id_t);
if(s < sizeof(length::base_max_t)) s = sizeof(length::base_max_t);
if(s < sizeof(length::base_scaleable_t)) s = sizeof(length::base_scaleable_t);
}
void *ptr = new char[s];
return ptr;
}
void length::deallocate(const length::base_t *p)
{
delete [] ((char*)p);
}
length_temporary operator+ (const length &l1,const length &l2)
{
length::base_t *l1base = l1.clone_base();
length::base_t *l2base = l2.clone_base();
length::base_lincombi_t *lc1 =
dynamic_cast<length::base_lincombi_t *>(l1base);
length::base_lincombi_t *lc2 =
dynamic_cast<length::base_lincombi_t *>(l2base);
length::base_lincombi_t *result = 0;
if(lc1)
{
result = lc1;
if(lc2)
{
for(unsigned int i=0; i<lc2->factors_.size(); ++i)
{
result->add(lc2->factors_[i],lc2->lengths_[i]);
}
}
else
{
result->add(1.0, l2base);
}
}
else if(lc2)
{
result = lc2;
result->add(1.0, l1base);
}
else
{
void *ptr = length::allocate();
result = new(ptr) length::base_lincombi_t;
result->add(1.0, l1base);
result->add(1.0, l2base);
}
return result;
}
length_temporary operator- (const length &l)
{
return -1*l;
}
length_temporary operator- (const length &l1,const length &l2)
{
length::base_t *l1base = l1.clone_base();
length::base_t *l2base = l2.clone_base();
length::base_lincombi_t *lc1
= dynamic_cast<length::base_lincombi_t *>(l1base);
length::base_lincombi_t *lc2
= dynamic_cast<length::base_lincombi_t *>(l2base);
length::base_lincombi_t *result = 0;
if(lc1)
{
if(lc2)
{
for(unsigned int i=0; i<lc2->factors_.size(); ++i)
{
lc1->add(-lc2->factors_[i],lc2->lengths_[i]);
}
}
else
{
lc1->add(-1.0, l2base);
}
result = lc1;
}
else if(lc2)
{
lc2->multiply(-1);
lc2->add(1.0, l1base);
result = lc2;
}
else
{
void *ptr = length::allocate();
result = new(ptr) length::base_lincombi_t;
result->add(1.0, l1base);
result->add(-1.0, l2base);
}
return result;
}
length_temporary operator* (double f,const length &l)
{
length::base_t *lbase = l.clone_base();
length::base_lincombi_t *lc =
dynamic_cast<length::base_lincombi_t *>(lbase);
if(lc)
{
lc->multiply(f);
return lc;
}
void *ptr = length::allocate();
lc = new(ptr) length::base_lincombi_t;
lc->add(f,lbase);
return lc;
}
length_temporary operator* (const length &l,double f)
{
length::base_t *lbase = l.clone_base();
length::base_lincombi_t *lc =
dynamic_cast<length::base_lincombi_t *>(lbase);
if(lc)
{
lc->multiply(f);
return lc;
}
void *ptr = length::allocate();
lc = new(ptr) length::base_lincombi_t;
lc->add(f,lbase);
return lc;
}
length_temporary operator/ (const length &l,double f)
{
length::base_t *lbase = l.clone_base();
length::base_lincombi_t *lc =
dynamic_cast<length::base_lincombi_t *>(lbase);
if(lc)
{
lc->multiply(1.0/f);
return lc;
}
void *ptr = length::allocate();
lc = new(ptr) length::base_lincombi_t;
lc->add(1.0/f,lbase);
return lc;
}
bool length::depends_on(const length &l) const
{
return length_base_ptr_->depends_on(l.length_base_ptr_);
}
void length::register_me() const
{
registered_entries_.push_back(length_base_ptr_);
}
void length::clear_regs()
{
registered_entries_.clear();
}
void length::detect_deadlock()
{
for(unsigned int i=0; i<registered_entries_.size(); ++i)
{
registered_entries_[i]->print(cout);
cout<<endl;
}
}
void length::specialize_regs(terminal *term)
TRY
{
for(unsigned int i=0; i<registered_entries_.size(); ++i)
{
registered_entries_[i]->dependencies(®istered_entries_);
}
for(unsigned int i=0; i<registered_entries_.size(); ++i)
{
registered_entries_[i]->reset();
}
bool everything_ok = false;
while(!everything_ok)
{
everything_ok = true;
int success = 0;
for(unsigned int i=0; i<registered_entries_.size(); ++i)
{
if(!registered_entries_[i]->specialized())
{
if(!registered_entries_[i]->specialize(term))
{
everything_ok = false;
}
else
{
++success;
}
}
}
if(!everything_ok && !success)
{
err("Failed to do anything");
}
}
}
CATCH("length::specialize_regs")
length_temporary lincombi(double factor,int id)
{
return length::base_lincombi_t(factor,new length::base_id_t(id));
}
}