// text.cpp - Text's implementation of functions

// NOTE ABOUT TEXTMASK: + marks superscript, - marks subscript
// B marks bold, I marks italic, U marks underline

#include <qobject.h>
#include <iostream>
#include <math.h>
#include <qrect.h>
#include <qfont.h>
#include <qnamespace.h>
#include <qtextstream.h>

using std::cout;
using std::endl;

#include "render2d.h"
#include "drawable.h"
#include "text.h"
#include "defs.h"

Text::Text(Render2D *r1, QObject *parent, const char *name)
  : Drawable(parent, name)
{
  r = r1;
  font = QFont("Helvetica", 12);  // CHANGE BACK TO 12
  highlighted = false;
  shiftdown = false;
  cursor = 0;
  selectMin = -1; selectMax = -1;
  bfont = font;
  bfont.setWeight(QFont::Bold);
  ifont = font;
  ifont.setItalic(true);
  ufont = font;
  ufont.setUnderline(true);
  molecule = 0;
  DataType = TEXT_DATA_NORMAL;

  bold=false;
  italic=false;
  underline=false;
  super=false;
  sub=false;
}

QString Text::ToXML(QString xml_id) {
  QString s, n1;
  int fsize;
  fsize = font.pointSize();
  if (fsize < 1) fsize = font.pixelSize();

  // begin text
  s.append("<text id=");
  s.append(xml_id);
  s.append(">\n");

  // write Start
  s.append("<Start>");
  n1.setNum(start->x);
  s.append(n1);
  s.append(" ");
  n1.setNum(start->y);
  s.append(n1);
  s.append("</Start>\n");

  // write text
  s.append("<textstring>");
  s.append(text);
  s.append("</textstring>\n");

  // write textmask
  s.append("<textmask>");
  s.append(textmask);
  s.append("</textmask>\n");

  // write color
  s.append("<color>");
  n1.setNum(color.red());
  s.append(n1);
  s.append(" ");
  n1.setNum(color.green());
  s.append(n1);
  s.append(" ");
  n1.setNum(color.blue());
  s.append(n1);
  s.append("</color>\n");

  // write font
  s.append("<font>");
  s.append(font.family());
  s.append(QString("#"));
  n1.setNum(fsize);
  s.append(n1);
  s.append("</font>\n");

  // end arrow
  s.append("</text>\n");

  return s;
}

QString Text::ToCDXML(QString xml_id) {
  QString s, n1;

  // begin text
  s.append("<t id=\"");
  s.append(xml_id);
  s.append("\" p=\"");
  n1.setNum(start->x);
  s.append(n1);
  s.append(" ");
  n1.setNum(start->y);
  s.append(n1);
  s.append("\"><s font=\"21\" size=\"10\" face=\"96\">");
  s.append(text);
  s.append("</s></t>\n");

  return s;
}

void Text::FromXML(QString xml_tag) {
  int i1, i2;

  i1 = xml_tag.find("<Start>");
  i2 = xml_tag.find("</Start>") + 8;
  SetStartFromXML(xml_tag.mid(i1, i2 - i1));
  i1 = xml_tag.find("<color>");
  if (i1 >= 0) {
    i2 = xml_tag.find("</color>") + 8;
    SetColorFromXML(xml_tag.mid(i1, i2 - i1));
  }
  i1 = xml_tag.find("<font>");
  if (i1 >= 0) {
    i2 = xml_tag.find("</font>") + 7;
    SetFontFromXML(xml_tag.mid(i1, i2 - i1));
  }
  i1 = xml_tag.find("<textstring>");
  i2 = xml_tag.find("</textstring>") + 13;
  SetTextstringFromXML(xml_tag.mid(i1, i2 - i1));
  i1 = xml_tag.find("<textmask>");
  i2 = xml_tag.find("</textmask>") + 11;
  SetTextmaskFromXML(xml_tag.mid(i1, i2 - i1));
}

