#ifndef _SQUAREDANCE
#define _SQUAREDANCE

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <math.h>

#define true	1
#define false	0
#define forever	for (;;)
#define PI	3.1415926535897932

#ifndef DEBUG
# define DEBUG
#endif

enum movingOrientation {
    mo_fixed,			/* Person always faces same direction no matter what motion (do-si-do) */
    mo_forward,			/* Person faces direction of motion */
    mo_backward,		/* Person faces away from motion (walking backward) */
    mo_forward90,		/* Person faces 90 from motion, as in a circle */
    mo_forward_90,		/* Person faces -90 from motion, as in a circle */
    mo_rotating,		/* Person spins while moving (turn-single-back-to-place) by a specified amount */
    mo_rotateto,		/* Person spins while moving and ends facing the specified orientation */
    mo_cw_rotateto,		/* Same as above but only spin clockwise */
    mo_ccw_rotateto,		/* Same as above but only spin anti-clockwise */
    mo_faceDancer		/* Person faces another dancer */
};

enum command {
    c_moveto,			/* Only used to establish an initial position, not part of the dance itself, no bars */
    c_pause,			/* Do nothing */
    c_lineto,			/* move in a straight line */
    c_curveto,			/* move in a curved line */
    c_if,
    c_elseif,
    c_else,
    c_resetDance,		/* At end of a dance segment, reset partners, neighbors, people out, etc. */
    c_return,
    c_end,			/* End dance */
    c_copy,			/* Not a real command, a macro that moves commands from another role */
    c_transform		/* also not a real command */
};

enum condition {
    if_always,
    if_topset,			/* the top minorset (if there's a couple out then that would be the topset) */
    if_nottopset,
    if_bottomset,
    if_notbottomset,
    if_semitopset,		/* the minor set below a couple out at top */
    if_notsemitopset,
    if_semibottomset,		/* the minor set above a couple out at bottom */
    if_notsemibottomset,
    if_nottopsetorsemi,
    if_notbottomsetorsemi,
    if_nottopbottomset
};

enum band {
    band_unspecified,
    band_left,
    band_bottom,
    band_right,
    band_top
};

typedef struct position {
    float x, y;
} Position;

typedef struct rtheta {
    float r, theta;
} RTheta;

typedef struct rect {
    int x,y;
    int width,height;
} Rect;

typedef struct bb {
    int minx, maxx;
    int miny, maxy;
} BB;

typedef struct cubic {
    float a, b, c, d;		/* x/y = a*t^3 + b*t^2 + c*t + d */
} Cubic;

typedef struct expression {
    enum oper {op_and, op_or, op_not, op_topset, op_bottomset, op_part, op_last, op_first, op_majorpos, op_proper, op_improper } operator;
    int argument1;	/* for topset, bottomset, majorpos, part */
    int argument2;	/* for topset, bottomset */
    struct expression *op1, *op2;	/* For and, or, and cond1 is for not */
} Condition;
#define LAST_MASK	0x80000000
#define NOTLAST_MASK	0x40000000
#define FIRST_MASK	0x20000000
#define NOTFIRST_MASK	0x10000000

typedef struct block {
    Condition *condition;
    struct figureSegment *moves;
    int move_cnt, move_max;
    struct block *next;		/* a block with no condition is an else block, otherwise elseif */
				/* we can have as many blocks as we want representing a long if/elseif/.../elseif/else */
			        /* structure. There must be an else block. All blocks must be of the same millibar length */
    long lineno;
} Block;

typedef struct valChange {
    short value;		/* Sometimes a percentage, sometimes a degree */
    short millibars;		/* a value of -1 indicates the end of a list */
} ValChange;

typedef struct rThetaChange {
    RTheta pos;		/* Sometimes a percentage, sometimes a degree */
    short millibars;		/* a value of -1 indicates the end of a list */
} RThetaChange;

typedef struct valPoints {
    short end_of_last_move;	/* The value of this thing at the end of the last move */
    short now;			/* The current value of this thing */
} ValPoints;

typedef struct rThetaPoints {
    RTheta end_of_last_move;	/* The value of this thing at the end of the last move */
    RTheta now;			/* The current value of this thing */
} RThetaPoints;
    
#define MILLIBARS_MUL	1000.0
#define DEGREES_END	9999

