
//		  ÚÄÄÄÄÄÄÄ¿
//	ÄÄÄÄÄÄÄÄÄ>³ AVNER ³
//	ÄÄÄÄÄÄÄÄÄ>³  BEN  ³ÄÄÄÄÄÄ> Software Engineering Method
//		  ÀÄÄÄÄÄÄÄÙ
//	10 Dov-Hoz st. Tel-Aviv 63416 Israel tel. 972-3-221535

// The Screen NAVigator, ver 1.20 August 1990
// Copyright (c) 1990 by Avner Ben
// Snav is not, and never was, free software.
// for conditions for use refer to file "copyrigh.txt"

// The Screen Navigator is an object-oriented device-independent
// character-graphics driver package, written in the C++ language,
// distributed in the form of C++ source code.
// For further information refer to the documentation files.

// The user may not omit this text, from the beginning of the file, to
// the line of asterisks below.

/***************************************************************************/

// package nucleus part 4 - headers.
// This file defines the generic "shape" (character-graphic element to be
// charted on a panel).

// History:
// 8.8.90   - avner ben seperated snav2.
// for further details refer to documentation.

// Site history (of this copy):
// __.__.__ ____________ : __________________.

#ifndef SNAV3_H
#define SNAV3_H

#include <string.h>
#ifndef SNAV2_H
#include "/mtad/snav/snav2.hpp"
#endif
#ifndef NULL
#include <stdlib.h>
#endif

class shape_segment
 { // generic shape element

	protected :
		direction dir;
		color_ind *color;

	public	:
		shape_segment(direction &indir, color_ind *incolor=NULL);
		virtual ~shape_segment(void);
		virtual shape_segment *new_copy(void)=0;
		// pointer to a replica of yourself

		// structural info
		virtual boolean homogeneous(void) { return TRUE; }
		 // tell if made of homoegoneous elements (such as arrow)
		 // or heterogeneous (such as character string)
		virtual boolean can_point(void) { return TRUE; }
		 // tell if arrowhead applicable
		virtual boolean has_weight(void) { return TRUE; }
		 // tell if weight_distribution applicable

		// state info
		direction &ask_dir(void);  // (temporary result)
		color_ind *ask_color(void)  { return color; }
		virtual int ask_len(void)=0;
		virtual weight_d &ask_wgt(void)=0; // (temporary result)
		virtual boolean ask_tip(void)=0;
		 // tell if pointed (where applies)

		// management
		void set_dir(direction &indir);
		void set_color(color_ind *color);
		void turn(void);
		void invert(void);
		virtual void list(panel *scr, point_pos *pt)=0;
		virtual void clear(panel *scr, point_pos *pt)=0;
		virtual void contract(void)=0;
		virtual void expand(void)=0;
		virtual void toggle_tip(void)=0;
		virtual void set_len(int inlen)=0;
		virtual void set_wgt(weight_d &inwgt)=0;
		virtual void mask(weight_d &other_wgt)=0;
} ;

class arc : public shape_segment
{ // the straight line shape - the basic graphic primitive

	protected :
		int len;
		weight_d wgt;		// only relevant axis considered
		boolean tipped; 	// tipped with arrowhead

	public	:
		arc(int inlen, direction &indir, weight_d &inwgt=h1v1,
		 boolean intip=FALSE, color_ind *incolor=NULL)
		 : shape_segment(indir,incolor)
		{ len=inlen; wgt=inwgt; tipped=intip; }
		shape_segment *new_copy(void);

		// info
		int ask_len(void)  { return len; }
		weight_d &ask_wgt(void);  // (temporary result)
		boolean ask_tip(void)  { return tipped; }

		// management
		void list(panel *scr, point_pos *pt);
		void clear(panel *scr, point_pos *pt);
		void contract(void);
		void expand(void);
		void toggle_tip(void);
		void set_len(int inlen);
		void set_wgt(weight_d &inwgt);
		void mask(weight_d &other_wgt);
} ;

class display_string : public shape_segment
{
	private :
		char *s;
		direction align; // right or left. any other means center.

	public	:
		display_string(char *str, direction &indir=rt,
		 direction &alignment=lt, color_ind *incolor=NULL)
		 : shape_segment(indir,incolor), align(alignment)
		 { s=new char[strlen(str)+1]; strcpy(s,str); }
		~display_string(void) { delete s; }
		shape_segment *new_copy(void);

		// info
		boolean homogeneous(void) { return FALSE; }
		boolean can_point(void) { return FALSE; }
		boolean has_weight(void) { return FALSE; }
		int ask_len(void)  { return strlen(s); }
		weight_d &ask_wgt(void);
		boolean ask_tip(void)  { return FALSE; }