// convert XML <font> tag to QFont and set current
void Text::SetFontFromXML(QString xml_tag) {
  cout << "SetFontFromXML:" << xml_tag << endl;
  int i1, i2;
  //int d1, d2, d3;

  i1 = xml_tag.find("<font>");
  i2 = xml_tag.find("</font>");
  xml_tag.remove(i2, 999);
  xml_tag.remove(i1, 6);
  i1 = xml_tag.find("#");
  cout << xml_tag.mid(0, i1) << "*" << xml_tag.mid(i1 + 1) << endl;
  font = QFont(xml_tag.mid(0, i1), xml_tag.mid(i1 + 1).toInt());
}

// get Text::text from <textstring> tag
void Text::SetTextstringFromXML(QString xml_tag) {
  cout << "SetTextstringFromXML:" << xml_tag << endl;
  int i1, i2;
  //int d1, d2, d3;

  i1 = xml_tag.find("<textstring>");
  i2 = xml_tag.find("</textstring>");
  xml_tag.remove(i2, 999);
  xml_tag.remove(i1, 12);
  text = xml_tag;
}

// get Text::textmask from <textmask> tag
void Text::SetTextmaskFromXML(QString xml_tag) {
  cout << "SetTextmaskFromXML:" << xml_tag << endl;
  int i1, i2;
  //int d1, d2, d3;

  i1 = xml_tag.find("<textmask>");
  i2 = xml_tag.find("</textmask>");
  xml_tag.remove(i2, 999);
  xml_tag.remove(i1, 10);
  textmask = xml_tag;
}

bool Text::WithinRect(QRect n, bool shiftdown) {
  if ( DPointInRect(start, n) )
    highlighted = true;
  else
    highlighted = false;
  return highlighted;
}

void Text::Render(void)
{
  UpdateDisplayText();
  int supersub = r->GetTextHeight(font) / 2;
  QFont supersubfont = subscriptFont(font);
  int subx = r->GetTextHeight(supersubfont) / 2;
  QColor drawcolor;
  if (highlighted)
    drawcolor = QColor(255,0,0);
  else
    drawcolor = color;
  QRect b = r->GetTextDimensions(displayText, font);
  QPoint t = GetTopLeftPoint();
  b.moveBy( t.x(), t.y() );
  r->drawFillBox(b.topLeft(), b.bottomRight(), r->getBGColor(), false,
		 QColor(0,0,0), 1);
  QPoint curpos(t.x(), t.y() + r->GetTextHeight(font));
  bool smaller_font = false;

  int i;
  for (i = 0; i < displayText.length(); i++) {
    if ((int)QChar(displayText[i]) == 10) {
      curpos.setX(t.x());
      curpos.setY(curpos.y() + r->GetTextFullHeight(font));
      continue;
    }
    if (displayTextMask[i] == ' ')
      r->drawText(displayText[i], curpos, drawcolor, font);
    if (displayTextMask[i] == 'B')
      r->drawText(displayText[i], curpos, drawcolor, bfont);
    if (displayTextMask[i] == 'I')
      r->drawText(displayText[i], curpos, drawcolor, ifont);
    if (displayTextMask[i] == 'U')
      r->drawText(displayText[i], curpos, drawcolor, ufont);
    if (displayTextMask[i] == '+') {
      r->drawText(displayText[i], QPoint(curpos.x(), curpos.y()-supersub), 
		  drawcolor, supersubfont);
      smaller_font = true;
    }
    if (displayTextMask[i] == '-') {
      r->drawText(displayText[i], QPoint(curpos.x(), curpos.y()+subx), 
		  drawcolor, supersubfont);
      smaller_font = true;
    }
    if (smaller_font == true)
      curpos.setX(curpos.x() + r->GetCharWidth(displayText[i], supersubfont));
    else
      curpos.setX(curpos.x() + r->GetCharWidth(displayText[i], font));
    smaller_font = false;
  }
}