typedef struct figureSegment {
    enum command cmd;
    int millibars;		/* number of bars in which this command takes place */
    enum movingOrientation orient;
    float degrees;		/* amount of rotation, either for c_rotate, or mo_rotating */
    int faceDancer;		/* dancer to face */
    Position endPoint;		/* for c_lineto, c_curveto */
    Position cp1, cp2;		/* for c_curveto */
    Cubic splines[2];		/* x, then y */
    unsigned int part_mask;
    enum condition condition;
    unsigned char position_absolute;
#define HAND_RIGHT_MASK		0x40000000	/* Other person's right hand */
#define HAND_LEFT_MASK		0x20000000	/* Other person's left hand */
#define HAND_HAND_MASK		0x60000000
#define HAND_ABOVE_MASK		0x10000000	/* Draw arm and clasp after dancer so it appears to be above the head */
#define HAND_FRONT_MASK		0x08000000	/* Position the shoulder to the front of the body rather than in the middle */
#define HAND_BACK_MASK		0x04000000	/* Position the shoulder to the back of the body rather than in the middle */
#define HAND_BALLROOM_MASK	0x02000000	/* Indicates a hand clasp in ballroom position (arms meeting a body length out from the shoulders) */
#define HAND_OUT_MASK		0x01000000	
#define HAND_COPY_MASK		0x7f000000

#define HAND_NOTOUT_MASK	0x200000	/* Do not join hands if the couple we want to clasp with is not active (out at top or bottom) */

#define HAND_PERSON_MASK	0x1fffff	/* Other person's number */
#define HAND_MINORSET_MASK	0x1f0000	/* If non-zero, then hand clasp is to the equivalent dancer in a different minor set (ie. in long lines you join hands with people in the minor set before and after the current one) */
#define HAND_MINORSET_UP	0x100000	/* If set, then clasp with someone in the set nearer the band */
						/* If not set, then clasp with someone in set further from the band */
#define HAND_MINORSET_OFFSET	0xf0000		/* indicates number of sets from current one (careful around edges of the set) */
#define HAND_MINORSET_SHIFT	16
						/* Some becket dances that start with a long lines slice left need this */
#define HAND_INDIVIDUAL_MASK	0xffff
#define HAND_STAR		0xffff		/* Indicates hand is not clasped by another person but goes to the center of a star. (3 or 5 person stars can't be done with a normal clasp) */

#define HAND_MILLIBARS_UNSET	0xffff
    unsigned short drop_right_millibars;	/* Time when we should drop hands (note, if no drop then should be UNSET) */
    unsigned short drop_left_millibars;
    unsigned int join_right_hand;		/* hand clasp to a person number ored with hand mask of other person, -1 => no clasp */
    unsigned int join_left_hand;
    unsigned short join_right_millibars;
    unsigned short join_left_millibars;
    unsigned long congruent;	/* Mask of all people who do the same movement (after rotation, translation, etc.) */
    Position star_center;			/* If a hand clasp==HAND_STAR */
    ValChange *levitation;	/* how far toward horizontal the person should be drawn (values between 0 and 100, 0 being vertical, 100 being horizontal) */
    ValChange *outness;		/* how far out hands should be clasped (if HAND_OUT_MASK is set). 0% means hands held out in front (in direction facing), 45 means hands held out in front and to the sides at a 45 degree angle. 90 probably won't work */
				/*  currently left and right hands will be a the same outness */
    RThetaChange *rightHand;	/* Position of the right hand (and sword hilt) in sword dancing */
				/* this is actually an r,theta value (x=r, theta=y) the center of the circle is the right shoulder with theta==0 heading in the direction the dancer faces */
			        /* Which means the coordinates need to be rotated by the dancer's orientation and then translated by the dancer's shoulder's position */
			        /* an r==x of 1 means a full arm lengh, say about 1.5* torso sizes */
    RThetaChange *swordPoint;	/* Position of the sword point */
				/* an r=x value of 1 means a full sword length say about 3 torso sizes */
    RThetaChange *leftHand;	/* Position of the left hand when not holding a sword point. Used to show swinging arms? */
    short join_left_to_point;	
    unsigned short start_honour, end_honour;
    Block *ifblock;
    unsigned int dd_setup:1;	/* This figureSegment is part of set up for a danceDescription (rather than the main body of action) */
    unsigned int dd_cleanup:1;	/* part of the final cleanup (and hence may be modified) */
#ifdef DEBUG
    unsigned int complained_about_rotation: 1;
    unsigned int checked_rotation_continuous: 1;
    unsigned short lineno;
    unsigned short copy_lineno;
#endif
} FigureSegment;

struct transformation {
    float xoff, yoff;
    /* Rotation is counter-clockwise */
    float rotateby, center_x, center_y;		/* Rotation in degrees!!!! */
    float flip_xcenter;
    float flip_ycenter;
    int dohflip, dovflip;
    double xscale, yscale;
    double xcenter_old, ycenter_old;
    double xcenter_new, ycenter_new;
    double timescale;
    int barscale;	/* Number of millibars desired for the enclosed block */
	/* this avoids rounding errors that pop up when we want to divide by 3 */
    long unmapped_hands;
    int hand_offset, hand_mod;
    int full_remap;
    signed char handmap[100];
    float x_slide, y_slide;
    int repeat;
};

#define MUSICNAMELEN	12
typedef struct callList {
    char *callName;
    char *audioFilename;
    char *longaudioFilename;
    char musicName[MUSICNAMELEN];	/* A1, A2, B1, etc. */
    int millibars;			/* number of bars to do this call */
    int actual_millibars;		/* In Cupid's Garden most of the dance is in 3 counts per bar, but a bit is in 2, this makes fitting calls to music tricky as the length of a bar is not constant */
	/* Also if we set actual_millibars to 0 then don't display the call name */
	/*  (useful where we want audio calls to be different from written ones) */
    int audio_millibars;		/* The audio may apply to several subsiquent calls */
    int offset_millisecs;		/* If the audio is too long, we may want to start it early */
#define CLAP_DONE		0xffff
    unsigned short *claplist_millibars;	/* An array of when to clap, terminated by a CLAP_DONE entry. Will be NULL if no claps */
    short honour_start, honour_end;
    unsigned int part_mask;
    unsigned int snap_not_clap: 1;
    unsigned int stamp_not_clap: 1;
} CallList;

