/* This file is part of `mogul'
 * Copyright (c) 1995 David Deaven
 *
 * In the following, "you" and "You" refer to any entity other than 
 * the Microsoft corporation and its subsidiaries.  All rights are
 * reserved by the author in connection with Microsoft and its
 * subsidiaries.  The Microsoft Network is explicity denied the right
 * to copy, reproduce, or transmit this software.
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program; if not, write to the Free Software
 *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 * $Author: deaven $
 * $Id: mogul.h,v 2.1 1996/07/11 18:41:37 deaven Exp deaven $
 */

#ifndef _DMD_MOGUL_H_
#define _DMD_MOGUL_H_

#include <stdio.h>
#include "dmd/rgb.h"
#include "dmd/geometry.h"
#include "dmd/neighbor.h"
#include "camera.h"

/* Attribute modes for rendering objects.
 *
 * Some attributes only affect specific objects, others have
 * universal meaning.
 */
#define MA_FILLED	(1 << 0)	/* fill object */
#define MA_OUTLINE	(1 << 1)	/* plot outline of object */
#define MA_SOLID	(1 << 2)	/* use realistic solid shading */
#define MA_TRANSLUCENT	(1 << 3)	/* use translucent effect */
#define MA_MOON		(1 << 4)	/* plot moon shading on spheres */
#define MA_STICK	(1 << 5)	/* use multiple lines for bonds */
#define MA_MINIMAL	(1 << 6)	/* use faster/smaller rendering */

#define SPEEDY_MODE 	(1 << 0)	/* be speedy */
#define SPEEDY_BONDS	(1 << 1)	/* plot bonds in speed mode */
#define SPEEDY_ATOMS	(1 << 2)	/* plot atoms in speed mode */
#define SPEEDY_LINES	(1 << 3)	/* plot lines in speed mode */
#define SPEEDY_ALL	(SPEEDY_BONDS | SPEEDY_ATOMS | SPEEDY_LINES)

/* Attributes common to an object of any type.
 */
struct commonAttributes {
	unsigned int mode;	/* rendering flags */
	Color color;		/* color */
};

struct plotAttributes {
	double width, height;	/* size of camera screen in a.u. */
	double vdist;		/* perspective distance (to viewer) in a.u. */
	Color foreground;	/* foreground color */
	Color background;	/* background color */
};

/* Rule attributes for all objects.
 */
struct ruleAttributes {
  enum ruleType {RULE_ATOM, RULE_BOND} type;
  struct commonAttributes attr;	/* use depends on context */
  union {

    struct {
      char *aname;		/* atomic name */
      char *fullname;		/* full atomic name */
      double radius;		/* atomic radius */
    } atom;

    struct {
      char *anameFrom;		/* type of atom on one side... */
      char *anameTo;		/* ...and the other side */
      double bondr;		/* maximum length of bond */
      double radius;		/* radius of bond cross-section */
    } bond;

  } u;

};

typedef struct MogulObjectRec * MogulObject;
typedef struct MogulRulesRec * MogulRules;
typedef struct MogulPlotRec * MogulPlot;
typedef struct MogulDeviceRec * MogulDevice;
typedef struct MogulParserRec * MogulParser;
typedef struct StringPoolRec * StringPool;
typedef void * MogulDeviceInstance;

/* Each device driver must provide these standard functions.
 */
struct MogulDeviceRec {
  char *devicename;
  char *fullname;
  int (*Pcolor)(Color c, MogulDeviceInstance mdi);
  int (*Parc)(double x[3], double r, double u[3], double v[3],
	  double t0, double t1, MogulDeviceInstance mdi);
  int (*Pcircle)(double x[3], double r, MogulDeviceInstance mdi);
  int (*Pshade)(double x[3], double r, double u[3], double v[3],
	  MogulDeviceInstance mdi);
  int (*Pmove)(double x[3], MogulDeviceInstance mdi);
  int (*Pline)(double x[3], MogulDeviceInstance mdi);
  int (*Pclose)(MogulDeviceInstance mdi);
  int (*Ptext)(char *s, double fracheight, MogulDeviceInstance mdi);
  MogulDeviceInstance (*Pinit)(char *devinfo);
  int (*Pstart)(MogulPlot p, MogulDeviceInstance mdi);
  int (*Pend)(MogulPlot p, MogulDeviceInstance mdi);
  int (*Pstop)(MogulDeviceInstance mdi);
  MogulDeviceInstance instance;
};

/* Error codes stored in mogul_errno.
 */
#define MoErrFatalMask			0x100000
#define MoErrNormalOperation		0
#define MoErrInvalidDeviceInstance	1
#define MoErrParserError		2
#define MoErrSystem			3
#define MoErrMax			4

extern int MogulErrno;
extern char *MogulParserMsg;

/* Function prototypes */