void Text::EditRender(void)
{
  int supersub = r->GetTextHeight(font) / 2;
  QFont supersubfont = subscriptFont(font);
  int subx = r->GetTextHeight(supersubfont) / 2;
  QRect b = r->GetTextDimensions(text, font);
  // determine top left point, and start drawing there.
  QPoint t = GetTopLeftPoint();
  b.moveBy( t.x(), t.y() );
  b.setLeft(b.left() - 2); b.setRight(b.right() + 3);
  b.setTop(b.top() - 1); b.setBottom(b.bottom() + 1);
  r->drawFillBox(b.topLeft(), b.bottomRight(), r->getBGColor(), true,
		   QColor(0,0,0), 1);
  QPoint curpos(t.x(), t.y() + r->GetTextHeight(font));
  int i, cnt = 0;
  bool smaller_font = false;
  for (i = 0; i < text.length(); i++) {
    if ((int)QChar(text[i]) == 10) {
      cnt++;
      curpos.setX(t.x());
      curpos.setY(curpos.y() + r->GetTextFullHeight(font));
      continue;
    }
    if ( (cnt < selectMin) || (cnt > selectMax) ) {
      if (textmask[i] == ' ')
	r->drawText(text[i], curpos, color, font);
      if (textmask[i] == 'B')
	r->drawText(text[i], curpos, color, bfont);
      if (textmask[i] == 'I')
	r->drawText(text[i], curpos, color, ifont);
      if (textmask[i] == 'U')
	r->drawText(text[i], curpos, color, ufont);
      if (textmask[i] == '+') {
	r->drawText(text[i], QPoint(curpos.x(), curpos.y()-supersub), 
		    color, supersubfont);
	smaller_font = true;
      }
      if (textmask[i] == '-') {
	r->drawText(text[i], QPoint(curpos.x(), curpos.y()+subx), 
		    color, supersubfont);
	smaller_font = true;
      }
    } else {
      if (textmask[i] == ' ')
	r->drawTextReverse(text[i], curpos, color, font);
      if (textmask[i] == 'B')
	r->drawTextReverse(text[i], curpos, color, bfont);
      if (textmask[i] == 'I')
	r->drawTextReverse(text[i], curpos, color, ifont);
      if (textmask[i] == 'U')
	r->drawTextReverse(text[i], curpos, color, ufont);
      if (textmask[i] == '+') {
	r->drawTextReverse(text[i], QPoint(curpos.x(), curpos.y()-supersub), 
			   color, supersubfont);
	smaller_font = true;
      }
      if (textmask[i] == '-') {
	r->drawTextReverse(text[i], QPoint(curpos.x(), curpos.y()+subx), 
			   color, supersubfont);
	smaller_font = true;
      }
    }
    cnt++;
    if (smaller_font == true)
      curpos.setX(curpos.x() + r->GetCharWidth(text[i], supersubfont));
    else
      curpos.setX(curpos.x() + r->GetCharWidth(text[i], font));
    smaller_font = false;
    //curpos.setX(curpos.x() + r->GetCharWidth(text[i], font));
  }
  // determine cursor position
  int lx = t.x(), ly = 1;
  for (i = 0; i < cursor; i++) {
    if ((int)QChar(text[i]) == 10) {
      lx = t.x();
      ly++;
    } else {
      lx = lx + r->GetCharWidth(text[i], font);
    }
  }
  ly = t.y() + ((ly - 1) * r->GetTextFullHeight(font)) +
    r->GetTextHeight(font);
  r->drawLine(QPoint(lx, ly), QPoint(lx, ly - r->GetTextHeight(font)), 1,
	      QColor(0,0,0));
}

int Text::Type(void)
{
  return TYPE_TEXT;
}

bool Text::Find(DPoint *target) {
  //if (start == target) return true;
  return false;
}

DPoint * Text::FindNearestPoint(DPoint *target, double &dist) {
  dist = 99999.0;
  return 0;
}

Drawable * Text::FindNearestObject(DPoint *target, double &dist) {
  if (WithinBounds(target))
    dist = 0.01;
  else
    dist = 99999.0;
  return this;
}

void Text::setPoint(DPoint *s) {
  start = s;
}

bool Text::WithinBounds(DPoint *target) {
  QRect b = r->GetTextDimensions(text, font);
  QPoint t = GetTopLeftPoint();
  b.moveBy( t.x(), t.y() );
  if ( (target->x > b.left()) && (target->x < b.right()) &&
       (target->y > b.top()) && (target->y < b.bottom()) )
    return true;
  else
    return false;
}