typedef struct bblist {
    BB bb;
    int millibars;	/* take this long in the dance to change the bb to the value above */
    int extra_frames;	/* or take this many extra frames (but don't progress the dance */
	/* extra frames is not currently supported. It is parsed and ignored */
    unsigned int fixed: 1;	/* bb does not change from previous value for this many millibars */
    unsigned int automatic: 1;	/* calculate the bb based on dancer's current positions */
				/* Note that if a millibars is specified then */
			        /*  when the bb finally is active the dance will */
			        /*  have moved on and may not be appropriate */
    struct bblist *next;
} BBList;

enum role {		/* couple role, not individual, further specified by sex */
    r_1s,
    r_2s,
    r_3s,
    r_4s,
    r_5s,
    r_6s,
    r_7s,
    r_8s,
    r_9s,
    r_10s,
    r_11s,
    r_12s,
    r_13s,
    r_14s,
    r_15s,
    r_16s,
    r_17s,
    r_18s,
    r_19s,
    r_20s,
    r_21s,
    r_22s,
    r_23s,
    r_24s,
    r_25s,
    r_26s,
    r_27s,
    r_28s,
    r_29s,
    r_30s,
    r_1sleft,		/* four face four, tempest */
    r_1sright,
    r_2sleft,
    r_2sright,
    r_outAtTop,
    r_outAtBottom,
    r_outAtTop1of2,
    r_outAtTop2of2,
    r_outAtBottom1of2,
    r_outAtBottom2of2,
    r_outAtTop1of3,
    r_outAtTop2of3,
    r_outAtTop3of3,
    r_outAtBottom1of3,
    r_outAtBottom2of3,
    r_outAtBottom3of3,
    r_outAtTopLeft,	/* four face four, tempest */
    r_outAtTopRight,
    r_outAtBottomLeft,
    r_outAtBottomRight,
	/* I do this with conditions now */
/*  r_top1s,	*/
/*  r_top2s,	*/
/*  r_top3s,	*/
/*  r_bottom1s, */
/*  r_bottom2s, */
/*  r_bottom3s, */
    r_outAtBottom_alt,
    r_waiting,		/* Used for couples not yet active in an old style progression dance or a scottish dance */
    r_waiting_left,	/* Same, but for a 4 face 4/tempest dance */
    r_waiting_right,
    r_1s_progression,	/* Used in scottish on the second time through the dance */
    r_3s_progression,	/*  to get the 1s and 3s to switch places. Only for dances */
			/*  where we can't do it automagically (if the threes */
			/*  have something to do in the first few bars) */
    r_4s_progression,	/* Used in scottish on the third time through if we */
			/*  couldn't swith the 1s+3s in 2nd iteration, then */
			/*  we must swith the 3s+4s at the start of the third */
			/*  (presumably the standard progression doesn't work)*/
			/*  will be used with 3s_progression (which has a */
			/*  meaning when used with 4s than with 1s) */
    r_last_unused
};

enum rolemask {
    m_1s = 1,
    m_2s = 2,
    m_3s = 4,
    m_4s = 8,
    m_5s = 0x10,
    m_6s = 0x20,
    m_7s = 0x40,
    m_8s = 0x80
};

enum sex { s_unknown= -1, s_male, s_female, s_left, s_center, s_right, sex_max, sex_first=s_male };

typedef struct person {
    enum sex sex;
    int couple_number;		/* sets color */
    enum role effective_role;	/* sets current dance role */
    enum role display_role;	/* set the way we display the role, for hacks where we use an n couple longways set to represent a duple minor set when progression is too hard to do right */
    enum sex effective_sex;	/* In HalfeHannikin dancers can dance a role with a different sex */
    int current_pos;		/* How far down the set was the couple at the start of the minorset */
/* In a contra dance, there are the normal dance steps, but you are out when *
 *  you reach the top or bottom, and then switch roles. Also there may be    *
 *  oddities if the dance wants you to intereact with previous/next neighbors*
 *  (might need to reach around the set to your partner if you are top/bottom*
 *  couple). Problems also when progression happens in the middle of a dance.*
 *  Things are even worse in a triple minor ECD.
 */
/* So we need a description of what the normal 1s do, the normal 2s, what    *
 *  happens to the couple out at the top, out at the bottom, and maybe what  *
 *  the top couple does if there is no couple at the top, possibly even what *
 *  the 2s in the top set have to do to avoid edge-effects, etc.             *
 */
    Position actualFigureStartPos;	/* In Scottish/TheGlasgowHighlanders the second chord moves people in very weird ways and they aren't at figures->moves[0].endPoint when they start the dance, this shows where the are */
    Block figures;
    FigureSegment *current;

    int millibars_start_of_current;
    float orientation_start_of_current;
    unsigned int dropped_left_in_current: 1;
    unsigned int dropped_right_in_current: 1;
    unsigned int joined_left_in_current: 1;
    unsigned int joined_right_in_current: 1;

    unsigned int started: 1;		/* In scottish country dancing couples*/
	/* down the set don't do anything until the dancing gets down to them */
	/* the top non-dancing couple can be "Out at bottom" and might interact*/
	/* with the minor set above, but other couples below that are just */
	/* "waiting". */
	/* This will play merry hell with my conditions code, but so far no scottish dances have needed conditions */

    Position now;
    float now_orientation;
    unsigned int now_hand_left, now_hand_right;
    Position now_star_center;
    float now_sicilian_theta;
    float now_sicilian_radius;
    float now_sicilian_couple_theta;
    int now_couple_x;
    ValPoints levitation;	/* how far toward horizontal the person should be drawn (values between 0 and 100, 0 being vertical, 100 being horizontal) */
    ValPoints outness;		/* how far out hands should be clasped (if HAND_OUT_MASK is set). 0% means hands held out in front (in direction facing), 45 means hands held out in front and to the sides at a 45 degree angle. 90 probably won't work */
				/*  currently left and right hands will be a the same outness */
    RThetaPoints rightHand;	/* Location of the right hand (and sword hilt) in the coordinate system of the dancer */
    RThetaPoints swordPoint;	/* Ditto for the sword point */
    RThetaPoints leftHand;
    short now_left_hand_point;	/* -1 means not holding a point, otherwise the number of the dancer whose sword is held */
    float now_honour; 		/* Info on honouring */
    short mapped_to;
    short ticked;
    unsigned short join_right_without_drop;
    unsigned short join_left_without_drop;
    struct _GdkPixbuf *face;
    float facescale;
    unsigned char face_hide_normal;

    /* These two are used by danceDescriptions */
    int old_move_cnt;
    Block *curBlock;
} Person;