MogulPlot NewMogulPlot(char *author);
void DeleteMogulPlot(MogulPlot p);
int MogulRender(MogulPlot p, MogulDevice d);

struct commonAttributes *MogulDefaultAttributes(MogulPlot p,
  struct commonAttributes *attr);
int MogulObjectExtent(MogulPlot p, double center[3], double *r);
void MogulTransformObjects(MogulPlot p);
void MogulClearObjects(MogulPlot p);
int MogulAddAtom(MogulPlot p, struct commonAttributes *attr,
        double x[3], double radius);
int MogulAddBond(MogulPlot p, struct commonAttributes *attr,
        double x[3], double y[3], double radius);
int MogulAddBondBetween(MogulPlot p, struct commonAttributes *attr,
        double x1[3], double r1, double x2[3], double r2, double radius);
int MogulAddLine(MogulPlot p, struct commonAttributes *attr,
        double x[3], double y[3]);
int MogulAddLabel(MogulPlot p, struct commonAttributes * attr,
        double x[3], char *text, double height);
int MogulAddSegmentedLine(MogulPlot p, struct commonAttributes *attr,
	double a[3], double b[3]);

void MogulDeviceInit(void);
MogulDevice MogulGetDevice(char *devicename, char *deviceinfo);
void MogulFreeDevice(MogulDevice d);
void MogulPrintDevices(FILE *f);
char **MogulListDevices(void);
void MogulSetMsgHandler(void (*emsg)(char *), void (*wmsg)(char *));
void MogulPerror(char *s);
char *MogulStrerror(int code);

Camera MogulGetCamera(MogulPlot p);
struct plotAttributes *MogulGetPlotAttributes(MogulPlot p);
int MogulSetPlotAttributes(MogulPlot p, struct plotAttributes *attr);

double perscl(double x[3], double px[3], double vdist);
int Parc_from_lines(double x[3], double r, double u[3], double v[3],
	double t0, double t1, double res,
	int (*pline)(double *, MogulDeviceInstance),
	MogulDeviceInstance mdi);

int MogulSimpleAddGeometry(MogulPlot p, Geometry *g);
int MogulAddGeometry(MogulPlot p, MogulRules r, Geometry *g, NeighborList *nl);
int MogulAddBox(MogulPlot p, struct commonAttributes *attr, Geometry *g);

MogulRules NewMogulRules(void);
void DeleteMogulRules(MogulRules r);
struct ruleAttributes *MogulGetAtomRule(MogulRules r, char *aname);
struct ruleAttributes *MogulGetBondRule(MogulRules r, char *anameFrom, char *anameTo);

MogulParser NewMogulParser(void);
void DeleteMogulParser(MogulParser parser);
int MogulParseString(MogulParser parser,
  char *command, MogulPlot p, MogulDevice device, Geometry *g, NeighborList *nl);
int MogulParseFile(MogulParser parser,
  char *fn, MogulPlot p, MogulDevice device, Geometry *g, NeighborList *nl);

StringPool NewStringPool(void);
void DeleteStringPool(StringPool sp);
char *AddToStringPool(StringPool sp, char *s);

/* Only the Mogul source code needs to see these internal definitions;
 * external code may make the define but it's discouraged.
 */
#ifdef MOGUL_SOURCE

enum mogul_object_enum {O_ATOM, O_LABEL, O_BOND, O_LINE};

struct MogulObjectRec {
	enum mogul_object_enum type;
	struct commonAttributes attr;
	int id;
	int v[2];		/* indices into vertices */
	union {
	  struct {
	    double radius;	/* radius */
	  } atom;
	  struct {
	    double radius;	/* radius */
	    double length;
	  } bond;
	  struct { 
	    char *text;		/* string text */
	    double height;	/* letter height */
	  } label;
	} part;
};

struct orderedObject {
	int distance;
	MogulObject o;
};

struct MogulPlotRec {
	Camera camera;	/* public view camera transform */
	struct plotAttributes attr;
			/* public plot attributes */

	unsigned int nObjectMax;
			/* how many objects we've allocated space for */
	unsigned int nObject;
			/* how many objects there are */
	struct orderedObject *object;
			/* array of objects */
	int nextObjectID; /* next id to assign */
	
	unsigned int nVertexMax;
			/* dimensioned number of vertices */
	unsigned int nVertex;
			/* number of vertices */
	double *vertex;	/* lab frame vertex positions */
	double *tVertex; /* camera frame transformed vertices */
	int tCurrent;	/* transformed vertices are current? */

	int speedy;	/* fast-draw bit flags */
	int speedySkip;
	int nSkip;

	char *author;	/* argv[0] command name of constructor */

	StringPool sp;
};

#endif /* MOGUL_SOURCE */
#endif /* _DMD_MOGUL_H_ */