QRect Text::BoundingBox() {
  if (highlighted == false)
    return QRect( QPoint(999,999), QPoint(0,0) ); 
  QRect b = r->GetTextDimensions(text, font);
  QPoint t = GetTopLeftPoint();
  b.moveBy( t.x(), t.y() );
  return b;
}

// return nearest center point to m (see ChemData::AutoLayout)
QPoint Text::NearestCenter(QPoint m, int di, int &ns) {
  QRect b = r->GetTextDimensions(text, font);
  QPoint t = GetTopLeftPoint();
  b.moveBy( t.x(), t.y() );
  QPoint c1, cmin;
  double dist = 9999.0, ndist;
  if (di == ARROW_VERTICAL) {
    c1.setX(b.left());
    c1.setY(b.center().y());
    ndist = DistanceBetween(m, c1);
    if (ndist < dist) { cmin = c1; dist = ndist; ns = TEXT_LEFT; }
    c1.setX(b.right());
    c1.setY(b.center().y());
    ndist = DistanceBetween(m, c1);
    if (ndist < dist) { cmin = c1; dist = ndist; ns = TEXT_RIGHT; }
  } else { // ARROW_HORIZONTAL
    c1.setX(b.center().x());
    c1.setY(b.top());
    ndist = DistanceBetween(m, c1);
    if (ndist < dist) { cmin = c1; dist = ndist; ns = TEXT_TOP; }
    c1.setX(b.center().x());
    c1.setY(b.bottom());
    ndist = DistanceBetween(m, c1);
    if (ndist < dist) { cmin = c1; dist = ndist; ns = TEXT_BOTTOM; }
  }
  return cmin;
}

void Text::InsertCharacter(QKeyEvent *k1) {
  // if shift pressed, start new selection
  if (k1->state() == ShiftButton) {
    if (shiftdown == false) {
      shiftdown = true;
      selectMin = cursor;
      selectMax = cursor - 1;
      cout << cursor << "-" << selectMin << "-" << selectMax << endl;
    } else {
      shiftdown = true;
    }
  } else {
    shiftdown = false;
  }
  
  // if return pressed, add newline only if JUSTIFY_TOPLEFT (not a label)
  if ( (k1->key() == Key_Return) && (justify == JUSTIFY_CENTER) ) return;

  if (k1->key() == Key_Return) {
    cout << "Return" << endl;
    text.insert(cursor, (char)10);
    start->element = text;
    textmask.insert(cursor, (char)10);
    cursor++;
    return;
  }
  // if left or right arrow pressed with shift, make or extend new selection
  if ( (k1->key() == Key_Left) && shiftdown) {
    cout << cursor << "-" << selectMin << "-" << selectMax << endl;
    if (selectMin > 0) {
      if (cursor > selectMin)
	selectMax--;
      else
	selectMin--;
    }
    if (cursor > 0) cursor--;
    return;
  }
  if ( (k1->key() == Key_Right) && shiftdown) {
    cout << cursor << "-" << selectMin << "-" << selectMax << endl;
    if (selectMax < text.length()) {
      if (cursor <= selectMax)
	selectMin++;
      else
	selectMax++;
    }
    if (cursor < text.length()) cursor++;
    return;
  }
  // if Home or End pressed with shift, make or extend new selection
  if ( (k1->key() == Key_Home) && shiftdown) {
    cout << cursor << "-" << selectMin << "-" << selectMax << endl;
    if (selectMin > 0) {
      if (cursor > selectMin)
	selectMax--;
      else
	selectMin = 0;
    }
    if (cursor > 0) cursor = 0;
    return;
  }
  if ( (k1->key() == Key_End) && shiftdown) {
    cout << cursor << "-" << selectMin << "-" << selectMax << endl;
    if (selectMax < text.length()) {
      if (cursor <= selectMax)
	selectMin++;
      else
	selectMax = text.length();
    }
    if (cursor < text.length()) cursor = text.length();
    return;
  }
  // if left or right arrow pressed w/o shift, clear selection
  if (k1->key() == Key_Left) {
    if (cursor > 0) cursor--;
    selectMin = -1; selectMax = -1;
    return;
  }
  if (k1->key() == Key_Right) {
    if (cursor < text.length()) cursor++;
    selectMin = -1; selectMax = -1;
    return;
  }
  // if Home or End was pressed, go home or end
  if (k1->key() == Key_Home) {
    if (cursor > 0) cursor = 0;
    selectMin = -1; selectMax = -1;
    return;
  }
  if (k1->key() == Key_End) {
    if (cursor < text.length()) cursor = text.length();
    selectMin = -1; selectMax = -1;
    return;
  }
  if (k1->key() == Key_Backspace) {
    if (cursor == 0) return;
    if (selectMin >= 0) { // something selected
      text.remove(selectMin, selectMax - selectMin + 1);
      textmask.remove(selectMin, selectMax - selectMin + 1);
      start->element = text;
      cursor = selectMin;
      selectMin = -1, selectMax = -1;
      return;
    }
    text.remove(cursor - 1, 1);
    start->element = text;
    textmask.remove(cursor - 1, 1);
    cursor--;
    return;
  }

  // if key > 96 and not already handled, ignore (letters/numbers/space < 96)
  if (k1->key() > 96) return;
  // regular letter/number pressed
  text.insert(cursor, k1->text());
  start->element = text;
  QChar mask;
  if(bold)
    mask='B';
  else if(italic)
    mask='I';
  else if(underline)
    mask='U';
  else if(super)
    mask='+';
  else if(sub)
    mask='-';
  else //everythign else is false
    mask=' ';
  textmask.insert(cursor, mask);     //(Adam)
  cursor++;
}