enum startingPosition {
    sp_squaredSet,
    sp_rect6Set,
    sp_facingCouples,
    sp_facingCouplesBecket,
    sp_facingPeople,
    sp_couple,
    sp_singleton,
    sp_rightHandWave,
    sp_leftHandWave,
    sp_2rightHandWave,
    sp_2leftHandWave,
    sp_dupleMinor,
    sp_becket,
    sp_becketCCW,
    sp_shortWaves,
    sp_dupleMinorProgressed,
    sp_threeFaceThree,
    sp_fourFaceFour,
    sp_tempest,
    sp_quadrupleMinor,
    sp_quadrupleMinorBecket,
    sp_tripleMinor,
    sp_2Couple,
    sp_3Couple,
    sp_4Couple,
    sp_5Couple,
    sp_6Couple,
    sp_7Couple,
    sp_8Couple,

    sp_3CplCircle,
    /* A 4 couple circle is a square */
    sp_5CplCircle,
    sp_6CplCircle,
    sp_7CplCircle,

    sp_square3,

    sp_scottishDupleMinor,
    sp_scottishTripleMinor,

    sp_circularMonople,
    sp_trioCircularMonople,
    sp_rotatedTripleMinor,

    sp_custom,
    sp_custom3
};

/* When adding elements here, change the anchors array in list.c */
enum danceStyle {
    ds_english,
    ds_contredanse,
    ds_oscd,
    ds_acd,
    ds_cotillion,
    ds_quadrille,
    ds_scottish,
    ds_square,
    ds_contra,
    ds_appalachian,
    ds_longsword,

    ds_mine,

    ds_unspecified = -1
};

enum subStyle {
    ss_traditional,
    ss_basic1,
    ss_basic2,
    ss_mainstream,
    ss_plus,
    ss_advanced1,
    ss_advanced2,
    ss_challenge1,
    ss_challenge2,
    ss_challenge3a,
    ss_challenge3b,

    ss_unspecified = -1
};

typedef struct choreography {
    struct dance *figure;
    int active;		/* 0=> no one, 1=>1s, 4=>4s */
    int part;		/* 0=> default, etc. */
    int current_ms;	/* Reset dance->current_minorset for oldstyle progression */
    unsigned int no_one_out_at_top: 1;
    unsigned int first_set: 1;
    unsigned int clockwise: 1;
    float time_scale;
} Choreography;

typedef struct musicSegment {
    char *name;
    enum interpolation_type { it_copy, it_fit, it_fit2set, it_fit2lastset } type;
    /* it_copy means to use the segment at the same rate it is supposed to play */
    /* it_fit means to fit the start/end times into something that is the specified number of millibars */
    /* it_fit2set can only be used in intro and ending and means
     *  to find the average interpolation rate specified in the body or minorset
     *  and then apply that to stretch or shrink this segment
     */
    /* it_fit2lastset can only be used in ending and means use the interpolation rate of the last minorset */
    int start, end;	/* Time in milli seconds from start of music file */
    int duration_millibars;	/* (specified) */
    unsigned int copy: 1;	/* duration_millibars not specified, duration = start-end */
    unsigned int repeat_as_needed: 1;	/* If the tune is 16 bars but the dance 32... (Jamaica) */
    unsigned int autogen: 1;	/* used only by middlesets to indicate this segment was guessed at, not specified by user */

    int fadein_duration;	/* Milliseconds, specified, optional, default to 0 (no fade in) */
    float fadein_initial_level;	/* specified, optional, default to 0 (silent) */

    struct musicSegment *next;
} MusicSegment;

