// Basic point and rectangle classes
#ifndef RECT_HPP
#define RECT_HPP
#ifndef HARDWARE_HPP
#include "hardware.hpp"
#endif

// BIT macro for enum flags
#define BIT(n) (1 << n)

#ifndef max
#define max(x,y) ((x) >= (y) ? (x) : (y))
#define min(x,y) ((x) <= (y) ? (x) : (y))
#endif

extern "C" char *form(const char *,...);
// Standard printf-style format function. The return value points to
// one of a number of internal static buffers, so it will be
// overwritten after a few calls.
extern "C" char *strcat(char *,const char *)/*!*/;

/*
Basis of coordinate system. The Point is a structure with lots of
useful inline operators.
The coordinates are based on 0,0 at the top left of the screen.
*/
struct Point {
public:
coord x;
coord y;

//~ Assignment operators
Point& operator=(const Point &p) { x = p.x; y = p.y; return *this; }
Point& operator+=(const Point &p) { x += p.x; y += p.y; return *this; }
Point& operator+=(const coord i) { x += i; y += i; return *this; }
Point& operator-=(const Point &p) { x -= p.x; y -= p.y; return *this; }
Point& operator-=(const coord i) { x -= i; y -= i; return *this; }

//~ Boolean operators
int operator== (const Point &p) const { return (x == p.x && y == p.y); }
int operator!= (const Point &p) const { return (x != p.x || y != p.y); }
int operator< (const Point &p) const { return (x < p.x && y < p.y); };
int operator<= (const Point &p) const { return (x <= p.x && y <= p.y); };
int operator> (const Point &p) const { return (x > p.x && y > p.y); };
int operator>= (const Point &p) const { return (x >= p.x && y >= p.y); };

char *inspectinfo(char *buffer = 0,const char *s = "") const/*!*/;
};

#ifdef __TURBOC__
// The origin (0,0) - top left of the screen.
const Point origin = { 0, 0};
#else
const Point origin/*!*/;
#endif

// The basic rectangle, used to size all screen objects.
class Rectangle {
Point tl;
Point br;

public:
//~ Constructors
Rectangle();
Rectangle(const coord l,const coord t,const coord r,const coord b);
Rectangle(const Point& topl,const Point& botr);
Rectangle(const Point& topl,const coord width,const coord height);
Rectangle(const coord width,const coord height);
Rectangle(const Rectangle &r); // copy constructor

void build(const coord left,const coord top,const coord right,const coord bottom);
// Helper function called by constructors.

//~ Access methods
coord left() const { return tl.x; }
coord right() const { return br.x; }
coord top() const { return tl.y; }
coord bottom() const { return br.y; }
coord width() const { return br.x - tl.x + 1; }
coord height() const { return br.y - tl.y + 1; }
const Point& topleft() const { return tl; }
const Point& botright() const { return br; }

//~ Changing the Rectangle
void position(coord x,coord y);
void position(const Point &p) { position(p.x,p.y); }
void move(coord x,coord y);
void move(const Point& p) { move(p.x,p.y); }
void setwidth(const coord w);
void setheight(const coord h);
void setsize(coord x,coord y) { setwidth(x); setheight(y); }
void setsize(const Point &p) { setsize(p.x,p.y); }
Rectangle& operator=(const Rectangle& r)
{ build(r.tl.x,r.tl.y,r.br.x,r.br.y); return *this; }

//~ Boolean methods
int encloses(const coord x,const coord y) const;// Is p in this.
int encloses(const Point& p) const; // Is p in this.
int encloses(const Rectangle& r) const; // Is r in this.
int inside(const Rectangle& r) const // Is this in r.
{ return r.encloses(*this); }
int intersects(const Rectangle &r) const;

//~ intersection of two rectangles
Rectangle& operator&=(const Rectangle &r);

//~ Union of two rectangles
Rectangle& operator|=(const Rectangle &r);
// Smallest rectangle which encloses both.

char *inspectinfo(char *buffer = 0,const char *s = "") const /*!*/;
};

#endif