// Screen.h - Interface for the Screen class.  Since class Point
// and class Screen are inter-dependent, and will be used together,
// it makes sense to provide a single interface (dot-h) file.
//
// Written by (c) Wayne Pollock, 2000.  All Rights Reserved.

#ifndef SCREEN_H
#define SCREEN_H

#include <iostream>

//using namespace std;  // not needed since I used std:: qualified names.

// A simple point class.  Although not necessary, this Point class
// is implemented as a "Concrete Data Type" for illustration purposes.
// Two useful overloaded operators are provided: equality testing ("==")
// and addition.  Although these short functions could be defined inline,
// they are implemented elsewhere, again just for illustration.

struct Point
{   int row;
    int col;

    Point () { row = 0; col = 0; }
    Point ( int r, int c ) { row = r; col = c; }
    Point ( const Point& p ) { row = p.row; col = p.col; }
    Point& operator= ( const Point& p )
	{ row = p.row; col = p.col; return *this; }
    ~Point () {}

    int operator== ( const Point& p ) const;
    Point operator+ ( const Point& ) const;
};


// A Screen is a two dimensional grid of chars.  The Screen keeps track of the
// current char to plot with ("ink"), whose value can be examined and changed
// with get_ink() and set_ink().  Additionally, when a point is plotted on the
// Screen (via "plot()"), an optional argument can be supplied to override the
// ink char used for that point only; zero means to use Screen::ink.
//
//    Note that an attempt to plot points which aren't on the screen is not
// an error; such points are ignored (note that "current_pt" is not updated.)
//
//    A Screen can return its size via "size()"; the value returned is a
// Point whose row member = the maximum row, and likewise for the column.
//
//    A Screen also maintains the coordinates of the last Point ploted. This
// Point is returned via "cur_pt()".  (This is useful for extending lines
// from the end of the previous line and for drawing concentric circles.)
// The current point can be set with via "move_to()".
//
//    Lastly, a Screen can be displayed to some output stream via "display()",
// and a Screen can be erased (cleared, blanked) via "clear()".

class Screen
{
public:
    // Default values for Screens:
    enum { NUM_ROWS = 20, NUM_COLS = 72, INK_DEFAULT = '*' };

    Screen ();
    Screen ( const Screen& );
    Screen& operator= ( const Screen& );
    ~Screen ()  {}

    void clear ( char erase_char = ' ' );
    void display ( std::ostream& = std::cout ) const;
    void draw_circle ( const Point& center, int radius, char ink = 0 );
    void draw_line ( const Point& start_pt, const Point& end_pt, char ink = 0 );
    char get_ink () const { return ink; }
    Point cur_pt () const { return current_pt; }
    void move_to ( const Point& );  // does noting if the Point is off-screen.
    void plot ( const Point&, char ink = 0 );
    void set_ink ( char new_ink ) { ink = new_ink; }
    Point size () const;

private:
    char ink;   // The character to draw with.
    char rep[NUM_ROWS][NUM_COLS];
	Point current_pt;	// The last plotted point.

	void circle_points ( const Point&, const Point&, char temp_ink = 0 );
};

#endif