typedef struct musicDescription {
    char *filename;		/* For the music */
    int start_millibars;	/* Delay playing music this long (used for choreographies) */
    MusicSegment *intro;
    MusicSegment *honour;	/* For Scottish music where there is already an honour chord */
    MusicSegment *body;		/* Only one of body or _minorset*/
    int body_repeats;
    MusicSegment *minorset;	/* should be set. The first plays until done, the second can be repeated for each minor set */
    MusicSegment *middlesets;
    int middleset_count;
    MusicSegment *lastminorset;	/* if this is specified then it will be played for the final minor set of a dance */
    MusicSegment *ending;
    float amplify;
    char *name;
    char *danceName;
    char *mdId;
    char *composer;
    char *performers;
    char *publication;
    char *album;
    int year_written;
    int year_performed;
    enum danceStyle style;
    short counts_per_bar;
    short music_type;	/* Jig, waltz, etc. */
    char *key;
#define MINORSET_UNSPECIFIED	-1
    int show_minorset;
    int desired_repetitions;
    char *titleAudioFilename;
    char *html_notes;		/* Stored with entities as enties (you'll find &amp; in here but not &) */
    char *cdImage;
    char *cdNotes;	/* Url */
    char *permission;

    int minorset_millibars;	/* calculated, or supplied by the set-bounds tag */
    long intro_start, intro_end;
    long final_end;
    int set_count;
    long *set_ends;
    int tunecnt_per_minorset;	/* Jamaica has a 16 bar tune and a 32 bar minorset, so we need to play the tune twice per minorset */
} MusicDescription;

typedef struct faceImage {
    char *facename;
    int person;
    enum sex sex;
    float facescale;
    unsigned int hide_normal: 1;
    struct _GdkPixbuf *image;
} FaceImage;

enum danceFigure {
    df_meanwhile,
    df_concat,		/* Treat multiple commands as one (for a meanwhile) */
    df_if,
    df_explicit,	/* bunch of linetos and such */
    df_wait,		/* Used in a meanwhile where one subgroup of dancers starts after another (long cast+lead for instance) */

    df_circle,		/* 3,4,6,8... clockwise/counter single-file/face-in/face out hands/none full/half/three quarters */
    df_handturn,	/* right/left/two hand/no hand (gypsy)  arm?  full/half/once and a half/three quarters/twice */
    df_star,		/* right/left  full/half */
    df_siding,		/* right/left  full/half */
    df_sharpSiding,	/* right/left  full/half */
    df_change,		/* partner/neighbor/corner  left/right  with hands */
    df_backToBack,	/* partner/neighbor/corner  left/right  three-quarters/full */
    df_circularHey,	/* with-hands  start-right/left  partner/neighbor  number-of-changes */
    df_set,		/* start-right/left count */
    df_honour_,
    df_turnsingle,	/* left/right */
    df_cast,		/* long/short up/down/left/right how-far */
    df_cast_lead,	/* who is active (casts) */
    df_cast_then_lead,	/* up/down how-far */
    df_lead_then_cast,	/* up/down how-far */
    df_figure8,		/* which-person-goes-first double half/full */

    df_last
};

typedef struct danceDescription {
    enum danceFigure figure;
    long personMask;			/* Which people are involved */
    long activesMask;			/* Which people are active (cast+lead, these cast) */
    int count;				/* How many times to do it */
    int countDenom;			/* Devided by this. */

    enum who { who_default, who_partner, who_neighbor, who_corner } who;

    unsigned int isCounterClockwise: 1;
    unsigned int isDoubleFigure8: 1;
    unsigned int isArming: 1;
    unsigned int startByLeft: 1;
    enum { face_default, face_in, face_out, face_forward, face_backward } facing;
    enum hands { hand_default, hand_right, hand_left, hand_both, hand_none } takeHands;
    enum dir { dir_default, dir_right, dir_left, dir_up, dir_down, dir_cloverlear } dir;
    int howFar;			/* How many positions to lead (from 1s to 2s is 1 place) */
    int howFarDenom;
    int figure8Starter;		/* Usually this is the woman, but occasionally it will be the man, or if two men/women involved then which one */

    int millibars;
    char *callName;		/* Can sometimes generate this by default */
    char *callAudioFile;	/* Ditto */

    Condition *condition;
    struct danceDescription *kids;	/* for df_concat, df_meanwhile, df_if */
    struct danceDescription *siblings;	/* for something inside df_concat, df_meanwhile (df_if only supports one child which could be a concat) */
    struct danceDescription *elsebranch;/* for df_if */

    struct figureSegment *moves;	/* only for df_explicit */
    int move_cnt, move_max;
} DanceDescription;

