/*************************************************
*                       ASPIC                    *
*************************************************/

/* Copyright (c) University of Cambridge 1991 - 2008 */
/* Created: February 1991 */
/* Last modified: March 2008 */

/* General header file used by all modules */


#include <ctype.h>
#include <math.h>
#include <stdarg.h>
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <time.h>

#include <errno.h>
#include <sys/time.h>

#include "mytypes.h"


#define Version_String "1.05 (04-March-2008)"


/* Set up unit definitions appropriately for 16-bit and
32-bit environments */

#if INT_MAX == 32767
#define UNIT_IS_LONG
#endif

#ifdef UNIT_IS_LONG
typedef long unit;
#define uabs(n) labs(n)
#define udiv(n,m) ldiv(n,m)
#define udiv_t ldiv_t
#define UNIT_MAX LONG_MAX
#define UNIT_MIN LONG_MIN
#define U_FORMAT "ld"
#else
typedef int unit;
#define uabs(n) abs(n)
#define udiv(n,m) div(n,m)
#define udiv_t div_t
#define UNIT_MAX INT_MAX
#define UNIT_MIN INT_MIN
#define U_FORMAT "d"
#endif

/* Miscellaneous defines */

#define UNSET UNIT_MAX		/* For unset parameters */

#define INPUT_LINESIZE 256
#define MAC_STACKSIZE 20

/* Some environments don't have div_t defined */

#ifdef SUNOS4
#define __needs_div__
#endif


#ifdef __needs_div__
typedef struct { unit quot; unit rem; } udiv_t;
extern udiv_t udiv(unit numer, unit denom);
#endif


/* Macro to apply magnification to a dimension */

#define mag(x) ((x * env->magnification)/1000)

/* Macro to get the next UTF-8 character, advancing the pointer. */

#define GETCHARINC(c, ptr) \
  c = *ptr++; \
  if ((c & 0xc0) == 0xc0) \
    { \
    int gcaa = utf8_table4[c & 0x3f];  /* Number of additional bytes */ \
    int gcss = 6*gcaa; \
    c = (c & utf8_table3[gcaa]) << gcss; \
    while (gcaa-- > 0) \
      { \
      gcss -= 6; \
      c |= (*ptr++ & 0x3f) << gcss; \
      } \
    }



/*************************************************
*             Enumerations                       *
*************************************************/

/* Output types */

enum { OUT_UNSET, OUT_PS, OUT_SG, OUT_SV };

/* Item types */

enum { i_arc, i_box, i_line, i_text, i_wait, i_redraw };

/* Item "style"s */

enum { is_norm, is_invi };

/* Types of "box" */

enum { box_box, box_circle, box_ellipse };

/* Text justifications */

enum { just_left, just_right, just_centre };

/* Directions and positions */

enum { north, northeast, east, southeast, south, southwest, west, northwest,
       centre, start, end, middle, unset_dirpos };

/* Types of optional argument */

enum { opt_bool,            /* no data; set first arg; unset second arg */
       opt_xline,           /* one x dimension; set first arg; zero second arg if UNSET */
       opt_xnline,          /* one x dimension; set first arg negative; zero second arg if UNSET */
       opt_yline,           /* one y dimension; set first arg; zero second arg if UNSET */
       opt_ynline,          /* one y dimension; set first arg negative; zero second arg if UNSET */
       opt_dim,             /* one dimension; second arg ignored */
       opt_colour,          /* colour */
       opt_colgrey,         /* colour or grey level */
       opt_grey,            /* grey level */
       opt_at,              /* absolute position */
       opt_join,	    /* position specified by joining point */
       opt_angle,           /* one angle */
       opt_int,             /* integer */
       opt_dir              /* no data; sets direction from table data */
};

/* Special font types */

/* Values in the special fonts characters table */

enum { SF_SYMB, SF_DBAT };




/*************************************************
*              Structures                        *
*************************************************/

/* Structure for included files */

typedef struct includestr {
  struct includestr *prev;
  FILE *prevfile;
} includestr;

/* Structure of command table entries */

typedef struct {
  uschar *name;
  void (*function)(void);
  unit arg1;
  unit arg2;
} command_item;

/* Structure of entry in list of arguments per command */

typedef struct {
  uschar *name;
  int	type;
  unit	arg1;
  unit	arg2;
} arg_item;

/* Structure to hold a colour definition */

typedef struct colour {
  unit red;
  unit green;
  unit blue;
} colour;

/* Entry in string chain */

typedef struct stringchain {
  struct stringchain *next;
  unit xadjust;
  unit yadjust;
  int  justify;
  int  font;
  int  chcount;   /* Count of chars, not bytes */
  colour rgb;
  uschar text[1];
} stringchain;

/* Structure for holding a bindfont request */