// Superscript selected text
void Text::DoSuperscript() {
  //if (selectMin < 0) return;
  for (int i = selectMin; i < selectMax+1; i++) {
    if (textmask[i] == ' ') {
      textmask[i] = '+';
      continue;
    }
    /*if (textmask[i] == '+') {
      textmask[i] = ' ';
      continue;
    }*/
    if (textmask[i] == '-') {
      textmask[i] = '+';
      continue;
    }
  }
  super=true;
}

void Text::DoUnSuperscript() {
  //if (selectMin < 0) return;
  for (int i = selectMin; i < selectMax+1; i++) {
    /*if (textmask[i] == ' ') {
      textmask[i] = '+';
      continue;
    }*/
    if (textmask[i] == '+') {
      textmask[i] = ' ';
      continue;
    }
    /*if (textmask[i] == '-') {
      textmask[i] = '+';
      continue;
    }*/
  }
  super=false;
}

// Subscript selected text
void Text::DoSubscript() {
  //if (selectMin < 0) return;
  for (int i = selectMin; i < selectMax+1; i++) {
    if (textmask[i] == ' ') {
      textmask[i] = '-';
      continue;
    }
    if (textmask[i] == '+') {
      textmask[i] = '-';
      continue;
    }
    /*if (textmask[i] == '-') {
      textmask[i] = ' ';
      continue;
    }*/
  }
  sub=true;
}

void Text::DoUnSubscript() {
  //if (selectMin < 0) return;
  for (int i = selectMin; i < selectMax+1; i++) {
    /*if (textmask[i] == ' ') {
      textmask[i] = '-';
      continue;
    }
    if (textmask[i] == '+') {
      textmask[i] = '-';
      continue;
    }*/
    if (textmask[i] == '-') {
      textmask[i] = ' ';
      continue;
    }
  }
  sub=false;
}

// Bold selected text
void Text::DoBold() {
  //if (selectMin < 0) return;
  for (int i = selectMin; i < selectMax+1; i++) {
    if (textmask[i] == ' ') {
      textmask[i] = 'B';
      continue;
    }
    /*if (textmask[i] == 'B') {
      textmask[i] = ' ';
      continue;
    }*/
  }
  std::cerr << "Setting bold to true" << std::endl;
  bold=true;
}

void Text::DoUnBold() {
  //if (selectMin < 0) return;
  for (int i = selectMin; i < selectMax+1; i++) {
    /*if (textmask[i] == ' ') {
      textmask[i] = 'B';
      continue;
    }*/
    if (textmask[i] == 'B') {
      textmask[i] = ' ';
      continue;
    }
  }
  bold=false;
}