typedef struct dance {
    unsigned int is_figure: 1;
    unsigned int is_component: 1;
    unsigned int is_comparison: 1;
    unsigned int show_minorset: 1;
    unsigned int show_figure_titles: 1;
    unsigned int stroke_text_on_background: 1;
    unsigned int use_long_s: 2;	/* 0=> no, 1=> yes, 2=>guess (yes before 1803) */
    char *name;			/* Sides Face, Grand Square */
    char *altName;
    char *sortName;
    char *commonName;		/* used to link a bunch of dances together as */
	/* coming from the same source. if NULL defaults to sortName */
	/* There should be an altName to match the commonName */
    char *callGroup;		/* Grand Square */
    enum danceStyle style;
    enum subStyle substyle;	/* Basic 1, Basic 2, Mainstream,... */
    char *author;
    char *interpreter;
    char *source;
    char *animator;
    char *license;
    char *key;
    int difficulty_level;
    int year_written;
    int year_interpreted;
    char *animation_date;
    char *music_name;
    char *music_author;
    char *tags;
    char *rscds_precis;
    char *titleAudioFilename;
    char *url;
    char *url10;
    char *url11;
    char *source_url;
    char *sicilian_url;
    char *orig_url;
    char *la_url;		/* Live/animation mixed video */
    /* If there is more than one live url then delimit them with "|", which is considered an "unsafe" character that is not permitted in a valid url */
    /*  (the labels are short descriptive terms say where the corresponding url comes from, they are also delimited by "|" */
    char *live_urls;
    char *live_labels;
    char *publication;
    char *interpreterPublication;
    char *la_caller;		/* Live/animation caller */
    char *la_musicians;		/* Live/animation musicians */
    char *la_dancers;		/* Live/animation dancers */
    enum startingPosition formation;
    unsigned int improper_mask;		/* a mask of all the couples who are improper. Duple improper would be 1, indecent 2, etc. */
    enum becket_style { bs_none, bs_cw, bs_ccw } becket_style;		/* No becket, clockwise, or counter-clockwise. Used for Scottish/TheGlasgowHighlanders */
    int units;
	    /* A progression value of 0 is meaningful, see Cuckulds, a duple minor dance that doesn't progress. But the default should be 1 */
    int progression;
    int minorset_spacing;	/* Distance from the 1s in one minorset to the 1s in the next (not from 2s to 1s) */
				/* 0 is a default value which will be twice the inter-couple spacing for a duple minor or three times it for a triple */
    char *notes;		/* description of figure, etc. */
    char *html_notes;		/* Text to go into my list program. Expected to have html markup in it (ie. it's got entities. Don't add them) */
    enum band bandPos;
    char *background_file;
    char *title_background_file;
    char *title_font;		/* Font name to use for titling */
    int text_color;
    enum startingPosition original_formation;	/* What the devisor intended for the formation, rather than what the interpreter used. Ie. lots of triple minors became 3 couple or duple minor, this field would still be triple */
    unsigned int original_improper;
    int original_progression;
    int original_parts;
    Position **grid_pos;	/* NULL terminated list of pointers to positions where grid marks should show */

    BBList *bbs;
    int millibars_start_of_bbcurrent;	/* when the current BBs started */
    BBList *currentBB;
    BB bbStartOfCurrent;

    int people;			/* How many people needed for a figure (usually in couples, but not always. U-turn back, turn single both need just 1 person (number of dancers allocated) */
    int couples;		/* How many couples to display for a dance */
    int role_cnt;		/* How many roles need to be described (each role will have a m+f so this number should always be divisible by 2) */
    long roleMask;
    int call_cnt;
    int part_cnt;
    int desired_repetitions;	/* minorset_count, minorset_cnt, minor_set_cnt */
    int desired_couple_cnt;
    Person *roles;		/* These are static */
    Person *dancers;		/* these will move around and may switch roles*/
    int counts_per_min;
    int counts_per_bar;
    int millibars_start_of_current;	/* when the current call started */
    CallList *calls;
    CallList *current;
    /*char currentMusicName[MUSICNAMELEN]; */
    int current_part;
    int start_first_minor_set;

    unsigned int last_minor_set :1;
    unsigned int first_minor_set :1;

    MusicDescription music;
    char *include_md;		/* filename from which to read a description */
    char *music_description_ids;

    Person **orderedList;
    int face_cnt, face_max;
    struct faceImage *faceImages;
#if 0
    char **facenames;
    float *facescales;
    unsigned char *face_hide_normals;
#endif

    struct dance **components;
    int comp_cnt;
    Choreography *sequence;
    int choreo_cnt;
    int choreo_pos;

    int description_cnt;
    DanceDescription *description;

	/* Info on honouring */
    float honour;
    enum { honour_default, honour_doit, honour_dont } do_honour, do_honour_end;

    /* The 1s will sometimes interact with a couple outside the set. When */
    /*  displaying only the minorset this looks odd as the other couple will */
    /*  not normally be visible. So these allow us to start displaying another*/
    /*  couple at the appropriate time. Totally ignored when displaying the */
    /*  full set */
    int minorset1_bar;		/* Initialized to -1 */
    int minorset1_dont_show_couples_above_me;
    int minorset1_end_bar;
    unsigned int minorset1_same_bb: 1;

    /* Similar idea for butterfly whirl effects */
    int whirl_bar;
    int whirl_end_bar;

    unsigned int ticked: 1;	/* General useful bit for short term things */

    /* Runtime data for a sicilian circle format */
    unsigned int sicilian: 1;
    unsigned int sicilianScale: 1;
    unsigned int verbose: 1;
    double sicilian_radius;
    Position sicilian_center;
    double sicilian_midline;	/* The y value for the line that runs parallel to the major set and midway down the center of the set */
    double sicilian_circumference;

    /* Sigh. Some custom circle dances don't end up with couples where there were couples before */
    /*  but out of phase by half a couple spacing. Or perhaps a third? */
    /* To fix that up we need to know the center of the circle, and then */
    /*  on alternate sets rotate by 360/(2*<number of couples>) (if they are offset by half couple spacing ) */
    Position progression_center;
    int progression_mod;
    int progression_offset;
    int current_minorset;
    unsigned int ignore_sex: 1;
    unsigned int old_style_progression: 1;
/*    unsigned short waiting_couples_top, waiting_couples_bottom;*/
} Dance, Figure;

typedef struct comparison /* : Dance */ {
    Dance dance;

    struct dances {
	char *filename;
	Dance *d;
	char *args;
	unsigned int sicilian: 2;
    } dances[2];
    char *display_id;
    char *sourceImage;
    char *imageCopyright; /* Image copyright © 2019 Scot Pfitzinger, released under a Creative Commons Attribution-NonCommercial license &#10;http://playforddances.com/dances-2-3/st-margarets-hill/ */
    unsigned int stacked_vertically: 1;
} Comparison;

