/**********************************************************************
 *                               VERSION                              *
 **********************************************************************/
#define VERSION		"0.6"
//#define DEBUG

/**********************************************************************
 *                           ERROR HANDLING                           *
 **********************************************************************/

#define fatal_in(S) { fprintf (stderr, _("Fatal error in function '%s'.\n"),\
	              S); \
                      exit (1); }
#define fatal(S) { fprintf (stderr, _("Fatal error: %s.\n"), S); \
                   exit (1); }

/* bug_in is used in places that should never be reached (especially
 * default cases in switch instructions). */
#define bug_in(S) { fprintf (stderr, _("Strange fatal error in '%s'.\nThis shouldn't happen. You've just found a bug.\nPlease send a mail to <Francois-Xavier.Coudert@ens.fr>\n"), S); exit (1); }


/**********************************************************************
 *                        INTERNATIONALISATION                        *
 **********************************************************************/
#ifdef I18N
# include <libintl.h>
# define _(S) gettext (S)
#else
# define _(S) (S)
#endif

/* This one is a trick related to handling of menu items */
#define __(S) (S)


/**********************************************************************
 *                         MATHEMATICAL STUFF                         *
 **********************************************************************/

#define SQR(x) ((x)*(x))
#define INT(x) ((int) ((x) + 0.5))
#define ATAN2(y, x) ((x) == 0 ? ((y) > 0 ? (G_PI / 2) : (- G_PI / 2)) : \
                     ((x) > 0 ? atan2 ((double) (y), (double) (x)) : \
                     (G_PI + atan2 (- (double) (y), - (double) (x)))))

#define BIG             1000000
#define VERY_BIG        1E30


/**********************************************************************
 *                         ENCODING MANAGEMENT                        *
 **********************************************************************/

/*#define LATIN1(x) g_convert_with_fallback ((x), (signed) strlen (x), \
                  "latin1", "utf-8", "?", NULL, NULL, NULL)*/
#define LATIN1(x) (g_strdup(x))
#define IS_ALPHA(x) ((((x) >= 'a') && ((x) <= 'z')) \
                     || (((x) >= 'A') && ((x) <= 'Z')))



typedef gint64 LLINT;
#define LLFORMAT G_GINT64_FORMAT

#define BOND_LENGTH	5000
#define ORN_DEF_DIST	1400
#define ORN_DEF_SIZE	1600

#define UNITS		100
#define GLOBAL_SIZE_H	100000
#define GLOBAL_SIZE_V	100000

#define FULL_COLOR      65535

struct Bond
{
  unsigned int type;
  unsigned int selected;
  LLINT x1;
  LLINT y1;	/*
		 * For a bond or an arc, x1 and y1 are the coordinates of
		 * the first point.
		 *
		 * For an atom/group, it's the point where the
		 * PangoLayout should be displayed.
		 */
  LLINT x2;
  LLINT y2;	/*
		 * For a bond or an arc, the second point.
		 *
		 * For an atom/group, the width and height of the ink
		 * (used for the white masking rectangle).
		 */
  LLINT x3;
  LLINT y3;	/*
		 * For an atom/group, x3 and y3 are the coordinates of the
		 * atom (ie, the end of the bond).
		 *
		 * For an arc, x3 and y3 are the coordinates of its third
		 * point (the one in the middle).
		 */  
  LLINT x4;
  LLINT y4;	/*
		 * For an atom, x4 and y4 are the upper-left corner of
		 * the ink (used for selection and for the masking white
		 * rectangle.
		 *
		 * For an arrow (or arc arrow), x4 represents the
		 * properties of the arrow-head on point 1, and y4 does
		 * the same for point 2.
		 */
  double width;	/*
		 * For all bonds, this represents a "width"... For more
		 * details, use the source! :)
		 */
  GdkColor color;
  char *text;			/* Rich text in EasyChem format */
  char *pango;			/* Rich text in Pango markup */
  char *pango_left;		/* Left part, Pango markup */
  char *pango_right;		/* Right part, Pango markup */
  struct Bond *group_members;
  struct Ornament *ornaments[2]; /* ornaments[0] is for point 1,
				    ornaments[1] is for point 2,
				    ornaments[0] is for point 3
				    in case of text */
  struct Bond *next;
};


struct Ornament
{
  unsigned int type;	/* The type of the ornaments... */
  unsigned int number;
  double size;
  unsigned int angle;		/* The angle the ornaments are centered on,
			   counted as in the trigonometric circle */
  unsigned int spacing;	/* Angle between two ornaments */
  double dist;		/* Distance from the point to the ornaments */
  struct Ornament * next;
};



/* The global properties */
struct Properties
{
  LLINT global_height;
  LLINT global_width;
  int latex_export;
  gchar * path_gs;
  gchar * path_pstoedit;
};


extern GdkColor black;
extern struct Properties prop;
extern GdkGC * gc_gray, * gc_sel;


/* The definition of all options so that we can read the code. */
#define SEL_NO        0
#define SEL_YES       1
#define SEL_CLOSE_1   2
#define SEL_CLOSE_2   4
#define SEL_TEMP      8
#define SEL_ALL      15


enum { BOND_SIMPLE, BOND_DOUBLE, BOND_TRIPLE, BOND_UP,
  BOND_DOWN, BOND_DASHED, BOND_ARROW, BOND_ARC, 
  BOND_CIRCLE, BOND_ATOM, BOND_GROUP_L, BOND_GROUP_R, BOND_GROUP,
  BOND_DELIMITER };

enum { ORN_LONE_PAIR, ORN_GAP, ORN_RADICAL, ORN_GAP2, ORN_LONE_PAIR_DOTS,
  ORN_LONE_ELECTRON, ORN_DELIMITER };

#define BOND_HAS_TEXT(S) (((S)->type == BOND_ATOM) || \
                          ((S)->type == BOND_GROUP_R) || \
		          ((S)->type == BOND_GROUP_L))
#define BOND_HAS_WIDTH(S) ( \
    (((S)->type >= BOND_DOUBLE) && ((S)->type <= BOND_DOWN)) \
    || (((S)->type >= BOND_ARROW) && ((S)->type <= BOND_ARC)))

enum { MODE_ADJUST, MODE_EDIT, MODE_ADD, MODE_ROTATE, MODE_ORNAMENT };

enum { DRAW_NO, DRAW_NORMAL, DRAW_POLY, DRAW_SEL, DRAW_SEL_ADD,
  DRAW_MOVE, DRAW_MOVE_SEP, DRAW_COPY, DRAW_MOVE_POINT, DRAW_ROTATE,
  DRAW_SECOND, DRAW_THIRD };

enum { EXPORT_EPS, EXPORT_EPS_SIZE, EXPORT_EPS_NOBBOX, EXPORT_PDF,
  EXPORT_FIG, EXPORT_FIG_PRECISE, EXPORT_DELIMITER };