typedef struct bindfont {
  struct bindfont *next;
  int number;
  unit size;
  BOOL needSymbol;
  BOOL needDingbats;
  uschar name[1];
} bindfont;

/* Structure for the built-in list of named entities */

typedef struct entity_block {
  uschar *name;
  int    value;
} entity_block;

/* Structures for macro handling */

typedef struct mac_line {
  struct mac_line *next;
  uschar text[1];
} mac_line;

typedef struct mac_arg {
  struct mac_arg *next;
  uschar text[1];
} mac_arg;

typedef struct macro {
  struct macro *previous;
  uschar name[20];
  mac_line *nextline;
  int argcount;
  mac_arg *args;
} macro;

/* Input environment variables are held in a structure for stacking */

typedef struct environment {
  struct environment *previous;  /* link for stacking */
  unit arcradius;      /* default arc radius */
  unit arrow_x;        /* x distance for arrowhead */
  unit arrow_y;        /* y distance for arrowhead */
  unit boxdash1;       /* current box dash parameters */
  unit boxdash2;
  unit boxwidth;       /* current box width */
  unit boxthickness;   /* thickness of edge of boxes */
  unit boxdepth;       /* current box depth */
  colour boxcolour;    /* colour of box edges */
  colour boxfilled;    /* colour of box filling */
  unit cirdash1;       /* circle dash parameters */
  unit cirdash2;
  colour circolour;    /* colour of circle edges */
  unit cirradius;      /* default circle radius */
  unit cirthickness;   /* default thickness of circle edges */
  colour cirfilled;    /* colour of circle filling */
  int  direction;      /* current default direction */
  unit elldash1;       /* ellipse dash parameters */
  unit elldash2;
  colour ellcolour;    /* ellipse edge colour */
  unit ellwidth;       /* ellipse width */
  unit elldepth;       /* ellipse depth */
  unit ellthickness;   /* ellipse edge thickness */
  colour ellfilled;    /* colour of ellipse filling */
  colour shapefilled;  /* filled colour for shapes */
  colour arrowfilled;  /* filled colour for arrowheads */
  unit fontdepth;      /* current text font depth */
  int  setfont;        /* current font number */
  colour textcolour;   /* current text colour */
  int  level;          /* current drawing level */
  unit linedash1;      /* current line dash parameters */
  unit linedash2;
  unit linedepth;      /* current text linedepth */
  unit linethickness;  /* thickness of lines */
  colour linecolour;   /* colour of lines */
  unit line_hw;        /* default horizontal line width */
  unit line_vd;        /* default vertical line depth */
  unit magnification;  /* current magnification */
} environment;


/* We use a macro for the common header for aspic "items" */

#define itemhdr \
  struct item *next; \
  stringchain *strings; \
  int    level; \
  unit	 type; \
  unit	 style; \
  unit	 dash1; \
  unit	 dash2; \
  unit	 linedepth; \
  unit	 fontdepth; \
  unit	 thickness; \
  colour colour; \
  colour shapefilled; \
  unit	 x; \
  unit	 y

/* Generic item structure */

typedef struct item {
  itemhdr;
} item;

/* Structure of label chain */

typedef struct label {
  struct label *next;
  item *itemptr;
  uschar name[20];
} label;

/* Arc item */

typedef struct {
  itemhdr;
  double angle1;
  double angle2;
  int direction;
  unit radius;
  unit angle;
  unit cw;
  unit depth;
  unit via_x;
  unit via_y;
  unit arrow_start;
  unit arrow_end;
  unit arrow_x;
  unit arrow_y;
  colour arrow_filled;
  unit x0, y0, x1, y1;
} item_arc;

/* Box item */

typedef struct {
  itemhdr;
  int boxtype;
  unit width;
  unit depth;
  int joinpoint;
  int pointjoined;
} item_box;

/* Line item */

typedef struct {
  itemhdr;
  unit width;
  unit depth;
  unit endx;
  unit endy;
  unit alignx;
  unit aligny;
  unit arrow_start;
  unit arrow_end;
  unit arrow_x;
  unit arrow_y;
  colour arrow_filled;
} item_line;

/* Text item */

typedef struct {
  itemhdr;
} item_text;

/* Wait item */

typedef struct {
  itemhdr;              /* Wasteful, but what the heck */
} item_wait;

/* Redraw item */

typedef struct {
  itemhdr;              /* Wasteful, but what the heck */
  item *ref;            /* Referenced item */
  colour filled;
} item_redraw;

/* Tree nodes for macros */

typedef struct tree_node {
  struct tree_node *left;         /* pointer to left child */
  struct tree_node *right;        /* pointer to right child */
  uschar *value;                  /* value of the macro */
  uschar  balance;                /* balancing factor */
  uschar  name[1];                /* node name - variable length */
} tree_node;