// Italicize selected text
void Text::DoItalic() {
  //if (selectMin < 0) return;
  for (int i = selectMin; i < selectMax+1; i++) {
    if (textmask[i] == ' ') {
      textmask[i] = 'I';
      continue;
    }
    /*if (textmask[i] == 'I') {
      textmask[i] = ' ';
      continue;
    }*/
  }
  italic=true;
}

void Text::DoUnItalic() {
  //if (selectMin < 0) return;
  for (int i = selectMin; i < selectMax+1; i++) {
    /*if (textmask[i] == ' ') {
      textmask[i] = 'I';
      continue;
    }*/
    if (textmask[i] == 'I') {
      textmask[i] = ' ';
      continue;
    }
  }
  italic=false;
}


// Underline selected text
void Text::DoUnderline() {
  //if (selectMin < 0) return;
  for (int i = selectMin; i < selectMax+1; i++) {
    if (textmask[i] == ' ') {
      textmask[i] = 'U';
      continue;
    }
    /*if (textmask[i] == 'U') {
      textmask[i] = ' ';
      continue;
    }*/
  }
  underline=true;
}

void Text::DoUnUnderline() {
  //if (selectMin < 0) return;
  for (int i = selectMin; i < selectMax+1; i++) {
    /*if (textmask[i] == ' ') {
      textmask[i] = 'U';
      continue;
    }*/
    if (textmask[i] == 'U') {
      textmask[i] = ' ';
      continue;
    }
  }
  underline=false;
}

// move cursor to target
void Text::MoveCursor(DPoint *target) {
  selectMin = -1; selectMax = -1;
  double mindist = 99999.0, ldist;
  int newcur=0;
  DPoint *e = new DPoint;
  cout << "Move" << endl;
  if (WithinBounds(target) == false) return;
  QPoint t = GetTopLeftPoint();
  int lx = t.x(), ly = t.y() + (r->GetTextFullHeight(font) / 2);
  for (int i = 0; i < text.length(); i++) {
    e->x = lx; e->y = ly;
    ldist = e->distanceTo(target);
    if (ldist < mindist) { mindist = ldist; newcur = i; }
    if ((int)QChar(text[i]) == 10) {
      lx = t.x();
      ly = ly + r->GetTextFullHeight(font);
    } else {
      lx = lx + r->GetCharWidth(text[i], font);
    }
  }
  cursor = newcur;
  delete e;
}

// Select text between endpoints e1 and e2
void Text::Select(DPoint *e1, DPoint *e2) {
  if (WithinBounds(e1) == false) return;
  if (WithinBounds(e2) == false) return;
  cout << "select" << endl;
  double mindist = 99999.0, ldist;
  int newcur=0;
  int cr1 = 0, cr2 = 0;
  QPoint t;
  int i, lx, ly;
  DPoint *e = new DPoint;
  t = GetTopLeftPoint();
  lx = t.x(); ly = t.y() + (r->GetTextFullHeight(font) / 2);
  for (i = 0; i < text.length(); i++) {
    e->x = lx; e->y = ly;
    ldist = e->distanceTo(e1);
    if (ldist < mindist) { mindist = ldist; newcur = i; }
    if ((int)QChar(text[i]) == 10) {
      cr1++;
      lx = t.x();
      ly = ly + r->GetTextFullHeight(font);
    } else {
      lx = lx + r->GetCharWidth(text[i], font);
    }
  }
  selectMin = newcur;
  mindist = 99999.0;
  t = GetTopLeftPoint();
  lx = t.x(); ly = t.y() + (r->GetTextFullHeight(font) / 2);
  for (i = 0; i < text.length(); i++) {
    e->x = lx; e->y = ly;
    ldist = e->distanceTo(e2);
    if (ldist < mindist) { mindist = ldist; newcur = i; }
    if ((int)QChar(text[i]) == 10) {
      cr2++;
      lx = t.x();
      ly = ly + r->GetTextFullHeight(font);
    } else {
      lx = lx + r->GetCharWidth(text[i], font);
    }
  }
  selectMax = newcur;
  if (selectMin > selectMax) { 
    int swp = selectMin;
    selectMin = selectMax;
    selectMax = swp - 1;
  }
  std::cout << selectMin << " " << selectMax << std::endl;

  bool hasBold=false;
  bool hasItalic=false;
  bool hasUnderline=false;
  bool hasSuperscript=false;
  bool hasSubscript=false;

  for(int i=selectMin;i<=selectMax;i++) {

     if(textmask[i]=='B')
        hasBold=true;
     if(textmask[i]=='I')
        hasItalic=true;
     if(textmask[i]=='U')
        hasUnderline=true;
     if(textmask[i]=='+')
        hasSuperscript=true;
     if(textmask[i]=='-')
        hasSubscript=true;
  }

  emit signalHasBold(hasBold);
  emit signalHasItalic(hasItalic);
  emit signalHasUnderline(hasUnderline);
  emit signalHasSuperscript(hasSuperscript);
  emit signalHasSubscript(hasSubscript);

}