typedef struct figureLib {
    enum danceStyle style;
    enum subStyle substyle;
    Figure **figures;
} FigureLib;

struct danceFigureTable {
    enum danceFigure figure;
    char *name;
    void (*doIt)(Dance *,DanceDescription *dd);
    int dsMask;		/* Which dance styles use this figure */
};

struct setProgression {
    char progression[32];	/* where does each couple end up at the end of once through the dance progression[0] is where the 1s go, etc. */
    char fprogression[32];	/* if the women have a different pattern than the men */
    char progression2[32];	/* if part 2 has a different pattern than part 1 */
    char fprogression2[32];	/* if part 2 women have a different pattern than part 1 */
    unsigned int impropriety: 1;	/* man gets sent to a woman's spot and vice versa */
    unsigned int women_differ: 1;	/* mixer */
    unsigned int part2_differs: 1;	/* wierd */
    unsigned int identity: 1;		/* no progression */
    unsigned int error: 1;
    short int couple_cnt;
};

extern struct danceFigureTable figureTable[];
    
    /* danceInit.c */
enum libraries {
    lib_basic1,
    lib_basic2,
    lib_mainstream,
    lib_plus,
    lib_advanced1,
    lib_advanced2,
    lib_challenge1,
    lib_challenge2,
    lib_challenge3a,
    lib_challenge3b,
    lib_contra,
    lib_ecd
};
extern int figureLibariesOpened;	/* Bit mask of libraries we tried to load */
extern FigureLib *figureLibraries[];	/* Libraries we did load */
void danceInit(void);
    /* danceEnums.c */
extern char *styleNames[];
extern char *substyleNames[];
extern char *startFormationNames[];
extern char *bandNames[];
extern char  sexChars[];
extern char *sexNames[];
extern char *roleNames[];
extern int role2couple[];
extern char *becketStyle[];
extern char *commandNames[];
extern char *conditionNames[];
extern char *orientationNames[];
extern char *difficultyLevelNames[];
extern char *musicTypes[];
extern char *musicTypesShort[];
extern char *libNames[];
extern int danceMatchEnum(char **list,char *instance);
struct maskMap {
    char *name;
    unsigned int mask;
};
extern struct maskMap handMaskMap[];
extern unsigned int danceMatchMask(struct maskMap *map, char *instance);
extern unsigned int danceRoleList(char **list, char *instance);
    /* danceOutput.c */
extern void danceOutputHeader(FILE *out, enum danceStyle style, enum subStyle substyle );
extern void danceOutputTrailer(FILE *out);
extern void entityOutput(FILE *out, char *str, int donl );
extern int danceOutputFigure(const char *filename, Dance *dance);
extern int danceOutputDebugFigure(const char *filename, Dance *dance);
extern int danceOutputLibrary(const char *filename, FigureLib *lib);
extern int danceOutputLibraryInfo(const char *filename, FigureLib *lib);
extern void danceOutputAddDanceToMusicDB(FILE *out,Dance *dance, char *filename );
extern void danceOutputAddDanceToDB(FILE *out,Dance *dance, char *filename );
extern void danceOutputMusicDescription(FILE *out, MusicDescription *md);
    /* danceInput.c */
extern void danceBlockTransform(Block *b,struct transformation *trans);
	/* Load a single Figure (or Dance) from a file. If the file contains more */
	/*  than one then invoke a callback to pick one (if callback not*/
	/*  specified, return first figure/dance) */
extern Figure *danceLoadFigure(const char *filename, int (*chooseOne)(void *data, char **names,int cnt,int is_dance), void *data);
	/* Load every figure/dance in a file */
extern FigureLib *danceLoadLibrary(const char *filename);
extern MusicDescription *danceLoadMusicDescription(const char *filename);
extern char *danceLoaderError(void);
extern void initFigureSegment(FigureSegment *fs);
    /* danceNew.c */
extern long danceRoleMask(enum startingPosition,int numPeople);
extern Figure *danceNewFigure(enum danceStyle style,enum subStyle substyle,const char *figurename,const char *figuregroup,
			enum startingPosition starting,unsigned int improper_mask,
			int numPeople);
extern void danceResetToNew(Dance *dance,int numPeople);
extern Dance *danceNewDance(enum danceStyle style,enum subStyle substyle,const char *dancename,
			const char *author,const char *music,int year,
			const char *adaptor,int yearadapted,
			enum startingPosition starting,unsigned int improper_mask,
			int progression/* = 1 */,int numPeople/* Only for custom */);
extern void danceRebuildFromDescription(Dance *dance);
    /* danceUtils.c */