/* Entries in the Unicode to special font char table */

typedef struct u2sencod {
  int ucode;                   /* Unicode code point */
  int which;                   /* Which of the special fonts */
  int scode;                   /* Code point in the special font */
} u2sencod;



/*************************************************
*                  Global variables              *
*************************************************/

extern FILE   *main_input;        /* source input file */
extern FILE   *out_file;          /* output file */

extern includestr *included_from; /* chain for included files */
extern uschar **file_line_stack;  /* saved lines for included files */
extern int    *file_chptr_stack;  /* saved chptrs ditto */
extern int    inc_stack_ptr;      /* stack position */

extern item   *main_item_base;    /* base of chain of items */
extern item   *lastitem;          /* last on list of items read */
extern item   *baseitem;          /* item to base next item on */

extern label  *label_base;        /* base of chain of labels */
extern label  *nextlabel;         /* next label item */
extern environment *env;          /* input environment */

extern bindfont *font_base;       /* base of chain of font bindings */
extern BOOL   use_fonts;          /* TRUE if fonts are noticed */
extern BOOL   translate_chars;    /* TRUE to translate quotes and dash */

extern double pi;                 /* PI */

extern colour black;              /* For easy setting colours to black */
extern colour unfilled;           /* An "impossible" colour */

extern unit   centrepic;	  /* width for centering */
extern int    chptr;		  /* pointer to next char */
extern unit   drawbbox;		  /* draw bounding box offset */
extern BOOL   drawbboxfullwidth;  /* TRUE for full width bbox */
extern colour drawbboxcolour;     /* colour for same */
extern unit   drawbboxthickness;  /* thickness for same */
extern int    endfile;		  /* EOF reached */
extern unit   item_arg1;	  /* parameter 1 for items */
extern unit   item_arg2;	  /* parameter 2 for items */
extern unit   joined_xx;          /* explicit join point */
extern unit   joined_yy;
extern int    max_level;          /* uppermost level */
extern int    min_level;          /* lowermost level */
extern int    macro_count;        /* count of executed macros */
extern int    macro_id;		  /* this macro's id */
extern unit   minimum_thickness;  /* minimum line thickness */
extern BOOL   no_variables;       /* disable variables */
extern unit   resolution;         /* resolution of output device */
extern BOOL   strings_exist;      /* at least one item has a string */

extern uschar word[];             /* next word in input */

extern uschar *in_line;           /* current input line */
extern uschar *in_last;           /* last input line */
extern uschar *in_raw;            /* raw input line */

extern uschar **in_line_stack;    /* stack of pointers to saved in_lines */
extern int    *chptr_stack;       /* stack of saved chptrs */
extern int    mac_stack_ptr;      /* the stack position */
extern int    *mac_count_stack;   /* stack current count */

extern macro  *macroot;           /* root of all macros */
extern macro  *macactive;         /* chain of active macros */

extern int    outstyle;           /* output style */
extern BOOL   started;            /* after init */
extern BOOL   testing;            /* set when running tests */

extern tree_node *varroot;        /* variable root */

/* UTF-8 tables */

extern const int     utf8_table1[];
extern const int     utf8_table2[];
extern const int     utf8_table3[];
extern const uschar  utf8_table4[];

/* Entity list */

extern entity_block entity_list[];
extern int entity_list_count;

/* Character tables */

extern int nonulist[];
extern int nonucount;
extern int u2scount;
extern u2sencod u2slist[];


/*************************************************
*               Global functions                 *
*************************************************/

void c_arc(void);
void c_box(void);
void c_circle(void);
void c_line(void);
void c_redraw(void);

void chain_label(item *, int);
void error_moan(int, ...);
void find_bbox(unit *);
uschar *fixed(unit);
unit find_fontdepth(item *, stringchain *);
unit find_linedepth(item *, stringchain *);
item *findlabel(uschar *);
void freechain(void);
void *getstore(size_t);
void init_ps(void);
void init_sg(void);
void init_sv(void);
void nextch(void);
void nextsigch(void);
void options(item *, arg_item *);
int  readint(void);
unit readnumber(void);
stringchain *readstring(int);
void readword(void);
int  read_conf_file(uschar *);
int  read_inputfile(void);
unit rnd(unit);
BOOL samecolour(colour, colour);
void smallarc(unit, unit, double, double, void (*)(unit, unit, unit, unit, unit, unit));
void stringpos(item *, unit *, unit *);
void subs_vars(uschar *, uschar *);
int  tree_insertnode(tree_node **, tree_node *);
tree_node *tree_search(tree_node *, uschar *);
void write_ps(void);
void write_sg(void);
void write_sv(void);

/* End of aspic.h */