/* ORIGINAL GetTopLeftPoint() (version < 0.99.2)
QPoint Text::GetTopLeftPoint(void) {
  if(justify == JUSTIFY_TOPLEFT) {
    return start->toQPoint();
  } else {
    QPoint a;
    QRect b = r->GetTextDimensions(text, font);
    a.setX(start->x - b.width() / 2);
    a.setY(start->y - b.height() / 2);
    return a;
  }
}
*/

QPoint Text::GetTopLeftPoint(void) {
  bool leftcenter = true;
  if(justify == JUSTIFY_TOPLEFT) {
    return start->toQPoint();
  } else {
    QPoint a;
    QRect b = r->GetTextDimensions(text, font);
    // center on first or last character.  Try to guess what user intended
    // (a dangerous idea at best :)
    if ( (text.left(1) == "H") && 
	 (text.length() > 1) ) leftcenter = false;
    if ( (text.left(1) == "+") && 
	 (text.length() > 1) ) leftcenter = false;
    if ( (text.left(1) == "-") && 
	 (text.length() > 1) ) leftcenter = false;
    if ( text.at(0).isNumber() == true) leftcenter = false;
    if (text == "HO") leftcenter = false;
    if (text == "O2N") leftcenter = false;
    // E.g., "MeO", "AcO", other protecting groups, connect to O on right
    if (text.right(1) == "O") leftcenter = false;
    // unless...
    if (text == "CO") leftcenter = true;
    if (text == "SO") leftcenter = true;
    // this may not work as well as checking for "O"
    if (text.upper().contains("T") == 0)
      if (text.right(1) == "S") leftcenter = false;
    if (leftcenter) {
      int lc = r->GetCharWidth(text.at(0), font);
      a.setX(start->x - lc / 2);
    } else {
      int rc = r->GetCharWidth(text.at(text.length() - 1), font);
      a.setX(start->x - b.width() + rc / 2);
    }
    a.setY(start->y - b.height() / 2);
    return a;
  }
}

// position atom labels according to hindrance
void Text::CheckAlignment(int alignside) {
  // 1 = left, 2 = right
  whichside = alignside;
}

// find next smaller font for subscripts
QFont Text::subscriptFont(QFont f_in) {
  QFont f_out = f_in;

  if (f_out.pointSize() > 1) 
    f_out.setPointSize(f_out.pointSize() - 2);
  else
    f_out.setPixelSize(f_out.pixelSize() - 2);

  return f_out;
}

Drawable * Text::DeepCopy() {
  Text *np = new Text(r);
  DPoint *s1 = new DPoint(start);
  np->setPoint(s1);
  np->setText(getText());
  np->setTextMask(getTextMask());
  np->SetColor(GetColor());
  np->setFont(getFont());
  np->setJustify(Justify());
  if (highlighted) np->Highlight(true);
  return np;
}

void Text::UpdateDisplayText() {
  // decide how to display the text string
  if (whichside == 1) {
    displayText = text;
    displayTextMask = textmask;
    return;
  }
  // create right-aligned version.
  displayText = text;
  displayTextMask = textmask;
}


#include "text.moc"