extern void blockFree(Block *);
extern void conditionFree(Condition *);
extern void figureLibFree(FigureLib *);
extern void mdFreeContents(MusicDescription *md);
extern void mdFree(MusicDescription *md);
extern void figureFree(Figure *);
extern void figureFreeCalls(Figure *figure);
extern void figureFreeRoles(Figure *figure);
extern void peopleFreeContents(Person *p);
extern Condition *conditionCopy(Condition *c);
extern Block *blockCopy(Block *b);
extern int blockCountMillibars(Block *b);
extern ValChange *valueChangeCopy(ValChange *input);
extern RThetaChange *rThetaChangeCopy(RThetaChange *input);
extern void mdCopyContents(MusicDescription *to,MusicDescription *from);
extern char *danceLibDir(void);
extern void splineBisect(FigureSegment *cs,FigureSegment split[2],double t);
extern int danceIsCircle(Dance *dance);
extern struct setProgression *danceSetProgression(Dance *dance, struct setProgression *sp);
extern int danceHasActualBars(Dance *dance);
extern int danceHasProgression(Dance *dance);
extern int danceNeedsImproperCrossover(Dance *dance);
extern void danceForceImproper(Dance *dance);
extern int danceIsPublicDomain( Dance *dance );
extern int danceHasPublicDomainLicense( Dance *dance );
extern char *danceLicenseText( Dance *dance, char *buffer, int blen );
extern int danceInCopyright( Dance *dance, int curYear );
extern int danceAuthorNotDevisor(Dance *dance);
extern int danceHasTag(Dance *dance, char *tagname);
extern char *danceMusicType(Dance *dance, int shortForm);
extern char *danceScottishDanceType(Dance *dance);
extern int danceScottishRepetitions(Dance *dance);
extern char *danceScottishPrecis(char *buffer, int blen, Dance *dance);


/* Make polynomials from control points */
extern void splineMake(FigureSegment *cs, Position *lastPoint);
/* Make control points from polynomials */
extern void splineCpsFromPoly(FigureSegment *cs);
extern Dance *danceSaveState(Dance *dance);
extern void danceResetState(Dance *dance,Dance *starting_state);
extern char *romanNumeral(char *buf, int buflen, int val, int useLC);
extern char *partAndMusic(char *buf,int blen, CallList *call);
extern char *strip(char *name);
extern char *removeLongs(char *buffer, int blen, const char *_name,int doquotes);
extern char *makeSortName(char *buffer,int size,char *name,char *sortName);
extern char *makeMusicDescriptionID(char *buffer,int size, char *filename);
extern char *addEntities(char *buffer, int blen, const char *name, int do_lt);
extern void dumpCalls(FILE *output,Dance *dance,char *buffer,int sizebuf);
    /* danceRun.c */
extern int danceNeedsCoupleCount(Dance *dance);
extern int danceMinorSetSize(Dance *dance);
extern int danceCoupleSize(Dance *dance);
extern void danceXScale(Dance *dance, double xscale);
extern int danceMinorSetMillibarCount(Dance *dance);
extern int danceMinorSetActualMillibarCount(Dance *dance);
extern int danceClaspsOutsideMinorSet( Dance *dance );
extern int danceCoupleSpacing(Dance *dance);
extern int danceMinorSetSpacing(Dance *dance);
extern int danceHasReset(Dance *dance);
extern int danceHasLastCondition(Dance *dance);
extern int danceRoleIndex(Dance *dance, enum role r);
extern Person *danceFindRole(Dance *dance, enum role role,enum sex sex);
extern void danceReset(Dance *dance,int frame,int frames_per_bar);
extern void danceFixupFormation(Dance *dance,enum startingPosition formation,Dance *newfigure);
extern void danceForceNoOneOutAtTop(Dance *dance);
extern void danceStart(Dance *dance,int couples,int out_at_top);
extern CallList *danceFindFirstCallInCurrentPart(CallList *cl, int cnt, int mask);
extern CallList *danceCallNext(Dance *dance);
enum dancecondition {
    dc_continue,
    dc_minorSetEnded,
    dc_finished,

    dc_unspecified
};
extern enum dancecondition danceNextFrame(Dance *dance,int frame,int frames_per_bar);
extern void danceCleanup(Dance *dance);
extern void danceFindBB(Dance *dance, BB *bb);		/* Find bb for the whole dance */
extern void danceFindMinorSetBB(Dance *dance, BB *bb);	/* Find bb for the first minor set going once through the dance */
extern void danceFindCurrentBB(Dance *dance, BB *bb);	/* Find bb as dancers currently stand in the dance, not thinking of future or past movements */
    /* danceSequence.c */
extern int danceAdvanceChoreography(Dance *dance);
extern int danceAllComponentsSameBars(Dance *dance);
    /* danceVideo.c */
struct video_options {
    int width, height;
    int frames_per_bar, frames_per_sec;
    float usable_fraction;	/* How much of the screen to use */
    int audio_sample_rate;	/* output audio rate */

    int couples;		/* How many couples to display */
    int minor_set_count;	/* How many times to run through the minorset dance */
    int out_at_top;		/* In the American Husband there are cases where we want to start with a couple out at top */
    long flags;
    int past_path_millibars;	/* when drawing motion trace, how many bars into the past to draw */
    int future_path_millibars;
    int initial_part;
    char *background;
    enum callPos { cp_unspecified, cp_roomiest, cp_left, cp_under } callPos;
    int gifOutput;
    Rect crop;
    MusicDescription *music;
    int vbit_rate;
    float music_amplify;
    int titleframes, musictitleframes;
};
/* extern void danceRender(DanceView *dv,int frame);*/
extern void danceMakeVideo(Dance *dance,struct video_options *options,
	char *filename, char *framedir);
extern void danceMakeAudio(Dance *dance,struct video_options *options, char *filename);
/* danceJSOutput.c */
extern int danceJSOutputDance(const char *filename, Dance *dance);
/* danceAV.c */
extern void danceCheckCallLength(Dance *d );
#endif