		// management
		void list(panel *scr, point_pos *pt);
		void clear(panel *scr, point_pos *pt);
		void contract(void);
		void expand(void);
		void toggle_tip(void) {}
		void set_len(int inlen);
		void set_wgt(weight_d &inwgt) {}
		void mask(weight_d &other_wgt) {}
} ;

class stroke
 { // shape segment as list member

	friend class shape;

	private :
		shape_segment *item;
		stroke *suc;
		boolean pendn;
		point_pos offset;			   // used by "shape" iterator

	public :
		stroke(shape_segment *src, boolean pen_down=TRUE);
		stroke(int inlen, direction &dir, weight_d &wgt=h1v1,
		 boolean tip=FALSE, color_ind *color=NULL, boolean pendn=TRUE);
		stroke(char *s, direction &dir, direction &align=lt,
		 color_ind *color=NULL, boolean pendn=TRUE);
		~stroke(void);
		void list(panel *scr, point_pos *pt);
		void clear(panel *scr, point_pos *pt0);
		stroke *succ(void)  { return suc; }
		void toggle_pen(void);
		boolean pen_is_down(void);

		// interface to drawing item
		boolean homogeneous(void);
		boolean can_point(void);
		boolean has_weight(void);
		int len(void)
		 { return item->ask_len(); }
		weight_d &wgt(void)
		 { return item->ask_wgt(); } // (temporary result)
		direction &dir(void)
		 { return item->ask_dir(); } // (temporary result)
		color_ind *color(void)	{ return item->ask_color(); }
		int dirval(void)
		 { return (item->ask_dir())(); }
		boolean tip(void)
		 { return item->ask_tip(); }
		void contract(void);
		void expand(void);
		void turn(void);
		void invert(void);
		void toggle_tip(void);
		void set_len(int inlen);
		void set_wgt(weight_d &inwgt);
		void mask(weight_d &other_wgt);
} ;

class shape
 { // the generic shape
  // not an "abstract class" (may also be defined and used as is)

	protected :
		stroke *stsk, *ensk;				      // curve
		char *sname;				      // name for info

		// working storage
		point_pos tmpt1, tmpt2;

	public:
		shape(stroke *sk=NULL, char *inname="amorph");
		virtual ~shape(void);

		virtual void append_stroke(stroke *sk);
		void append_stroke(point_pos &offset); // dummi move
		virtual void list(panel *scr, point_pos *pt, boolean stay=TRUE);
		 // warning: the generic shape lists only arcs pre-allocated!
		 // in a "regular" shape, the user should supply specific listing.
		virtual void clear(panel *scr, point_pos *pt, boolean stay=TRUE);
		 // warning: the generic shape clears only arcs pre-allocated!
		 // in a "regular" shape, the user should supply specific clearing.
		char *name(void)  { return(sname); }
		stroke *ask_start(void)  { return stsk; }

		// management
		point_pos &where(void);
		 // offest of end from start (temp result)
		void posit_start(void);
		 // add dummi move back to start point
		void posit(point_pos &offset);
		 // add dummi move to offset from start.
		point_pos &area(void);
		 // size of rectangle covered by shape
		boolean occupied(point_pos &pt);
		 // tell point covered by pen-down operation
} ;

// used by class tracing

struct landmark
{ // list of turn points (fifo)

	point_pos pos;		// node cursor address
	intersection dirstart;	// all available directions
	intersection dirleft;	// directions left unexplored as yet
	landmark *suc;

	landmark(point_pos *pt, intersection *avdir);
	void proceed(intersection *avdir, direction *curdir);
	 // select next dirction to proceed from junction (modifies args)
};

class tracing : public shape
{ // shape copied from the real world. unnormalized sequential tracing.
  // a "procedural" class, implementing a shape + its imitializing process.

	private :
		landmark *stmark;

		void clear_landmarks(void);

	public:
		tracing(panel *scr, point_pos *cursor);
		 // "spy constructor". your assignment is to recognize a
		 // shape in the real screen and copy it. here are the
		 // coordinate where the real-world shape is to be found.
		 // you are to solve this mission alone, with no help from
		 // the outside. of-course, if you get cought, or hang the
		 // the machine, we'll deny any connection with you.

		landmark *append_stroke(panel *scr, point_pos *cursor, direction *curdir);
		 // one phase of the spy-constructor. read arc. return
		 // available directions at exit point. cursor set to exit point.
		landmark *mark(point_pos *cursor, intersection *avdir);
		 // locate node entry for cursor, append if not in list
};

class oblong : public shape
{ // sample "regular shape"

	public :
		oblong(int width, int height, weight_d &wgt=h1v1);
		void list (panel *scr, point_pos *pt);
		 // spcified is left up corner
		void clear (panel *scr, point_pos *pt);
		 // spcified is left up corner
} ;

class display_box : public shape
{
	public :
		display_box(char *s, point_pos &zise, weight_d &wgt=h1v1,
		 direction &pendir=rt, direction &align=lt);
} ;

#endif

