/* ====================================================================
 * Copyright (c) 2003-2006, Martin Hauner
 *                          http://subcommander.tigris.org
 *
 * Subcommander is licensed as described in the file doc/COPYING, which
 * you should have received as part of this distribution.
 * ====================================================================
 */

#ifndef _TEXT_POSITION_CALCULATOR_H
#define _TEXT_POSITION_CALCULATOR_H

// qt
#include <QtGui/QFontMetrics>
#include <QtCore/QRect>

class TextPositionCalculator
{
public:
  TextPositionCalculator( const QFontMetrics& m, const QRect& r, int x, int y )
  : _m(m), _r(r), _x(x), _y(y)
  {
  }

  // returns the line containing y, absolute.
  int getLine( int y ) const
  {
    return y / _m.height();
  }

  // returns the first line which is (partially) contained in r.
  int getTopLine() const
  {
    return ( _y + _r.y() ) / _m.height();
  }

  // returns the last line which is (partially) contained in r.
  int getBottomLine() const
  {
    return ( _y + _r.y() + _r.height() ) / _m.height();
  }

  // returns the first column which is (partially) contained in r.
  int getLeftColumn() const
  {
    return ( _x + _r.x() ) / _m.width('x');
  }

  // returns the last column which is (partially) contained in r.
  int getRightColumn() const
  {
    return ( _x + _r.x() + _r.width() ) / _m.width('x');
  }

  /**
   * returns y for line, relative to y scroll pos.
   */
  int getLineY( int line ) const
  {
    return line * _m.height() - _y;
  }

  /**
   * returns y for text in line, relative to y scroll pos.
   */
  int getTextY( int line ) const
  {
    return getLineY(line+1) - _m.descent();
  }

  /**
   * returns first visible x pixel.
   * used for drawing the background.
   */
  int getLineX() const
  {
    return _r.x();
  }

  /**
   * returns x pos plus correction for text.
   *
   * used for drawing text, we always draw the complete text for a line.
   * what is left or right of rect gets clipped away. it is a lot easier
   * to redraw the complete text line than to redraw just a part of it.
   */
  int getTextX( int corr = 0 ) const
  {
    return 0 - _x + corr;
  }

  /**
   * calculate the cursor x position for the given column.
   */
  int getCursorX( int column, const QString& str, int corr = 0 ) const
  {
    int width = _m.width( str, column );
    return width + corr - _x;
  }

  /**
   * calculate the column in @a str at the given @a x position.
   */
  int getColumn( int x, const QString& str ) const
  {
    int pos = 0;
    int off;

    for( off = 0; off < (int)str.length(); off++ )
    {
      QChar c = str[off];
      
      pos += _m.width(c);

      if( pos >= x )
      {
        break;
      }
    }

    return off;
  }

  // returns the height of lines lines.
  int getHeight( int lines ) const
  {
    return lines * _m.height();
  }

  /**
   * returns the font height.
   */
  int getFontHeight() const
  {
    return _m.height();
  }

  /**
   * returns the character width.
   * this is not acurate for proportional fonts.
   */
  int getFontWidth() const
  {
    // use _m.maxWidth() ??
    return _m.width('M');
  }

private:
  QFontMetrics _m;
  QRect        _r;
  int          _x;
  int          _y;
};

#endif // _TEXT_POSITION_CALCULATOR_H
